From 7c2b5b614f63611e8cfc28cbdfb7977f3054ef2e Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 25 Oct 2020 19:13:09 +0100 Subject: [PATCH 001/223] NEW: preload product description on selection for customer propal/order/invoice --- htdocs/comm/propal/card.php | 7 +++- htdocs/commande/card.php | 5 +++ htdocs/compta/facture/card.php | 5 +++ htdocs/contrat/card.php | 6 ++++ htdocs/core/tpl/objectline_create.tpl.php | 40 ++++++++++++++++------- htdocs/fourn/facture/card.php | 5 +++ htdocs/product/ajax/products.php | 35 ++++++++++++++++++-- 7 files changed, 87 insertions(+), 16 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 4a4cf3c37dd..3a9fc38fbaf 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -995,11 +995,16 @@ if (empty($reshook)) $outputlangs->setDefaultLang($newlang); } - $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description; + $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description; } else { $desc = $prod->description; } + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc) { + $product_desc=''; + } + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; else $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 596fe4e94bc..585b85def0b 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -854,6 +854,11 @@ if (empty($reshook)) $desc = $prod->description; } + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc) { + $product_desc=''; + } + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; else $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 94f817114aa..6b56d39ba3f 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2068,6 +2068,11 @@ if (empty($reshook)) $desc = $prod->description; } + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc) { + $product_desc=''; + } + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; else $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 64b3275379a..f3dc0355331 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -499,6 +499,12 @@ if (empty($reshook)) } $desc = $prod->description; + + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc) { + $product_desc=''; + } + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; else $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index d177ce7637c..ec73bf9725b 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -514,13 +514,13 @@ if (!empty($usemargins) && $user->rights->margins->creer) global->DISPLAY_MARGIN_RATES)) { ?> $("input[name='np_marginRate']:first").blur(function(e) { - return checkFreeLine(e, "np_marginRate"); + return checkFreeLine(e, "np_marginRate"); }); global->DISPLAY_MARK_RATES)) { ?> $("input[name='np_markRate']:first").blur(function(e) { - return checkFreeLine(e, "np_markRate"); + return checkFreeLine(e, "np_markRate"); }); rights->margins->creer) var rate = $("input[name='"+npRate+"']:first"); if (rate.val() == '') - return true; + return true; if (! $.isNumeric(rate.val().replace(',','.'))) { - alert('trans("rateMustBeNumeric")); ?>'); - e.stopPropagation(); - setTimeout(function () { rate.focus() }, 50); - return false; + alert('trans("rateMustBeNumeric")); ?>'); + e.stopPropagation(); + setTimeout(function () { rate.focus() }, 50); + return false; } if (npRate == "np_markRate" && rate.val() >= 100) { - alert('trans("markRateShouldBeLesserThan100")); ?>'); - e.stopPropagation(); - setTimeout(function () { rate.focus() }, 50); - return false; + alert('trans("markRateShouldBeLesserThan100")); ?>'); + e.stopPropagation(); + setTimeout(function () { rate.focus() }, 50); + return false; } var price = 0; @@ -659,7 +659,6 @@ if (!empty($usemargins) && $user->rights->margins->creer) ?> var pbq = parseInt($('option:selected', this).attr('data-pbq')); /* If product was selected with a HTML select */ if (isNaN(pbq)) { pbq = jQuery('#idprod').attr('data-pbq'); } /* If product was selected with a HTML input with autocomplete */ - //console.log(pbq); if ((jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val()) && ! isNaN(pbq) && pbq > 0) { @@ -675,6 +674,23 @@ if (!empty($usemargins) && $user->rights->margins->creer) function(data) { console.log("Load unit price end, we got value "+data.price_ht); jQuery("#price_ht").val(data.price_ht); + global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { ?> + var proddesc = data.desc_trans; + + var proddesc = data.desc; + + console.log("Load desciption into text area : "+proddesc); + global->FCKEDITOR_ENABLE_DETAILS)) { ?> + if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") + { + var editor = CKEDITOR.instances['dp_desc']; + if (editor) { + editor.setData(proddesc); + } + } + + jQuery('#dp_desc').text(proddesc); + }, 'json' ); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 542a4a09274..45fb10b525a 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1294,6 +1294,11 @@ if (empty($reshook)) $desc = $productsupplier->desc_supplier; } else $desc = $productsupplier->description; + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc) { + $product_desc=''; + } + if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); $type = $productsupplier->type; diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index 7441d88abc0..273eef35300 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -71,7 +71,9 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) { $outref = $object->ref; $outlabel = $object->label; + $outlabel_trans =''; $outdesc = $object->description; + $outdesc_trans =''; $outtype = $object->type; $outqty = 1; $outdiscount = 0; @@ -79,10 +81,25 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) $found = false; $price_level = 1; - if ($socid > 0 && !empty($conf->global->PRODUIT_MULTIPRICES)) { + + if ($socid > 0) { $thirdpartytemp = new Societe($db); $thirdpartytemp->fetch($socid); - $price_level = $thirdpartytemp->price_level; + //Load translation description and label + if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { + $newlang = $thirdpartytemp->default_lang; + + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + $outdesc_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["description"])) ? $object->multilangs[$outputlangs->defaultlang]["description"] : $object->description; + $outlabel_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["label"])) ? $object->multilangs[$outputlangs->defaultlang]["label"] : $object->label; + } + } + + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $price_level = $thirdpartytemp->price_level; + } } // Price by qty @@ -158,7 +175,19 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) $outtva_tx = $object->tva_tx; } - $outjson = array('ref' => $outref, 'label' => $outlabel, 'desc' => $outdesc, 'type' => $outtype, 'price_ht' => $outprice_ht, 'price_ttc' => $outprice_ttc, 'pricebasetype' => $outpricebasetype, 'tva_tx' => $outtva_tx, 'qty' => $outqty, 'discount' => $outdiscount); + $outjson = array( + 'ref' => $outref, + 'label' => $outlabel, + 'label_trans' => $outlabel_trans, + 'desc' => $outdesc, + 'desc_trans' => $outdesc_trans, + 'type' => $outtype, + 'price_ht' => $outprice_ht, + 'price_ttc' => $outprice_ttc, + 'pricebasetype' => $outpricebasetype, + 'tva_tx' => $outtva_tx, + 'qty' => $outqty, + 'discount' => $outdiscount); } echo json_encode($outjson); From 925dfd36b5d4559a9075c218d40250fde8ff39ea Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 25 Oct 2020 19:15:10 +0100 Subject: [PATCH 002/223] syntax --- htdocs/fourn/facture/card.php | 5 ----- htdocs/product/ajax/products.php | 9 +++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 45fb10b525a..542a4a09274 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1294,11 +1294,6 @@ if (empty($reshook)) $desc = $productsupplier->desc_supplier; } else $desc = $productsupplier->description; - //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time - if ($product_desc==$desc) { - $product_desc=''; - } - if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); $type = $productsupplier->type; diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index 273eef35300..c2b698c8e04 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -85,6 +85,11 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) if ($socid > 0) { $thirdpartytemp = new Societe($db); $thirdpartytemp->fetch($socid); + + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $price_level = $thirdpartytemp->price_level; + } + //Load translation description and label if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { $newlang = $thirdpartytemp->default_lang; @@ -96,10 +101,6 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) $outlabel_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["label"])) ? $object->multilangs[$outputlangs->defaultlang]["label"] : $object->label; } } - - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - $price_level = $thirdpartytemp->price_level; - } } // Price by qty From f4e63bb0462fde1cc339f1ebd81d61ba6af211b9 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 10:52:22 +0100 Subject: [PATCH 003/223] NEW: ref in product customer price: add fields in database --- htdocs/install/mysql/migration/12.0.0-13.0.0.sql | 3 +++ htdocs/install/mysql/tables/llx_product_customer_price.sql | 3 ++- htdocs/install/mysql/tables/llx_product_customer_price_log.sql | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index a73ca40d86f..0a3b9379cbf 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -423,6 +423,9 @@ ALTER TABLE llx_product MODIFY COLUMN finished tinyint DEFAULT NULL; ALTER TABLE llx_product ADD CONSTRAINT fk_product_finished FOREIGN KEY (finished) REFERENCES llx_c_product_nature (code); +ALTER TABLE llx_product_customer_price ADD COLUMN ref_customer varchar(30); +ALTER TABLE llx_product_customer_price_log ADD COLUMN ref_customer varchar(30); + -- MIGRATION TO DO AFTER RENAMING AN OBJECT -- drop constraint diff --git a/htdocs/install/mysql/tables/llx_product_customer_price.sql b/htdocs/install/mysql/tables/llx_product_customer_price.sql index 7cd481c3c75..f0d5edf9c2f 100644 --- a/htdocs/install/mysql/tables/llx_product_customer_price.sql +++ b/htdocs/install/mysql/tables/llx_product_customer_price.sql @@ -27,7 +27,8 @@ create table llx_product_customer_price datec datetime, tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_product integer NOT NULL, - fk_soc integer NOT NULL, + fk_soc integer NOT NULL, + ref_customer varchar(30), price double(24,8) DEFAULT 0, price_ttc double(24,8) DEFAULT 0, price_min double(24,8) DEFAULT 0, diff --git a/htdocs/install/mysql/tables/llx_product_customer_price_log.sql b/htdocs/install/mysql/tables/llx_product_customer_price_log.sql index 4d79353e884..29906fe7ff2 100644 --- a/htdocs/install/mysql/tables/llx_product_customer_price_log.sql +++ b/htdocs/install/mysql/tables/llx_product_customer_price_log.sql @@ -26,7 +26,8 @@ create table llx_product_customer_price_log entity integer DEFAULT 1 NOT NULL, -- multi company id datec datetime, fk_product integer NOT NULL, - fk_soc integer DEFAULT 0 NOT NULL, + fk_soc integer DEFAULT 0 NOT NULL, + ref_customer varchar(30), price double(24,8) DEFAULT 0, price_ttc double(24,8) DEFAULT 0, price_min double(24,8) DEFAULT 0, From 721e931ba7119817694b77f36bd3388430f239c2 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:04:06 +0100 Subject: [PATCH 004/223] NEW: ref in product customer price: add field in CRUD class --- .../class/productcustomerprice.class.php | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/htdocs/product/class/productcustomerprice.class.php b/htdocs/product/class/productcustomerprice.class.php index 25a3c5cd836..49386e8a379 100644 --- a/htdocs/product/class/productcustomerprice.class.php +++ b/htdocs/product/class/productcustomerprice.class.php @@ -54,7 +54,12 @@ class Productcustomerprice extends CommonObject /** * @var int Thirdparty ID */ - public $fk_soc; + public $fk_soc; + + /** + * @var string Customer reference + */ + public $ref_customer; public $price; public $price_ttc; @@ -107,7 +112,9 @@ class Productcustomerprice extends CommonObject if (isset($this->fk_product)) $this->fk_product = trim($this->fk_product); if (isset($this->fk_soc)) - $this->fk_soc = trim($this->fk_soc); + $this->fk_soc = trim($this->fk_soc); + if (isset($this->ref_customer)) + $this->ref_customer = trim($this->ref_customer); if (isset($this->price)) $this->price = trim($this->price); if (isset($this->price_ttc)) @@ -171,6 +178,7 @@ class Productcustomerprice extends CommonObject $sql .= "datec,"; $sql .= "fk_product,"; $sql .= "fk_soc,"; + $sql .= 'ref_customer,'; $sql .= "price,"; $sql .= "price_ttc,"; $sql .= "price_min,"; @@ -190,6 +198,7 @@ class Productcustomerprice extends CommonObject $sql .= " '".$this->db->idate(dol_now())."',"; $sql .= " ".(!isset($this->fk_product) ? 'NULL' : "'".$this->db->escape($this->fk_product)."'").","; $sql .= " ".(!isset($this->fk_soc) ? 'NULL' : "'".$this->db->escape($this->fk_soc)."'").","; + $sql .= " ".(!isset($this->ref_customer) ? 'NULL' : "'".$this->db->escape($this->ref_customer)."'").","; $sql .= " ".(empty($this->price) ? '0' : "'".$this->db->escape($this->price)."'").","; $sql .= " ".(empty($this->price_ttc) ? '0' : "'".$this->db->escape($this->price_ttc)."'").","; $sql .= " ".(empty($this->price_min) ? '0' : "'".$this->db->escape($this->price_min)."'").","; @@ -257,6 +266,7 @@ class Productcustomerprice extends CommonObject $sql .= " t.tms,"; $sql .= " t.fk_product,"; $sql .= " t.fk_soc,"; + $sql .= " t.ref_customer,"; $sql .= " t.price,"; $sql .= " t.price_ttc,"; $sql .= " t.price_min,"; @@ -286,6 +296,7 @@ class Productcustomerprice extends CommonObject $this->tms = $this->db->jdate($obj->tms); $this->fk_product = $obj->fk_product; $this->fk_soc = $obj->fk_soc; + $this->ref_customer = $obj->ref_customer; $this->price = $obj->price; $this->price_ttc = $obj->price_ttc; $this->price_min = $obj->price_min; @@ -334,6 +345,7 @@ class Productcustomerprice extends CommonObject $sql .= " t.tms,"; $sql .= " t.fk_product,"; $sql .= " t.fk_soc,"; + $sql .= " t.ref_customer,"; $sql .= " t.price,"; $sql .= " t.price_ttc,"; $sql .= " t.price_min,"; @@ -393,6 +405,7 @@ class Productcustomerprice extends CommonObject $line->tms = $this->db->jdate($obj->tms); $line->fk_product = $obj->fk_product; $line->fk_soc = $obj->fk_soc; + $line->ref_customer = $obj->ref_customer; $line->price = $obj->price; $line->price_ttc = $obj->price_ttc; $line->price_min = $obj->price_min; @@ -447,6 +460,7 @@ class Productcustomerprice extends CommonObject $sql .= " t.datec,"; $sql .= " t.fk_product,"; $sql .= " t.fk_soc,"; + $sql .= " t.ref_customer,"; $sql .= " t.price,"; $sql .= " t.price_ttc,"; $sql .= " t.price_min,"; @@ -502,6 +516,7 @@ class Productcustomerprice extends CommonObject $line->tms = $this->db->jdate($obj->tms); $line->fk_product = $obj->fk_product; $line->fk_soc = $obj->fk_soc; + $line->ref_customer = $obj->ref_customer; $line->price = $obj->price; $line->price_ttc = $obj->price_ttc; $line->price_min = $obj->price_min; @@ -549,7 +564,9 @@ class Productcustomerprice extends CommonObject if (isset($this->fk_product)) $this->fk_product = trim($this->fk_product); if (isset($this->fk_soc)) - $this->fk_soc = trim($this->fk_soc); + $this->fk_soc = trim($this->fk_soc); + if (isset($this->ref_customer)) + $this->ref_customer = trim($this->ref_customer); if (isset($this->price)) $this->price = trim($this->price); if (isset($this->price_ttc)) @@ -615,6 +632,7 @@ class Productcustomerprice extends CommonObject $sql .= "datec,"; $sql .= "fk_product,"; $sql .= "fk_soc,"; + $sql .= "ref_customer,"; $sql .= "price,"; $sql .= "price_ttc,"; $sql .= "price_min,"; @@ -637,6 +655,7 @@ class Productcustomerprice extends CommonObject $sql .= " t.datec,"; $sql .= " t.fk_product,"; $sql .= " t.fk_soc,"; + $sql .= " t.ref_customer,"; $sql .= " t.price,"; $sql .= " t.price_ttc,"; $sql .= " t.price_min,"; @@ -671,6 +690,7 @@ class Productcustomerprice extends CommonObject $sql .= " tms=".(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : 'null').","; $sql .= " fk_product=".(isset($this->fk_product) ? $this->fk_product : "null").","; $sql .= " fk_soc=".(isset($this->fk_soc) ? $this->fk_soc : "null").","; + $sql .= " ref_customer=".(isset($this->ref_customer) ? $this->ref_customer : "null").","; $sql .= " price=".(isset($this->price) ? $this->price : "null").","; $sql .= " price_ttc=".(isset($this->price_ttc) ? $this->price_ttc : "null").","; $sql .= " price_min=".(isset($this->price_min) ? $this->price_min : "null").","; @@ -790,6 +810,7 @@ class Productcustomerprice extends CommonObject // If line do not exits then create it $prodsocpricenew = new Productcustomerprice($this->db); $prodsocpricenew->fk_soc = $obj->rowid; + $prodsocpricenew->ref_customer = $obj->ref_customer; $prodsocpricenew->fk_product = $this->fk_product; $prodsocpricenew->price = $this->price; $prodsocpricenew->price_min = $this->price_min; @@ -924,6 +945,7 @@ class Productcustomerprice extends CommonObject $this->tms = ''; $this->fk_product = ''; $this->fk_soc = ''; + $this->ref_customer = ''; $this->price = ''; $this->price_ttc = ''; $this->price_min = ''; @@ -962,6 +984,11 @@ class PriceByCustomerLine */ public $fk_product; + /** + * @var string Customer reference + */ + public $ref_customer; + /** * @var int Thirdparty ID */ From 6a3150028c74851ce256bb8fc8546cac1e2530e9 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:47:01 +0100 Subject: [PATCH 005/223] NEW: ref in product customer price: fix price update SQL --- htdocs/product/class/productcustomerprice.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/productcustomerprice.class.php b/htdocs/product/class/productcustomerprice.class.php index 49386e8a379..c18d09614e6 100644 --- a/htdocs/product/class/productcustomerprice.class.php +++ b/htdocs/product/class/productcustomerprice.class.php @@ -690,7 +690,7 @@ class Productcustomerprice extends CommonObject $sql .= " tms=".(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : 'null').","; $sql .= " fk_product=".(isset($this->fk_product) ? $this->fk_product : "null").","; $sql .= " fk_soc=".(isset($this->fk_soc) ? $this->fk_soc : "null").","; - $sql .= " ref_customer=".(isset($this->ref_customer) ? $this->ref_customer : "null").","; + $sql .= " ref_customer=".(isset($this->ref_customer) ? "'" . $this->db->escape($this->ref_customer) . "'" : "null").","; $sql .= " price=".(isset($this->price) ? $this->price : "null").","; $sql .= " price_ttc=".(isset($this->price_ttc) ? $this->price_ttc : "null").","; $sql .= " price_min=".(isset($this->price_min) ? $this->price_min : "null").","; From c2518e92fbb26ce077cb33500965b6cc77528ea8 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:50:04 +0100 Subject: [PATCH 006/223] NEW: ref in product customer price: add field in views --- htdocs/product/price.php | 9 ++++++--- htdocs/societe/price.php | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 8d10535ae31..2444fe6468d 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -1854,6 +1854,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print ''; print ''.$langs->trans("ThirdParty").''; + print ''.$langs->trans('RefCustomer').''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("DefaultTaxRate").''; @@ -1901,6 +1902,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print ''; print "".$staticsoc->getNomUrl(1).""; + print '' . $line->ref_customer . ''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; print ''; @@ -1969,7 +1971,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) if (count($prodcustprice->lines) > 0 || $search_soc) { - $colspan = 8; + $colspan = 9; //if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") $colspan++; print ''; @@ -1985,6 +1987,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print ''; print ''.$langs->trans("ThirdParty").''; + print '' . $langs->trans('RefCustomer') . ''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("DefaultTaxRate").''; @@ -2023,8 +2026,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) $total_ttc = $resultarray[2]; print ''; - print "".$langs->trans("Default").""; - print ""; + print '' . $langs->trans('Default') . ''; print ''.$langs->trans($object->price_base_type).""; print ''; @@ -2102,6 +2104,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print ''; print "".$staticsoc->getNomUrl(1).""; + print '' . $line->ref_customer . ''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; diff --git a/htdocs/societe/price.php b/htdocs/societe/price.php index 8a65b56b2bf..2275ab251f7 100644 --- a/htdocs/societe/price.php +++ b/htdocs/societe/price.php @@ -461,6 +461,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''.$langs->trans("Product").''; + print '' . $langs->trans('RefCustomer') . ''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("VAT").''; @@ -478,6 +479,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { $staticprod->fetch($line->fk_product); print "".$staticprod->getNomUrl(1).""; + print '' . $line->ref_customer . ''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; @@ -547,6 +549,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print '' . $langs->trans("Ref") . ''; print '' . $langs->trans("Product") . ''; + print '' . $langs->trans('RefCustomer') . ''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("VAT").''; @@ -563,7 +566,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''; print ''; - print ' '; + print ' '; print ''; print ''; print ' '; @@ -586,6 +589,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "".$staticprod->getNomUrl(1).""; print "" . $staticprod->label .""; + print '' . $line->ref_customer .''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; @@ -623,7 +627,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "\n"; } } else { - $colspan = 9; + $colspan = 10; if ($user->rights->produit->supprimer || $user->rights->service->supprimer) $colspan += 1; print ''.$langs->trans('None').''; } From 496c31d63ab611e5b67278643823326d0b0f5258 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 12:18:24 +0100 Subject: [PATCH 007/223] NEW: ref in product customer price: add field in forms and form handlers --- htdocs/product/price.php | 10 ++++++++++ htdocs/societe/price.php | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 2444fe6468d..a150402cfde 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -499,6 +499,7 @@ if (empty($reshook)) // add price by customer $prodcustprice->fk_soc = GETPOST('socid', 'int'); + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->fk_product = $object->id; $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); @@ -600,6 +601,7 @@ if (empty($reshook)) $prodcustprice->fetch(GETPOST('lineid', 'int')); // update price by customer + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha'); @@ -1662,6 +1664,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print ''; print ''; + // Ref. Customer + print '' . $langs->trans('RefCustomer') . ''; + print ''; + // VAT print ''.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, $object->type, false, 1); @@ -1748,6 +1754,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) print "".$staticsoc->getNomUrl(1).""; print ''; + // Ref. Customer + print '' . $langs->trans('RefCustomer') . ''; + print ''; + // VAT print ''.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $prodcustprice->default_vat_code ? $prodcustprice->tva_tx.' ('.$prodcustprice->default_vat_code.')' : $prodcustprice->tva_tx, $mysoc, '', $object->id, $prodcustprice->recuperableonly, $object->type, false, 1); diff --git a/htdocs/societe/price.php b/htdocs/societe/price.php index 2275ab251f7..6d1d08b17b5 100644 --- a/htdocs/societe/price.php +++ b/htdocs/societe/price.php @@ -88,6 +88,7 @@ if (empty($reshook)) // add price by customer $prodcustprice->fk_soc = $socid; + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->fk_product = GETPOST('prodid', 'int'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); @@ -162,6 +163,7 @@ if (empty($reshook)) $update_child_soc = GETPOST('updatechildprice'); // update price by customer + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha'); @@ -294,6 +296,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''; + // Ref. Customer + print '' . $langs->trans('RefCustomer') . ''; + print ''; + // VAT print ''.$langs->trans("VATRate").''; print $form->load_tva("tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, '', false, 1); @@ -372,6 +378,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "".$staticprod->getNomUrl(1).""; print ''; + // Ref. Customer + print '' . $langs->trans('RefCustomer') . ''; + print ''; + // VAT print ''.$langs->trans("VATRate").''; print $form->load_tva("tva_tx", $prodcustprice->tva_tx, $mysoc, '', $staticprod->id, $prodcustprice->recuperableonly); From bb850ad0d083e8cc76eeb997acd29dc8779cab31 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 13:05:07 +0100 Subject: [PATCH 008/223] NEW: ref in product customer price: add ref in PDFs + hidden conf to choose refs to show --- htdocs/core/lib/pdf.lib.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 0ff40659daa..9889e3ff220 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1237,6 +1237,10 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, } else { include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $prodser = new Product($db); + + if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { + include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; + } } if ($idprod) @@ -1364,6 +1368,32 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, } } else { $ref_prodserv = $prodser->ref; // Show local ref only + + if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { + $productCustomerPriceStatic = new Productcustomerprice($db); + $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid); + + $nbCustomerPrices = $productCustomerPriceStatic->fetch_all('', '', 1, 0, $filter); + + if ($nbCustomerPrices > 0) { + $productCustomerPrice = $productCustomerPriceStatic->lines[0]; + + if (! empty($productCustomerPrice->ref_customer)) { + switch($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) { + case 1: + $ref_prodserv = $productCustomerPrice->ref_customer; + break; + + case 2: + $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')'; + break; + + default: + $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')'; + } + } + } + } } if (!empty($libelleproduitservice) && !empty($ref_prodserv)) $ref_prodserv .= " - "; From 79ba133a07d5f691fac0ef00f94af5559ac233aa Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 26 Oct 2020 13:05:26 +0100 Subject: [PATCH 009/223] NEW: ref in product customer price: fix missing language key --- htdocs/langs/en_US/main.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 1096b9857f1..84d399ddde2 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -646,6 +646,7 @@ SupplierPreview=Vendor preview ShowCustomerPreview=Show customer preview ShowSupplierPreview=Show vendor preview RefCustomer=Ref. customer +InternalRef=Internal ref. Currency=Currency InfoAdmin=Information for administrators Undo=Undo From 541dab57371e5b8517bc77f527262bc777b178ea Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 26 Oct 2020 13:40:05 +0000 Subject: [PATCH 010/223] Fixing style errors. --- htdocs/core/lib/pdf.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 9889e3ff220..6d0b3023964 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1379,7 +1379,7 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $productCustomerPrice = $productCustomerPriceStatic->lines[0]; if (! empty($productCustomerPrice->ref_customer)) { - switch($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) { + switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) { case 1: $ref_prodserv = $productCustomerPrice->ref_customer; break; From 76824c868bdadc3268cfab95a4b49820bfaa224d Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 26 Oct 2020 16:31:07 +0100 Subject: [PATCH 011/223] clean get price for fourn and labal for supplier coducment --- htdocs/core/class/html.form.class.php | 30 +++++++- htdocs/core/lib/ajax.lib.php | 40 ++++++++--- htdocs/core/tpl/objectline_create.tpl.php | 83 +++++++++++++++++------ htdocs/fourn/commande/card.php | 4 +- htdocs/fourn/facture/card.php | 2 +- htdocs/product/fournisseurs.php | 2 +- 6 files changed, 127 insertions(+), 34 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index bf52ff5871a..397d1a008cf 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2737,6 +2737,12 @@ class Form $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,"; $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.fk_soc, s.nom as name,"; $sql .= " pfp.supplier_reputation"; + // if we use supplier description of the products + if (!empty($conf->global->PRODUIT_FOURN_TEXTS)) { + $sql .= " ,pfp.desc_fourn as description"; + } else { + $sql .= " ,p.description"; + } // Units if ($conf->global->PRODUCT_USE_UNITS) { $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units"; @@ -2766,7 +2772,11 @@ class Form foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; - $sql .= "(pfp.ref_fourn LIKE '".$this->db->escape($prefix.$crit)."%' OR p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%')"; + $sql .= "(pfp.ref_fourn LIKE '".$this->db->escape($prefix.$crit)."%' OR p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; + if (!empty($conf->global->PRODUIT_FOURN_TEXTS)) { + $sql .= " OR pfp.desc_fourn LIKE '".$this->db->escape($prefix.$crit)."%'"; + } + $sql .= ")"; $i++; } if (count($scrit) > 1) $sql .= ")"; @@ -2956,8 +2966,9 @@ class Form if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) $opt .= ' disabled'; if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) { - $opt .= ' pbq="'.$objp->idprodfournprice.'" data-pbq="'.$objp->idprodfournprice.'" data-pbqqty="'.$objp->quantity.'" data-pbqup="'.$objp->unitprice.'" data-pbqpercent="'.$objp->remise_percent.'"'; + $opt .= ' data-qty="'.$objp->quantity.'" data-up="'.$objp->unitprice.'" data-discount="'.$outdiscount.'"'; } + $opt .= ' data-description="'.dol_escape_htmltag($objp->description).'"'; $opt .= ' data-html="'.dol_escape_htmltag($optlabel).'"'; $opt .= '>'; @@ -2971,7 +2982,20 @@ class Form // "key" value of json key array is used by jQuery automatically as selected value // "label" value of json key array is used by jQuery automatically as text for combo box $out .= $opt; - array_push($outarray, array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'qty'=>$outqty, 'up'=>$objp->unitprice, 'discount'=>$outdiscount, 'type'=>$outtype, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'disabled'=>(empty($objp->idprodfournprice) ?true:false))); + array_push($outarray, + array('key'=>$outkey, + 'value'=>$outref, + 'label'=>$outval, + 'qty'=>$outqty, + 'up'=>$objp->unitprice, + 'discount'=>$outdiscount, + 'type'=>$outtype, + 'duration_value'=>$outdurationvalue, + 'duration_unit'=>$outdurationunit, + 'disabled'=>(empty($objp->idprodfournprice) ?true:false), + 'description'=>$objp->description + ) + ); // Exemple of var_dump $outarray // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp" // ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)" diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 10fa477600a..9b225967eb1 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -134,7 +134,11 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen } return { label: label, value: item.value, id: item.key, disabled: item.disabled, update: update, textarea: textarea, - pbq: item.pbq, type: item.type, qty: item.qty, discount: item.discount, pricebasetype: item.pricebasetype, price_ht: item.price_ht, price_ttc: item.price_ttc } + pbq: item.pbq, + type: item.type, qty: item.qty, discount: item.discount, + pricebasetype: item.pricebasetype, price_ht: item.price_ht, + price_ttc: item.price_ttc, + up: item.up, description : item.description} })); } else console.error("Error: Ajax url '.$url.($urloption ? '?'.$urloption : '').' has returned an empty page. Should be an empty json array."); @@ -146,14 +150,34 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen console.log("Call change on input '.$htmlname.' because of select definition of autocomplete select call on input#search_'.$htmlname.'"); console.log("Selected id = "+ui.item.id+" - If this value is null, it means you select a record with key that is null so selection is not effective"); - //console.log(ui.item); - $("#'.$htmlname.'").attr("data-pbq", ui.item.pbq); - $("#'.$htmlname.'").attr("data-pbqup", ui.item.price_ht); - $("#'.$htmlname.'").attr("data-pbqbase", ui.item.pricebasetype); - $("#'.$htmlname.'").attr("data-pbqqty", ui.item.qty); - $("#'.$htmlname.'").attr("data-pbqpercent", ui.item.discount); + console.log(ui.item); + //For supplier price + $("#'.$htmlname.'").attr("data-up", ui.item.up); + $("#'.$htmlname.'").attr("data-discount", ui.item.discount); + $("#'.$htmlname.'").attr("data-qty", ui.item.qty); + $("#'.$htmlname.'").attr("data-description", ui.item.description); - $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Select new value + //For customer price + '; + + if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { + $script .= ' + $("#' . $htmlname . '").attr("data-pbq", ui.item.pbq); + $("#' . $htmlname . '").attr("data-pbqup", ui.item.price_ht); + $("#' . $htmlname . '").attr("data-pbqbase", ui.item.pricebasetype); + $("#' . $htmlname . '").attr("data-pbqqty", ui.item.qty); + $("#' . $htmlname . '").attr("data-pbqpercent", ui.item.discount); + '; + } else { + $script .= ' + $("#' . $htmlname . '").attr("data-up", ui.item.price_ht); + $("#' . $htmlname . '").attr("data-base", ui.item.pricebasetype); + $("#' . $htmlname . '").attr("data-qty", ui.item.qty); + $("#' . $htmlname . '").attr("data-discount", ui.item.discount); + '; + } + $script .= ' + $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Select new value // Disable an element if (options.option_disabled) { console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index ec73bf9725b..ba6b4e1bb1b 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -602,39 +602,39 @@ if (!empty($usemargins) && $user->rights->margins->creer) }); $("#prod_entry_mode_free").on( "click", function() { - setforfree(); + setforfree(); }); $("#select_type").change(function() { - setforfree(); + setforfree(); if (jQuery('#select_type').val() >= 0) { /* focus work on a standard textarea but not if field was replaced with CKEDITOR */ - jQuery('#dp_desc').focus(); - /* focus if CKEDITOR */ - if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") - { - var editor = CKEDITOR.instances['dp_desc']; - if (editor) { editor.focus(); } - } + jQuery('#dp_desc').focus(); + /* focus if CKEDITOR */ + if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") + { + var editor = CKEDITOR.instances['dp_desc']; + if (editor) { editor.focus(); } + } } console.log("Hide/show date according to product type"); if (jQuery('#select_type').val() == '0') { - jQuery('#trlinefordates').hide(); - jQuery('.divlinefordates').hide(); + jQuery('#trlinefordates').hide(); + jQuery('.divlinefordates').hide(); } else { - jQuery('#trlinefordates').show(); - jQuery('.divlinefordates').show(); + jQuery('#trlinefordates').show(); + jQuery('.divlinefordates').show(); } }); $("#prod_entry_mode_predef").on( "click", function() { - console.log("click prod_entry_mode_predef"); - setforpredef(); - jQuery('#trlinefordates').show(); + console.log("click prod_entry_mode_predef"); + setforpredef(); + jQuery('#trlinefordates').show(); }); rights->margins->creer) 'json' ); } - rights->margins->creer) @@ -804,7 +804,10 @@ if (!empty($usemargins) && $user->rights->margins->creer) } ?> - /* To process customer price per quantity (CUSTOMER_PRICE_PER_QTY works only if combo product is not an ajax after x key pressed) */ + global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) + {?> + /* To process customer price per quantity (PRODUIT_CUSTOMER_PRICES_BY_QTY works only if combo product is not an ajax after x key pressed) */ var pbq = parseInt($('option:selected', this).attr('data-pbq')); // When select is done from HTML select if (isNaN(pbq)) { pbq = jQuery('#idprod').attr('data-pbq'); } // When select is done from HTML input with autocomplete var pbqup = parseFloat($('option:selected', this).attr('data-pbqup')); @@ -816,7 +819,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) var pbqpercent = parseFloat($('option:selected', this).attr('data-pbqpercent')); if (isNaN(pbqpercent)) { pbqpercent = jQuery('#idprod').attr('data-pbqpercent'); } - if ((jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val()) && ! isNaN(pbq) && pbq > 0) + if ((jQuery('#idprod').val() > 0) && ! isNaN(pbq) && pbq > 0) { var pbqupht = pbqup; /* TODO support of price per qty TTC not yet available */ @@ -832,6 +835,48 @@ if (!empty($usemargins) && $user->rights->margins->creer) jQuery("#remise_percent").val(pbqpercent); } } + + //Deal with supplier + if (jQuery('#idprodfournprice').val() >0) + { + var up = parseFloat($('option:selected', this).attr('data-up')); // When select is done from HTML select + if (isNaN(up)) { up = parseFloat(jQuery('#idprodfournprice').attr('data-up'));} // When select is done from HTML input with autocomplete + + var qty = parseFloat($('option:selected', this).attr('data-qty')); + if (isNaN(qty)) { qty = parseFloat(jQuery('#idprodfournprice').attr('data-qty'));} + + var discount = parseFloat($('option:selected', this).attr('data-discount')); + if (isNaN(discount)) { discount = parseFloat(jQuery('#idprodfournprice').attr('data-discount'));} + + var description = $('option:selected', this).attr('data-description'); + if (typeof description == 'undefined') { description = jQuery('#idprodfournprice').attr('data-description'); } + console.log("We find supplier price :"+up+" qty: "+qty+" discount: "+discount+" for product "+jQuery('#idprodfournprice').val()); + + jQuery("#price_ht").val(up); + if (jQuery("#qty").val() < qty) + { + jQuery("#qty").val(qty); + } + if (jQuery("#remise_percent").val() < discount) + { + jQuery("#remise_percent").val(discount); + } + + console.log("Load desciption into text area : "+description); + global->FCKEDITOR_ENABLE_DETAILS)) { ?> + if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") + { + var editor = CKEDITOR.instances['dp_desc']; + if (editor) { + editor.setData(description); + } + } + + jQuery('#dp_desc').text(description); + + } else { jQuery("#pbq").val(''); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index e202b3e8efd..e5ddc3b1b75 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -356,7 +356,7 @@ if (empty($reshook)) // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOST('dp_desc') ?GETPOST('dp_desc') : ''); + $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year')); $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year')); $prod_entry_mode = GETPOST('prod_entry_mode'); @@ -475,7 +475,7 @@ if (empty($reshook)) $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); } - $desc = (!empty($productsupplier->multilangs [$outputlangs->defaultlang] ["description"])) ? $productsupplier->multilangs [$outputlangs->defaultlang] ["description"] : $productsupplier->description; + $desc = (!empty($productsupplier->multilangs[$outputlangs->defaultlang]["description"])) ? $productsupplier->multilangs[$outputlangs->defaultlang]["description"] : $productsupplier->description; } else { $desc = $productsupplier->description; } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index c304a4edce7..3f9ea28c420 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1180,7 +1180,7 @@ if (empty($reshook)) // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOST('dp_desc') ?GETPOST('dp_desc') : ''); + $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year')); $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year')); diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index b9a8d6c3b68..41c38c82ba7 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -166,7 +166,7 @@ if (empty($reshook)) $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : ''; $supplier_reputation = GETPOST('supplier_reputation'); - $supplier_description = GETPOST('supplier_description', 'alpha'); + $supplier_description = GETPOST('supplier_description', 'restricthtml'); $barcode = GETPOST('barcode', 'alpha'); $fk_barcode_type = GETPOST('fk_barcode_type', 'int'); $packaging = price2num(GETPOST("packaging", 'alphanohtml'), 'MS'); From a53e9077069e4ab467ac94f90a527b8991d3204b Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 26 Oct 2020 15:32:00 +0000 Subject: [PATCH 012/223] Fixing style errors. --- htdocs/core/tpl/objectline_create.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index ba6b4e1bb1b..c69b57a90d0 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -695,7 +695,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) 'json' ); } - rights->margins->creer) @@ -835,7 +835,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) jQuery("#remise_percent").val(pbqpercent); } } - //Deal with supplier From 9aa3368627a052592a342cdeb41dc22d279444fd Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 26 Oct 2020 16:33:13 +0100 Subject: [PATCH 013/223] syntax --- htdocs/core/lib/ajax.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 9b225967eb1..f8ec1d5ead1 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -150,7 +150,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen console.log("Call change on input '.$htmlname.' because of select definition of autocomplete select call on input#search_'.$htmlname.'"); console.log("Selected id = "+ui.item.id+" - If this value is null, it means you select a record with key that is null so selection is not effective"); - console.log(ui.item); + //console.log(ui.item); //For supplier price $("#'.$htmlname.'").attr("data-up", ui.item.up); $("#'.$htmlname.'").attr("data-discount", ui.item.discount); From 2c772cd8bb2b046e5490d3f0f73db6bd9dc2876b Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 27 Oct 2020 09:52:04 +0100 Subject: [PATCH 014/223] try to make it work for experimental PRODUIT_CUSTOMER_PRICES_BY_QTY option --- htdocs/core/class/html.form.class.php | 45 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 397d1a008cf..ff83173be5e 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2150,7 +2150,9 @@ class Form if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= ", pl.label as label_translated"; + $sql .= ", pl.description as description_translated"; $selectFields .= ", label_translated"; + $selectFields .= ", description_translated"; } // Price by quantity if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) @@ -2190,7 +2192,18 @@ class Form // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='".$this->db->escape($langs->getDefaultLang())."'"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid "; + if (!empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE) && !empty($socid)) { + $soc = new Societe($db); + $result = $soc->fetch($socid); + if ($result > 0 && !empty($soc->default_lang)) { + $sql .= " AND pl.lang='" . $this->db->escape($soc->default_lang) . "'"; + } else { + $sql .= " AND pl.lang='".$this->db->escape($langs->getDefaultLang())."'"; + } + } else { + $sql .= " AND pl.lang='".$this->db->escape($langs->getDefaultLang())."'"; + } } if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { @@ -2403,7 +2416,9 @@ class Form $outval = ''; $outref = ''; $outlabel = ''; + $outlabel_translated = ''; $outdesc = ''; + $outdesc_translated = ''; $outbarcode = ''; $outorigin = ''; $outtype = ''; @@ -2424,6 +2439,11 @@ class Form $outref = $objp->ref; $outlabel = $objp->label; $outdesc = $objp->description; + if (!empty($conf->global->MAIN_MULTILANGS)) + { + $outlabel_translated = $objp->label_translated; + $outdesc_translated = $objp->description_translated; + } $outbarcode = $objp->barcode; $outorigin = $objp->fk_country; $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid; @@ -2485,6 +2505,10 @@ class Form elseif ($objp->stock <= 0) $opt .= ' class="product_line_stock_too_low"'; } } + if (!empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { + $opt .= ' data-labeltrans="'.$outlabel_translated.'"'; + $opt .= ' data-desctrans="'.dol_escape_htmltag($outdesc_translated).'"'; + } $opt .= '>'; $opt .= $objp->ref; if ($outbarcode) $opt .= ' ('.$outbarcode.')'; @@ -2655,7 +2679,24 @@ class Form } $opt .= "\n"; - $optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>price2num($outprice_ht), 'price_ttc'=>price2num($outprice_ttc), 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'pbq'=>$outpbq); + $optJson = array( + 'key'=>$outkey, + 'value'=>$outref, + 'label'=>$outval, + 'label2'=>$outlabel, + 'desc'=>$outdesc, + 'type'=>$outtype, + 'price_ht'=>price2num($outprice_ht), + 'price_ttc'=>price2num($outprice_ttc), + 'pricebasetype'=>$outpricebasetype, + 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, + 'discount'=>$outdiscount, + 'duration_value'=>$outdurationvalue, + 'duration_unit'=>$outdurationunit, + 'pbq'=>$outpbq, + 'labeltrans'=>$outlabel_translated, + 'desctrans'=>$outdesc_translated + ); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps From ca2ed2ef74d94d7808154ee8e41cf0f4ec290891 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Wed, 28 Oct 2020 11:04:15 +0100 Subject: [PATCH 015/223] NEW: ref in product customer price: look for products with customer ref --- htdocs/core/class/html.form.class.php | 10 +++++++--- htdocs/core/lib/ajax.lib.php | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index bf52ff5871a..59f98e626a9 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2137,8 +2137,8 @@ class Form if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,'; - $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx'; - $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx"; + $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.ref_customer as custref'; + $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custref"; } // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { @@ -2235,6 +2235,7 @@ class Form if ($i > 0) $sql .= " AND "; $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= " OR pl.label LIKE '".$this->db->escape($prefix.$crit)."%'"; + if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && ! empty($socid)) $sql .= " OR pcp.ref_customer LIKE '".$this->db->escape($prefix.$crit)."%'"; if (!empty($conf->global->PRODUCT_AJAX_SEARCH_ON_DESCRIPTION)) { $sql .= " OR p.description LIKE '".$this->db->escape($prefix.$crit)."%'"; @@ -2422,6 +2423,7 @@ class Form $outkey = $objp->rowid; $outref = $objp->ref; + $outrefcust = empty($objp->custref) ? '' : $objp->custref; $outlabel = $objp->label; $outdesc = $objp->description; $outbarcode = $objp->barcode; @@ -2487,11 +2489,13 @@ class Form } $opt .= '>'; $opt .= $objp->ref; + if (! empty($objp->custref)) $opt.= ' (' . $objp->custref . ')'; if ($outbarcode) $opt .= ' ('.$outbarcode.')'; $opt .= ' - '.dol_trunc($label, $maxlengtharticle); if ($outorigin && !empty($conf->global->PRODUCT_SHOW_ORIGIN_IN_COMBO)) $opt .= ' ('.getCountry($outorigin, 1).')'; $objRef = $objp->ref; + if (! empty($objp->custref)) $objRef .= ' (' . $objp->custref . ')'; if (!empty($filterkey) && $filterkey != '') $objRef = preg_replace('/('.preg_quote($filterkey, '/').')/i', '$1', $objRef, 1); $outval .= $objRef; if ($outbarcode) $outval .= ' ('.$outbarcode.')'; @@ -2655,7 +2659,7 @@ class Form } $opt .= "\n"; - $optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>price2num($outprice_ht), 'price_ttc'=>price2num($outprice_ttc), 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'pbq'=>$outpbq); + $optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>price2num($outprice_ht), 'price_ttc'=>price2num($outprice_ttc), 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'pbq'=>$outpbq, 'ref_customer'=>$outrefcust); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 10fa477600a..0c7a8ecc312 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -134,7 +134,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen } return { label: label, value: item.value, id: item.key, disabled: item.disabled, update: update, textarea: textarea, - pbq: item.pbq, type: item.type, qty: item.qty, discount: item.discount, pricebasetype: item.pricebasetype, price_ht: item.price_ht, price_ttc: item.price_ttc } + pbq: item.pbq, type: item.type, qty: item.qty, discount: item.discount, pricebasetype: item.pricebasetype, price_ht: item.price_ht, price_ttc: item.price_ttc, ref_customer: item.ref_customer } })); } else console.error("Error: Ajax url '.$url.($urloption ? '?'.$urloption : '').' has returned an empty page. Should be an empty json array."); @@ -152,6 +152,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen $("#'.$htmlname.'").attr("data-pbqbase", ui.item.pricebasetype); $("#'.$htmlname.'").attr("data-pbqqty", ui.item.qty); $("#'.$htmlname.'").attr("data-pbqpercent", ui.item.discount); + $("#'.$htmlname.'").attr("data-ref-customer", ui.item.ref_customer); $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Select new value // Disable an element From d77a0b40a8923049710455d633911416cd66ada8 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 28 Oct 2020 16:37:41 +0100 Subject: [PATCH 016/223] tested and approuve feaure #15036 --- htdocs/comm/propal/card.php | 4 +- htdocs/commande/card.php | 4 +- htdocs/compta/facture/card.php | 4 +- htdocs/contrat/card.php | 4 +- htdocs/core/tpl/objectline_create.tpl.php | 65 +++++++++++++++++------ htdocs/fourn/commande/card.php | 8 ++- htdocs/fourn/facture/card.php | 7 ++- htdocs/langs/en_US/admin.lang | 4 +- htdocs/product/admin/product.php | 23 ++++++++ htdocs/product/ajax/products.php | 3 ++ 10 files changed, 98 insertions(+), 28 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index f03986d471c..47dd722b5b1 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -793,7 +793,7 @@ if (empty($reshook)) } elseif ($action == 'addline' && $usercancreate) { // Add line // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOSTISSET('dp_desc') ?GETPOST('dp_desc', 'restricthtml') : ''); + $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht')); $price_ht_devise = price2num(GETPOST('multicurrency_price_ht')); $prod_entry_mode = GETPOST('prod_entry_mode'); @@ -1001,7 +1001,7 @@ if (empty($reshook)) } //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time - if ($product_desc==$desc) { + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { $product_desc=''; } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 6572a383532..1bdce17f564 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -640,7 +640,7 @@ if (empty($reshook)) // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOST('dp_desc') ?GETPOST('dp_desc') : ''); + $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = GETPOST('price_ht'); $price_ht_devise = GETPOST('multicurrency_price_ht'); $prod_entry_mode = GETPOST('prod_entry_mode'); @@ -855,7 +855,7 @@ if (empty($reshook)) } //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time - if ($product_desc==$desc) { + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { $product_desc=''; } diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 80e60dd8784..4602e968220 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1902,7 +1902,7 @@ if (empty($reshook)) // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOST('dp_desc', 'none') ?GETPOST('dp_desc', 'restricthtml') : ''); + $product_desc =(GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht')); $price_ht_devise = price2num(GETPOST('multicurrency_price_ht')); $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha'); @@ -2073,7 +2073,7 @@ if (empty($reshook)) } //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time - if ($product_desc==$desc) { + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { $product_desc=''; } diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 034709ef110..3265e2f5866 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -383,7 +383,7 @@ if (empty($reshook)) { // Set if we used free entry or predefined product $predef = ''; - $product_desc = (GETPOST('dp_desc') ?GETPOST('dp_desc') : ''); + $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht')); $price_ht_devise = price2num(GETPOST('multicurrency_price_ht')); if (GETPOST('prod_entry_mode', 'alpha') == 'free') @@ -501,7 +501,7 @@ if (empty($reshook)) $desc = $prod->description; //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time - if ($product_desc==$desc) { + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { $product_desc=''; } diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index c69b57a90d0..f1faf50e991 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -674,13 +674,18 @@ if (!empty($usemargins) && $user->rights->margins->creer) function(data) { console.log("Load unit price end, we got value "+data.price_ht); jQuery("#price_ht").val(data.price_ht); - global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { ?> + global->PRODUIT_AUTOFILL_DESC)) { + if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { ?> var proddesc = data.desc_trans; - + var proddesc = data.desc; - + console.log("Load desciption into text area : "+proddesc); - global->FCKEDITOR_ENABLE_DETAILS)) { ?> + global->FCKEDITOR_ENABLE_DETAILS)) { ?> if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") { var editor = CKEDITOR.instances['dp_desc']; @@ -688,9 +693,13 @@ if (!empty($usemargins) && $user->rights->margins->creer) editor.setData(proddesc); } } - + jQuery('#dp_desc').text(proddesc); - + + }, 'json' ); @@ -834,7 +843,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { jQuery("#remise_percent").val(pbqpercent); } - } + } else { jQuery("#pbq").val(''); } @@ -850,8 +859,6 @@ if (!empty($usemargins) && $user->rights->margins->creer) var discount = parseFloat($('option:selected', this).attr('data-discount')); if (isNaN(discount)) { discount = parseFloat(jQuery('#idprodfournprice').attr('data-discount'));} - var description = $('option:selected', this).attr('data-description'); - if (typeof description == 'undefined') { description = jQuery('#idprodfournprice').attr('data-description'); } console.log("We find supplier price :"+up+" qty: "+qty+" discount: "+discount+" for product "+jQuery('#idprodfournprice').val()); jQuery("#price_ht").val(up); @@ -864,24 +871,48 @@ if (!empty($usemargins) && $user->rights->margins->creer) jQuery("#remise_percent").val(discount); } + global->PRODUIT_AUTOFILL_DESC)) { + ?> + var description = $('option:selected', this).attr('data-description'); + if (typeof description == 'undefined') { description = jQuery('#idprodfournprice').attr('data-description'); } + console.log("Load desciption into text area : "+description); - global->FCKEDITOR_ENABLE_DETAILS)) { ?> + global->FCKEDITOR_ENABLE_DETAILS)) { ?> if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") { var editor = CKEDITOR.instances['dp_desc']; if (editor) { - editor.setData(description); + editor.setData(description); } } - + jQuery('#dp_desc').text(description); - - } - else - { - jQuery("#pbq").val(''); + + } else if (jQuery('#idprodfournprice').length > 0) { + global->PRODUIT_AUTOFILL_DESC)) { + if (!empty($conf->global->FCKEDITOR_ENABLE_DETAILS)) { ?> + if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") + { + var editor = CKEDITOR.instances['dp_desc']; + if (editor) { + editor.setData(''); + } + } + + jQuery('#dp_desc').text(''); + } + /* To set focus */ if (jQuery('#idprod').val() > 0 || jQuery('#idprodfournprice').val() > 0) { diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 42817e2ea28..f7c963f5e29 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -484,7 +484,13 @@ if (empty($reshook)) $desc = $productsupplier->desc_supplier; } - if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { + $product_desc=''; + } + + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; + if (!empty($product_desc) && trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); $type = $productsupplier->type; if ($price_ht != '' || $price_ht_devise != '') { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 9849e3b6223..a6bc58879c1 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1294,7 +1294,12 @@ if (empty($reshook)) $desc = $productsupplier->desc_supplier; } else $desc = $productsupplier->description; - if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); + //If text set in desc is the same as product descpription (as now it's preloaded) whe add it only one time + if ($product_desc==$desc && !empty($conf->global->PRODUIT_AUTOFILL_DESC)) { + $product_desc=''; + } + if (!empty($product_desc) && !empty($conf->global->MAIN_NO_CONCAT_DESCRIPTION)) $desc = $product_desc; + if (!empty($product_desc) && trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); $type = $productsupplier->type; if ($price_ht != '' || $price_ht_devise != '') { diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index e47390b9ce0..c2bcdef711f 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1587,6 +1587,8 @@ ServiceSetup=Services module setup ProductServiceSetup=Products and Services modules setup NumberOfProductShowInSelect=Maximum number of products to show in combo select lists (0=no limit) ViewProductDescInFormAbility=Display product descriptions in forms (otherwise shown in a tooltip popup) +DoNotAddProductDescAtAddLines=Do not add product description (from product card) on submit add lines on forms +OnProductSelectAddProductDesc=On product selection in forms get the production description into description line MergePropalProductCard=Activate in product/service Attached Files tab an option to merge product PDF document to proposal PDF azur if product/service is in the proposal ViewProductDescInThirdpartyLanguageAbility=Display products descriptions in the language of the third party UseSearchToSelectProductTooltip=Also if you have a large number of products (> 100 000), you can increase speed by setting constant PRODUCT_DONOTSEARCH_ANYWHERE to 1 in Setup->Other. Search will then be limited to start of string. @@ -2067,4 +2069,4 @@ TemplateDeleted=Template deleted MailToSendEventPush=Event reminder email SwitchThisForABetterSecurity=Switching this value to %s is recommended for more security DictionaryProductNature= Nature of product -CountryIfSpecificToOneCountry=Country (if specific to a given country) \ No newline at end of file +CountryIfSpecificToOneCountry=Country (if specific to a given country) diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index 313a27884ff..e7003c6ee47 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -145,6 +145,12 @@ if ($action == 'other') $value = GETPOST('activate_useProdFournDesc', 'alpha'); $res = dolibarr_set_const($db, "PRODUIT_FOURN_TEXTS", $value, 'chaine', 0, '', $conf->entity); + $value = GETPOST('activate_FillProductDescAuto', 'alpha'); + $res = dolibarr_set_const($db, "PRODUIT_AUTOFILL_DESC", $value, 'chaine', 0, '', $conf->entity); + + $value = GETPOST('activate_DoNotAddStdProductDescOnAddLine', 'alpha'); + $res = dolibarr_set_const($db, "MAIN_NO_CONCAT_DESCRIPTION", $value, 'chaine', 0, '', $conf->entity); + if ($value) { $sql_test = "SELECT count(desc_fourn) as cpt FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE 1"; $resql = $db->query($sql_test); @@ -630,6 +636,23 @@ print $form->selectyesno("activate_viewProdDescInForm", $conf->global->PRODUIT_D print ''; print ''; +// Do Not Add Product description on add lines +print ''; +print ''.$langs->trans("DoNotAddProductDescAtAddLines").''; +print ''; +print $form->selectyesno("activate_DoNotAddStdProductDescOnAddLine", $conf->global->MAIN_NO_CONCAT_DESCRIPTION, 1); +print ''; +print ''; + +// Do Not Add Product description on add lines +print ''; +print ''.$langs->trans("OnProductSelectAddProductDesc").''; +print ''; +print $form->selectyesno("activate_FillProductDescAuto", $conf->global->PRODUIT_AUTOFILL_DESC, 1); +print ''; +print ''; + + // Activate propal merge produt card /* Kept as hidden feature only. PRODUIT_PDF_MERGE_PROPAL can be added manually. Still did not understand how this feature works. diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index c2b698c8e04..40249e4041e 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -99,6 +99,9 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) $outputlangs->setDefaultLang($newlang); $outdesc_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["description"])) ? $object->multilangs[$outputlangs->defaultlang]["description"] : $object->description; $outlabel_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["label"])) ? $object->multilangs[$outputlangs->defaultlang]["label"] : $object->label; + } else { + $outdesc_trans = $object->description; + $outlabel_trans = $object->label; } } } From 88b570926f7ab66c829d979545a8b700445128bd Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 28 Oct 2020 15:38:31 +0000 Subject: [PATCH 017/223] Fixing style errors. --- htdocs/core/tpl/objectline_create.tpl.php | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index f1faf50e991..bc04e7b6614 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -678,13 +678,13 @@ if (!empty($usemargins) && $user->rights->margins->creer) if (!empty($conf->global->PRODUIT_AUTOFILL_DESC)) { if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { ?> var proddesc = data.desc_trans; - var proddesc = data.desc; - console.log("Load desciption into text area : "+proddesc); - global->FCKEDITOR_ENABLE_DETAILS)) { ?> if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") { @@ -693,12 +693,12 @@ if (!empty($usemargins) && $user->rights->margins->creer) editor.setData(proddesc); } } - jQuery('#dp_desc').text(proddesc); - - }, 'json' @@ -873,12 +873,12 @@ if (!empty($usemargins) && $user->rights->margins->creer) global->PRODUIT_AUTOFILL_DESC)) { - ?> + ?> var description = $('option:selected', this).attr('data-description'); if (typeof description == 'undefined') { description = jQuery('#idprodfournprice').attr('data-description'); } console.log("Load desciption into text area : "+description); - global->FCKEDITOR_ENABLE_DETAILS)) { ?> if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined") { @@ -887,10 +887,10 @@ if (!empty($usemargins) && $user->rights->margins->creer) editor.setData(description); } } - jQuery('#dp_desc').text(description); - } else if (jQuery('#idprodfournprice').length > 0) { @@ -904,10 +904,10 @@ if (!empty($usemargins) && $user->rights->margins->creer) editor.setData(''); } } - + jQuery('#dp_desc').text(''); - } From 11099132da9783cc3b4b0f7eacec8ee1e9d7f086 Mon Sep 17 00:00:00 2001 From: bahfir abbes Date: Fri, 6 Nov 2020 00:45:30 +0100 Subject: [PATCH 018/223] New: add notification on ACTION_CREATE event --- htdocs/core/class/notify.class.php | 27 ++++++++++++++----- ..._50_modNotification_Notification.class.php | 3 ++- .../mysql/data/llx_c_action_trigger.sql | 2 +- htdocs/langs/en_US/other.lang | 2 ++ htdocs/langs/fr_FR/other.lang | 2 ++ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 6547b98471a..fb0ce5a91f5 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -81,7 +81,8 @@ class Notify 'EXPENSE_REPORT_VALIDATE', 'EXPENSE_REPORT_APPROVE', 'HOLIDAY_VALIDATE', - 'HOLIDAY_APPROVE' + 'HOLIDAY_APPROVE', + 'ACTION_CREATE' ); @@ -502,12 +503,18 @@ class Notify $object_type = 'holiday'; $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayValidated", $link); break; - case 'HOLIDAY_APPROVE': - $link = ''.$newref.''; - $dir_output = $conf->holiday->dir_output; - $object_type = 'holiday'; - $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link); - break; + case 'HOLIDAY_APPROVE': + $link = ''.$newref.''; + $dir_output = $conf->holiday->dir_output; + $object_type = 'holiday'; + $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link); + break; + case 'ACTION_CREATE': + $link = ''.$newref.''; + $dir_output = $conf->agenda->dir_output; + $object_type = 'action'; + $mesg = $outputlangs->transnoentitiesnoconv("EMailTextActionAdded", $link); + break; } $ref = dol_sanitizeFileName($newref); $pdf_path = $dir_output."/".$ref."/".$ref.".pdf"; @@ -718,6 +725,12 @@ class Notify $object_type = 'holiday'; $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayApproved", $link); break; + case 'ACTION_CREATE': + $link = ''.$newref.''; + $dir_output = $conf->agenda->dir_output; + $object_type = 'action'; + $mesg = $langs->transnoentitiesnoconv("EMailTextActionAdded", $link); + break; } $ref = dol_sanitizeFileName($newref); $pdf_path = $dir_output."/".$ref."/".$ref.".pdf"; diff --git a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php index c5a4f450e42..a6078796478 100644 --- a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php +++ b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php @@ -46,7 +46,8 @@ class InterfaceNotification extends DolibarrTriggers 'EXPENSE_REPORT_VALIDATE', 'EXPENSE_REPORT_APPROVE', 'HOLIDAY_VALIDATE', - 'HOLIDAY_APPROVE' + 'HOLIDAY_APPROVE', + 'ACTION_CREATE' ); /** diff --git a/htdocs/install/mysql/data/llx_c_action_trigger.sql b/htdocs/install/mysql/data/llx_c_action_trigger.sql index eeca137dbc0..c72a8ab7f40 100644 --- a/htdocs/install/mysql/data/llx_c_action_trigger.sql +++ b/htdocs/install/mysql/data/llx_c_action_trigger.sql @@ -145,4 +145,4 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_CREATE','Task created','Executed when a project task is created','project',150); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_MODIFY','Task modified','Executed when a project task is modified','project',151); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_DELETE','Task deleted','Executed when a project task is deleted','project',152); - +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ACTION_CREATE','Action added','Executed when an action is added to the agenda','agenda',700); diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index 7495291cf3f..40f4f019793 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -78,6 +78,7 @@ Notify_EXPENSE_REPORT_VALIDATE=Expense report validated (approval required) Notify_EXPENSE_REPORT_APPROVE=Expense report approved Notify_HOLIDAY_VALIDATE=Leave request validated (approval required) Notify_HOLIDAY_APPROVE=Leave request approved +Notify_ACTION_CREATE=Added action to Agenda SeeModuleSetup=See setup of module %s NbOfAttachedFiles=Number of attached files/documents TotalSizeOfAttachedFiles=Total size of attached files/documents @@ -215,6 +216,7 @@ EMailTextExpenseReportValidated=Expense report %s has been validated. EMailTextExpenseReportApproved=Expense report %s has been approved. EMailTextHolidayValidated=Leave request %s has been validated. EMailTextHolidayApproved=Leave request %s has been approved. +EMailTextActionAdded=The action %s has been added to the Agenda. ImportedWithSet=Importation data set DolibarrNotification=Automatic notification ResizeDesc=Enter new width OR new height. Ratio will be kept during resizing... diff --git a/htdocs/langs/fr_FR/other.lang b/htdocs/langs/fr_FR/other.lang index 0a5abbfbf3a..5120fd52e67 100644 --- a/htdocs/langs/fr_FR/other.lang +++ b/htdocs/langs/fr_FR/other.lang @@ -78,6 +78,7 @@ Notify_EXPENSE_REPORT_VALIDATE=Note de frais validée (approbation requise) Notify_EXPENSE_REPORT_APPROVE=Note de frais approuvé Notify_HOLIDAY_VALIDATE=Demande de congé validée (approbation requise) Notify_HOLIDAY_APPROVE=Demande de congé approuvée +Notify_ACTION_CREATE=Ajout d'action à l'agenda SeeModuleSetup=Voir la configuration du module %s NbOfAttachedFiles=Nombre de fichiers/documents liés TotalSizeOfAttachedFiles=Taille totale fichiers/documents liés @@ -218,6 +219,7 @@ EMailTextExpenseReportValidated=La note de frais %s a été validée. EMailTextExpenseReportApproved=La note de frais %s a été approuvée. EMailTextHolidayValidated=La demande de congé %s a été validée. EMailTextHolidayApproved=La demande de congé %s a été approuvée. +EMailTextActionAdded=L'action %s a été ajoutée à l'Agenda. ImportedWithSet=Lot d'importation (Import key) DolibarrNotification=Notification automatique ResizeDesc=Entrer la nouvelle largeur OU la nouvelle hauteur. Le ratio d'aspect est conservé lors du redimensionnement… From f4566fe0f1fa8dace06466e45e65ccc690bb1ffd Mon Sep 17 00:00:00 2001 From: Bahfir Abbes Date: Mon, 9 Nov 2020 22:20:20 +0100 Subject: [PATCH 019/223] fix:link name --- htdocs/core/class/notify.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index fb0ce5a91f5..75d6a33c43b 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -510,7 +510,7 @@ class Notify $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link); break; case 'ACTION_CREATE': - $link = ''.$newref.''; + $link = ''.$newref.''; $dir_output = $conf->agenda->dir_output; $object_type = 'action'; $mesg = $outputlangs->transnoentitiesnoconv("EMailTextActionAdded", $link); @@ -726,7 +726,7 @@ class Notify $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayApproved", $link); break; case 'ACTION_CREATE': - $link = ''.$newref.''; + $link = ''.$newref.''; $dir_output = $conf->agenda->dir_output; $object_type = 'action'; $mesg = $langs->transnoentitiesnoconv("EMailTextActionAdded", $link); From 2c1d4049be08c850dd79a194993b2cf2cbfe2b80 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 17:24:17 +0100 Subject: [PATCH 020/223] Enable list filtering on date and datetime extrafields --- htdocs/core/class/extrafields.class.php | 60 +++++++++++++++---- .../tpl/extrafields_list_search_input.tpl.php | 4 +- .../tpl/extrafields_list_search_param.tpl.php | 15 +++++ .../tpl/extrafields_list_search_sql.tpl.php | 10 +++- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 4b6f43bd06e..459a7b1820d 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -948,15 +948,15 @@ class ExtraFields * Return HTML string to put an input field into a page * Code very similar with showInputField of common object * - * @param string $key Key of attribute - * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value) - * @param string $moreparam To add more parametes on html input tag - * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) - * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) - * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) - * @param int $objectid Current object id - * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data - * @param string $mode 1=Used for search filters + * @param string $key Key of attribute + * @param string|array $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=>, 'end'=>) should be provided + * @param string $moreparam To add more parametes on html input tag + * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) + * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) + * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) + * @param int $objectid Current object id + * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data + * @param string $mode 1=Used for search filters * @return string */ public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0) @@ -1069,8 +1069,23 @@ class ExtraFields // Do not show current date when field not required (see selectDate() method) if (!$required && $value == '') $value = '-1'; + if ($mode == 1) { + // search filter on a date extrafield shows two inputs to select a date range + $prefill = array( + 'start' => isset($value['start']) ? $value['start'] : '', + 'end' => isset($value['end']) ? $value['end'] : ''); + $out = '
' + . $langs->trans('From') . ' ' + . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) + . '
' + . '
' + . $langs->trans('to') . ' ' + . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) + . '
'; + } else { + $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); + } // TODO Must also support $moreparam - $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); } elseif (in_array($type, array('int', 'integer'))) { @@ -2162,9 +2177,28 @@ class ExtraFields if (in_array($key_type, array('date', 'datetime'))) { - if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it. - // Clean parameters - $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); + $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start'; + $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end'; + if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) { + // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc. + $value_key = array( + 'start' => mktime( + 0, 0, 0, + GETPOST($dateparamname_start . 'month', 'int'), + GETPOST($dateparamname_start . 'day', 'int'), + GETPOST($dateparamname_start . 'year', 'int')), + 'end' => mktime( + 23, 59, 59, + GETPOST($dateparamname_end . 'month', 'int'), + GETPOST($dateparamname_end . 'day', 'int'), + GETPOST($dateparamname_end . 'year', 'int')) + ); + } elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) { + // Clean parameters + $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int')); + } else { + continue; // Value was not provided, we should not set it. + } } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) { diff --git a/htdocs/core/tpl/extrafields_list_search_input.tpl.php b/htdocs/core/tpl/extrafields_list_search_input.tpl.php index 6e1dae186b1..7fece2efd1d 100644 --- a/htdocs/core/tpl/extrafields_list_search_input.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_input.tpl.php @@ -36,8 +36,8 @@ if (!empty($extrafieldsobjectkey)) // $extrafieldsobject is the $object->table_e } elseif (in_array($typeofextrafield, array('datetime', 'timestamp'))) { - // TODO - // Use showInputField in a particular manner to have input with a comparison operator, not input for a specific value date-hour-minutes + $morecss = ''; + echo $extrafields->showInputField($key, $search_array_options[$search_options_pattern.$tmpkey], '', '', $search_options_pattern, $morecss, 0, $extrafieldsobjectkey, 1); } else { diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 6e6d6305106..009d05b30ee 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -16,6 +16,21 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf { $crit = $val; $tmpkey = preg_replace('/'.$search_options_pattern.'/', '', $key); + if (is_array($val) && array_key_exists('start', $val) && array_key_exists('end', $val)) { + // date range from list filters is stored as array('start' => , 'end' => ) + // start date + $param .= '&' . $search_options_pattern.$tmpkey.'_startyear' . '=' . intval(dol_print_date($val['start'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth' . '=' . intval(dol_print_date($val['start'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startday' . '=' . intval(dol_print_date($val['start'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_starthour' . '=' . intval(dol_print_date($val['start'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmin' . '=' . intval(dol_print_date($val['start'], '%M')); + // end date + $param .= '&' . $search_options_pattern.$tmpkey.'_endyear' . '=' . intval(dol_print_date($val['end'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth' . '=' . intval(dol_print_date($val['end'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endday' . '=' . intval(dol_print_date($val['end'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endhour' . '=' . intval(dol_print_date($val['end'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmin' . '=' . intval(dol_print_date($val['end'], '%M')); + } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); } } diff --git a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php index 03d487ee0c0..048ca24020a 100644 --- a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php @@ -23,7 +23,15 @@ if (!empty($extrafieldsobjectkey) && !empty($search_array_options) && is_array($ if ($crit != '' && in_array($typ, array('date', 'datetime', 'timestamp'))) { - $sql .= " AND ".$extrafieldsobjectprefix.$tmpkey." = '".$db->idate($crit)."'"; + if (is_numeric($crit)) { + $sql .= " AND ".$extrafieldsobjectprefix.$tmpkey." = '".$db->idate($crit)."'"; + } elseif (is_array($crit)) { + $sql .= ' AND (' . $extrafieldsobjectprefix.$tmpkey + .' BETWEEN "' + . $db->idate($crit['start']) + . '" AND "' + . $db->idate($crit['end']) . '")'; + } } elseif (in_array($typ, array('boolean'))) { From a64c4b0cb5a74de2514279b311d4a7f765b80716 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 17:29:03 +0100 Subject: [PATCH 021/223] support for $moreparam --- htdocs/core/class/extrafields.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 459a7b1820d..a188dafd885 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -950,7 +950,7 @@ class ExtraFields * * @param string $key Key of attribute * @param string|array $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=>, 'end'=>) should be provided - * @param string $moreparam To add more parametes on html input tag + * @param string $moreparam To add more parameters on html input tag * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) @@ -1074,18 +1074,18 @@ class ExtraFields $prefill = array( 'start' => isset($value['start']) ? $value['start'] : '', 'end' => isset($value['end']) ? $value['end'] : ''); - $out = '
' + $out = '
' . $langs->trans('From') . ' ' . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) . '
' . '
' . $langs->trans('to') . ' ' . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) - . '
'; + . '
'; } else { + // TODO Must also support $moreparam $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); } - // TODO Must also support $moreparam } elseif (in_array($type, array('int', 'integer'))) { From 952f398a609cc112e4f06748b54a24b80f6650f4 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 10 Nov 2020 23:50:42 +0100 Subject: [PATCH 022/223] Apply stickler CI recommendation to avoid concatenating string literals --- htdocs/core/class/extrafields.class.php | 3 +-- .../tpl/extrafields_list_search_param.tpl.php | 20 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index a188dafd885..b5d4852d128 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1077,8 +1077,7 @@ class ExtraFields $out = '
' . $langs->trans('From') . ' ' . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) - . '
' - . '
' + . '
' . $langs->trans('to') . ' ' . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) . '
'; diff --git a/htdocs/core/tpl/extrafields_list_search_param.tpl.php b/htdocs/core/tpl/extrafields_list_search_param.tpl.php index 009d05b30ee..902d4df59ca 100644 --- a/htdocs/core/tpl/extrafields_list_search_param.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_param.tpl.php @@ -19,17 +19,17 @@ if (!empty($search_array_options) && is_array($search_array_options)) // $extraf if (is_array($val) && array_key_exists('start', $val) && array_key_exists('end', $val)) { // date range from list filters is stored as array('start' => , 'end' => ) // start date - $param .= '&' . $search_options_pattern.$tmpkey.'_startyear' . '=' . intval(dol_print_date($val['start'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth' . '=' . intval(dol_print_date($val['start'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startday' . '=' . intval(dol_print_date($val['start'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_starthour' . '=' . intval(dol_print_date($val['start'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_startmin' . '=' . intval(dol_print_date($val['start'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startyear=' . intval(dol_print_date($val['start'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmonth=' . intval(dol_print_date($val['start'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startday=' . intval(dol_print_date($val['start'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_starthour=' . intval(dol_print_date($val['start'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_startmin=' . intval(dol_print_date($val['start'], '%M')); // end date - $param .= '&' . $search_options_pattern.$tmpkey.'_endyear' . '=' . intval(dol_print_date($val['end'], '%Y')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth' . '=' . intval(dol_print_date($val['end'], '%m')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endday' . '=' . intval(dol_print_date($val['end'], '%d')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endhour' . '=' . intval(dol_print_date($val['end'], '%H')); - $param .= '&' . $search_options_pattern.$tmpkey.'_endmin' . '=' . intval(dol_print_date($val['end'], '%M')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endyear=' . intval(dol_print_date($val['end'], '%Y')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmonth=' . intval(dol_print_date($val['end'], '%m')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endday=' . intval(dol_print_date($val['end'], '%d')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endhour=' . intval(dol_print_date($val['end'], '%H')); + $param .= '&' . $search_options_pattern.$tmpkey.'_endmin=' . intval(dol_print_date($val['end'], '%M')); } if ($val != '') $param .= '&'.$search_options_pattern.$tmpkey.'='.urlencode($val); } From 13f985d28085753683212eff42fd8e39cbcd2974 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Fri, 4 Dec 2020 04:13:42 +0100 Subject: [PATCH 023/223] NEW: Accountancy - Introduce "Level3" - Define account directly in thirdparty --- htdocs/accountancy/customer/index.php | 16 ++- htdocs/accountancy/customer/list.php | 38 ++++-- htdocs/accountancy/supplier/index.php | 14 +- htdocs/accountancy/supplier/list.php | 32 ++++- .../install/mysql/migration/13.0.0-14.0.0.sql | 36 +++++ htdocs/install/mysql/tables/llx_societe.sql | 3 + htdocs/langs/en_US/accountancy.lang | 1 + htdocs/societe/card.php | 124 +++++++++++++++++- htdocs/societe/class/societe.class.php | 101 +++++++++++++- 9 files changed, 338 insertions(+), 27 deletions(-) create mode 100644 htdocs/install/mysql/migration/13.0.0-14.0.0.sql diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 1a5098bda38..3634fba2e79 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -1,7 +1,7 @@ * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013-2017 Alexandre Spangaro + * Copyright (C) 2013-2020 Alexandre Spangaro * Copyright (C) 2014 Juanjo Menent * Copyright (C) 2015 Jean-François Ferry * @@ -123,9 +123,9 @@ if ($action == 'validatehistory') { $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; - $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; + $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; - $sql .= " s.tva_intra"; + $sql .= " s.tva_intra, s.accountancy_code_sell as company_code_sell"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; @@ -134,6 +134,7 @@ if ($action == 'validatehistory') { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; @@ -153,7 +154,7 @@ if ($action == 'validatehistory') { $isBuyerInEEC = isInEEC($objp); - // Search suggested account for product/service (similar code exists in page list.php to make manual binding) + // Level 2: Search suggested account for product/service (similar code exists in page list.php to make manual binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_sell_p = $objp->code_sell; @@ -179,6 +180,13 @@ if ($action == 'validatehistory') { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_sell)) { + $objp->code_sell_t = $objp->company_code_sell; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if ($objp->aarowid_suggest > 0) { $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."facturedet"; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index eb2743258d7..88464dcf95d 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -211,9 +211,9 @@ $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; $sql .= " p.tosell as status, p.tobuy as status_buy,"; -$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; +$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; -$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur"; +$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur, s.accountancy_code_sell as company_code_sell"; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; @@ -225,6 +225,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; // Define begin binding date @@ -456,11 +457,12 @@ if ($result) { $facture_static->type = $objp->ftype; $code_sell_p_notset = ''; + $code_sell_t_notset = ''; $objp->aarowid_suggest = ''; // Will be set later $isBuyerInEEC = isInEEC($objp); - // Search suggested default account for product/service + // Level 1: Search suggested default account for product/service $suggestedaccountingaccountbydefaultfor = ''; if ($objp->type_l == 1) { if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) @@ -503,7 +505,7 @@ if ($result) { } if ($objp->code_sell_l == -1) $objp->code_sell_l = ''; - // Search suggested account for product/service (similar code exists in page index.php to make automatic binding) + // Level 2: Search suggested account for product/service (similar code exists in page index.php to make automatic binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_sell_p = $objp->code_sell; @@ -529,6 +531,13 @@ if ($result) { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_sell)) { + $objp->code_sell_t = $objp->company_code_sell; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + // Manage Deposit if ($objp->description == "(DEPOSIT)") { $accountdeposittoventilated = new AccountingAccount($db); @@ -547,6 +556,7 @@ if ($result) { // $objp->code_sell_l is now default code of product/service // $objp->code_sell_p is now code of product/service + // $objp->code_sell_t is now code of thirdparty print ''; @@ -596,7 +606,7 @@ if ($result) { // Found accounts print ''; - $s = ''.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport"); @@ -605,7 +615,7 @@ if ($result) { if ($objp->product_id > 0) { print '
'; - $s = ''.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountfor == 'eecwithvat') $shelp = $langs->trans("SaleEECWithVAT"); @@ -613,16 +623,23 @@ if ($result) { elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport"); $s .= (empty($objp->code_sell_p) ? ''.$langs->trans("NotDefined").'' : length_accountg($objp->code_sell_p)); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + } else { + print '
'; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $shelp = ''; + $s .= $langs->trans("NotDefined"); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } + print '
'; + $s = '3. '.$langs->trans("DefaultForThirdparty").': '; + $shelp = ''; + $s .= ($objp->code_sell_t > 0 ? length_accountg($objp->code_sell_t) : ''.$langs->trans("NotDefined").''); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); print ''; // Suggested accounting account - // $objp->code_sell_l = default (it takes the country into consideration), $objp->code_sell_p is value for product (it takes the country into consideration too) print ''; $suggestedid = $objp->aarowid_suggest; - /*var_dump($suggestedid); - var_dump($objp->code_sell_p); - var_dump($objp->code_sell_l);*/ if (empty($suggestedid) && empty($objp->code_sell_p) && !empty($objp->code_sell_l) && empty($conf->global->ACCOUNTANCY_DO_NOT_AUTOFILL_ACCOUNT_WITH_GENERIC)) { if (empty($accountingaccount_codetotid_cache[$objp->code_sell_l])) @@ -642,7 +659,6 @@ if ($result) { // Column with checkbox print ''; - //var_dump($objp->aarowid);var_dump($objp->aarowid_intra);var_dump($objp->aarowid_export);var_dump($objp->aarowid_suggest); $ischecked = $objp->aarowid_suggest; if ($suggestedaccountingaccountfor == 'eecwithoutvatnumber') $ischecked = 0; print ''; diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 0dbe09fa468..9dd097f3d0c 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -120,9 +120,9 @@ if ($action == 'validatehistory') { $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export, p.tva_tx as tva_tx_prod,"; - $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; + $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; - $sql .= " s.tva_intra"; + $sql .= " s.tva_intra, s.accountancy_code_buy as company_code_buy"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; @@ -131,6 +131,7 @@ if ($action == 'validatehistory') { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; @@ -151,7 +152,7 @@ if ($action == 'validatehistory') { $isSellerInEEC = isInEEC($objp); - // Search suggested account for product/service + // Level 2: Search suggested account for product/service (similar code exists in page list.php to make manual binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_buy_p = $objp->code_buy; @@ -169,6 +170,13 @@ if ($action == 'validatehistory') { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_buy)) { + $objp->code_buy_t = $objp->company_code_buy; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if ($objp->aarowid_suggest > 0) { $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det"; diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index cbdecd2e85e..6f1f4c25a9f 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -215,9 +215,9 @@ $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; $sql .= " p.tosell as status, p.tobuy as status_buy,"; -$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; +$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; -$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur"; +$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur, s.accountancy_code_buy as company_code_buy"; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; @@ -229,6 +229,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; // Define begin binding date @@ -460,10 +461,12 @@ if ($result) { $facturefourn_static->label = $objp->invoice_label; $code_buy_p_notset = ''; + $code_buy_t_notset = ''; $objp->aarowid_suggest = ''; // Will be set later $isSellerInEEC = isInEEC($objp); + // Level 1: Search suggested default account for product/service $suggestedaccountingaccountbydefaultfor = ''; if ($objp->type_l == 1) { if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) @@ -494,7 +497,7 @@ if ($result) { } if ($objp->code_sell_l == -1) $objp->code_sell_l = ''; - // Search suggested account for product/service + // Level 2: Search suggested account for product/service (similar code exists in page index.php to make automatic binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_buy_p = $objp->code_buy; @@ -512,6 +515,13 @@ if ($result) { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_buy)) { + $objp->code_buy_t = $objp->company_code_buy; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if (!empty($objp->code_buy_p)) { // Value was defined previously } else { @@ -521,6 +531,7 @@ if ($result) { // $objp->code_buy_l is now default code of product/service // $objp->code_buy_p is now code of product/service + // $objp->code_buy_t is now code of thirdparty print ''; @@ -576,7 +587,7 @@ if ($result) { // Found accounts print ''; - $s = ''.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport"); @@ -585,13 +596,24 @@ if ($result) { if ($objp->product_id > 0) { print '
'; - $s = ''.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport"); $s .= (empty($objp->code_buy_p) ? ''.$langs->trans("NotDefined").'' : length_accountg($objp->code_buy_p)); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + } else { + print '
'; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $shelp = ''; + $s .= $langs->trans("NotDefined"); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } + print '
'; + $s = '3. '.$langs->trans("DefaultForThirdparty").': '; + $shelp = ''; + $s .= ($objp->code_buy_t > 0 ? length_accountg($objp->code_buy_t) : ''.$langs->trans("NotDefined").''); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); print ''; // Suggested accounting account diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql new file mode 100644 index 00000000000..706ead91506 --- /dev/null +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -0,0 +1,36 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 14.0.0 or higher. +-- +-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y +-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex +-- To make pk to be auto increment (mysql): -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. + + +-- Missing in v13 + +-- For v14 + +ALTER TABLE llx_societe ADD COLUMN accountancy_code_sell varchar(32) AFTER webservices_key; +ALTER TABLE llx_societe ADD COLUMN accountancy_code_buy varchar(32) AFTER accountancy_code_sell; diff --git a/htdocs/install/mysql/tables/llx_societe.sql b/htdocs/install/mysql/tables/llx_societe.sql index ea02b7be8ad..27503d82727 100644 --- a/htdocs/install/mysql/tables/llx_societe.sql +++ b/htdocs/install/mysql/tables/llx_societe.sql @@ -116,6 +116,9 @@ create table llx_societe webservices_url varchar(255), -- supplier webservice url webservices_key varchar(128), -- supplier webservice key + accountancy_code_sell varchar(32), -- Selling accountancy code + accountancy_code_buy varchar(32), -- Buying accountancy code + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- last modification date datec datetime, -- creation date fk_user_creat integer NULL, -- utilisateur qui a cree l'info diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 3211a0b62df..32f7949f3ef 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -16,6 +16,7 @@ ThisService=This service ThisProduct=This product DefaultForService=Default for service DefaultForProduct=Default for product +DefaultForThirdparty=Default for thirdparty CantSuggest=Can't suggest AccountancySetupDoneFromAccountancyMenu=Most setup of the accountancy is done from the menu %s ConfigAccountingExpert=Configuration of the module accounting (double entry) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 7d7dcbe86c3..c49d6115cc5 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -46,6 +46,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; if (!empty($conf->adherent->enabled)) require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; $langs->loadLangs(array("companies", "commercial", "bills", "banks", "users")); if (!empty($conf->adherent->enabled)) $langs->load("members"); @@ -476,6 +479,9 @@ if (empty($reshook)) $object->webservices_url = GETPOST('webservices_url', 'custom', 0, FILTER_SANITIZE_URL); $object->webservices_key = GETPOST('webservices_key', 'san_alpha'); + $object->accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha'); + $object->accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + // Incoterms if (!empty($conf->incoterm->enabled)) { @@ -890,6 +896,7 @@ $form = new Form($db); $formfile = new FormFile($db); $formadmin = new FormAdmin($db); $formcompany = new FormCompany($db); +if (! empty($conf->accounting->enabled)) $formaccounting = new FormAccounting($db); if ($socid > 0 && empty($object->id)) { @@ -1030,6 +1037,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) $object->commercial_id = GETPOST('commercial_id', 'int'); $object->default_lang = GETPOST('default_lang'); + $object->accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha'); + $object->accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + $object->logo = (isset($_FILES['photo']) ?dol_sanitizeFileName($_FILES['photo']['name']) : ''); // Gestion du logo de la société @@ -1546,6 +1556,47 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''."\n"; + // Accountancy codes + print ''; + + if (! empty($conf->accounting->enabled)) + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + else // For external software + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + print '
'.$langs->trans("ProductAccountancySellCode").''; + if($type == 0) { + $accountancy_code_sell = (GETPOST('accountancy_code_sell', 'alpha')?(GETPOST('accountancy_code_sell', 'alpha')):$conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT); + } else { + $accountancy_code_sell = (GETPOST('accountancy_code_sell', 'alpha')?(GETPOST('accountancy_code_sell', 'alpha')):$conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT); + } + print $formaccounting->select_account($accountancy_code_sell, 'accountancy_code_sell', 1, null, 1, 1, ''); + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + if($type == 0) { + $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha')?(GETPOST('accountancy_code_buy', 'alpha')):$conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT); + } else { + $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha')?(GETPOST('accountancy_code_buy', 'alpha')):$conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT); + } + print $formaccounting->select_account($accountancy_code_buy, 'accountancy_code_buy', 1, null, 1, 1, ''); + print '
'.$langs->trans("ProductAccountancySellCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print '
'; + print dol_get_fiche_end(); print '
'; @@ -1661,6 +1712,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) $object->webservices_url = GETPOST('webservices_url', 'custom', 0, FILTER_SANITIZE_URL); $object->webservices_key = GETPOST('webservices_key', 'san_alpha'); + $object->accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha'); + $object->accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + //Incoterms if (!empty($conf->incoterm->enabled)) { @@ -2188,10 +2242,42 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print $form->multiselectarray('commercial', $userlist, $arrayselected, null, null, null, null, "90%"); print ''; + print ''; + + print '
'; + + print ''; + + if (! empty($conf->accounting->enabled)) + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + else // For external software + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } print '
'.$langs->trans("ProductAccountancySellCode").''; + print $formaccounting->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 1, 1); + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print $formaccounting->select_account($object->accountancy_code_buy, 'accountancy_code_buy', 1, '', 1, 1); + print '
'.$langs->trans("ProductAccountancySellCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print '
'; print '
'; - print dol_get_fiche_end(); + print dol_get_fiche_end(); print '
'; print ''; @@ -2550,6 +2636,42 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''; } + // Accountancy sell code + print ''; + print $langs->trans("ProductAccountancySellCode"); + print ''; + if (! empty($conf->accounting->enabled)) + { + if (! empty($object->accountancy_code_sell)) + { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('', $object->accountancy_code_sell, 1); + + print $accountingaccount->getNomUrl(0, 1, 1, '', 1); + } + } else { + print $object->accountancy_code_sell; + } + print ''; + + // Accountancy buy code + print ''; + print $langs->trans("ProductAccountancyBuyCode"); + print ''; + if (! empty($conf->accounting->enabled)) + { + if (! empty($object->accountancy_code_buy)) + { + $accountingaccount2 = new AccountingAccount($db); + $accountingaccount2->fetch('', $object->accountancy_code_buy, 1); + + print $accountingaccount2->getNomUrl(0, 1, 1, '', 1); + } + } else { + print $object->accountancy_code_buy; + } + print ''; + // Other attributes $parameters = array('socid'=>$socid, 'colspan' => ' colspan="3"', 'colspanvalue' => '3'); include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 73c41aeb782..b3b3497dcf5 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -693,6 +693,15 @@ class Societe extends CommonObject */ public $logo_squarred_mini; + /** + * @var string Accountancy account for sales + */ + public $accountancy_code_sell; + + /** + * @var string Accountancy account for bought + */ + public $accountancy_code_buy; // Multicurrency /** @@ -792,6 +801,9 @@ class Societe extends CommonObject if (empty($this->fournisseur)) $this->fournisseur = 0; $this->import_key = trim($this->import_key); + $this->accountancy_code_buy = trim($this->accountancy_code_buy); + $this->accountancy_code_sell= trim($this->accountancy_code_sell); + if (!empty($this->multicurrency_code)) $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); if (empty($this->fk_multicurrency)) { @@ -817,8 +829,24 @@ class Societe extends CommonObject { $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."societe (nom, name_alias, entity, datec, fk_user_creat, canvas, status, ref_ext, fk_stcomm, fk_incoterms, location_incoterms ,import_key, fk_multicurrency, multicurrency_code)"; - $sql .= " VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".$this->db->escape($this->entity).", '".$this->db->idate($now)."'"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."societe ("; + $sql .= "nom"; + $sql .= ", name_alias"; + $sql .= ", entity"; + $sql .= ", datec"; + $sql .= ", fk_user_creat"; + $sql .= ", canvas"; + $sql .= ", status"; + $sql .= ", ref_ext"; + $sql .= ", fk_stcomm"; + $sql .= ", fk_incoterms"; + $sql .= ", location_incoterms"; + $sql .= ", import_key"; + $sql .= ", fk_multicurrency"; + $sql .= ", multicurrency_code"; + $sql .= ", accountancy_code_buy"; + $sql .= ", accountancy_code_sell"; + $sql .= ") VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".$this->db->escape($this->entity).", '".$this->db->idate($now)."'"; $sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null"); $sql .= ", ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null"); $sql .= ", ".$this->status; @@ -828,7 +856,10 @@ class Societe extends CommonObject $sql .= ", '".$this->db->escape($this->location_incoterms)."'"; $sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null"); $sql .= ", ".(int) $this->fk_multicurrency; - $sql .= ", '".$this->db->escape($this->multicurrency_code)."')"; + $sql .= ", '".$this->db->escape($this->multicurrency_code)."'"; + $sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'"; + $sql .= ", '".$this->db->escape($this->accountancy_code_sell)."'"; + $sql .= ")"; dol_syslog(get_class($this)."::create", LOG_DEBUG); $result = $this->db->query($sql); @@ -1196,6 +1227,9 @@ class Societe extends CommonObject $this->webservices_url = $this->webservices_url ?clean_url($this->webservices_url, 0) : ''; $this->webservices_key = trim($this->webservices_key); + $this->accountancy_code_buy = trim($this->accountancy_code_buy); + $this->accountancy_code_sell= trim($this->accountancy_code_sell); + //Incoterms $this->fk_incoterms = (int) $this->fk_incoterms; $this->location_incoterms = trim($this->location_incoterms); @@ -1320,6 +1354,9 @@ class Societe extends CommonObject $sql .= ",supplier_order_min_amount= ".($this->supplier_order_min_amount != '' ? $this->supplier_order_min_amount : 'null'); $sql .= ",fk_prospectlevel='".$this->db->escape($this->fk_prospectlevel)."'"; + $sql.= ", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy)."'"; + $sql.= ", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell)."'"; + $sql .= ",webservices_url = ".(!empty($this->webservices_url) ? "'".$this->db->escape($this->webservices_url)."'" : "null"); $sql .= ",webservices_key = ".(!empty($this->webservices_key) ? "'".$this->db->escape($this->webservices_key)."'" : "null"); @@ -1505,6 +1542,7 @@ class Societe extends CommonObject $sql .= ', s.fk_effectif as effectif_id'; $sql .= ', s.fk_forme_juridique as forme_juridique_code'; $sql .= ', s.webservices_url, s.webservices_key'; + $sql .= ', s.accountancy_code_buy, s.accountancy_code_sell'; $sql .= ', s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur, s.parent, s.barcode'; $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.remise_supplier, s.mode_reglement, s.cond_reglement, s.transport_mode'; $sql .= ', s.fk_account, s.tva_assuj'; @@ -1668,6 +1706,9 @@ class Societe extends CommonObject $this->webservices_url = $obj->webservices_url; $this->webservices_key = $obj->webservices_key; + $this->accountancy_code_buy = $obj->accountancy_code_buy; + $this->accountancy_code_sell = $obj->accountancy_code_sell; + $this->outstanding_limit = $obj->outstanding_limit; $this->order_min_amount = $obj->order_min_amount; $this->supplier_order_min_amount = $obj->supplier_order_min_amount; @@ -4403,4 +4444,58 @@ class Societe extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Sets an accountancy code for a thirdparty. + * Also calls COMPANY_MODIFY trigger when modified + * + * @param string $type It can be only 'buy' or 'sell' + * @param string $value Accountancy code + * @return int <0 KO >0 OK + */ + public function setAccountancyCode($type, $value) + { + global $user, $langs, $conf; + + $this->db->begin(); + + if ($type == 'buy') { + $field = 'accountancy_code_buy'; + } elseif ($type == 'sell') { + $field = 'accountancy_code_sell'; + } else { + return -1; + } + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET "; + $sql.= "$field = '".$this->db->escape($value)."'"; + $sql.= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::".__FUNCTION__." sql=".$sql, LOG_DEBUG); + $resql = $this->db->query($sql); + + if ($resql) { + // Call triggers + include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + $interface=new Interfaces($this->db); + $result=$interface->run_triggers('COMPANY_MODIFY', $this, $user, $langs, $conf); + if ($result < 0) { + $this->errors=$interface->errors; + $this->db->rollback(); + return -1; + } + // End call triggers + + $this->$field = $value; + + $this->db->commit(); + return 1; + } + else + { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } } From d6ac26dd8595d256b31ae5a599b2e6156975ae66 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 4 Dec 2020 03:23:48 +0000 Subject: [PATCH 024/223] Fixing style errors. --- htdocs/societe/card.php | 4 ++-- htdocs/societe/class/societe.class.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index c49d6115cc5..0e64117d632 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1564,7 +1564,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) // Accountancy_code_sell print ''.$langs->trans("ProductAccountancySellCode").''; print ''; - if($type == 0) { + if ($type == 0) { $accountancy_code_sell = (GETPOST('accountancy_code_sell', 'alpha')?(GETPOST('accountancy_code_sell', 'alpha')):$conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT); } else { $accountancy_code_sell = (GETPOST('accountancy_code_sell', 'alpha')?(GETPOST('accountancy_code_sell', 'alpha')):$conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT); @@ -1575,7 +1575,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) // Accountancy_code_buy print ''.$langs->trans("ProductAccountancyBuyCode").''; print ''; - if($type == 0) { + if ($type == 0) { $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha')?(GETPOST('accountancy_code_buy', 'alpha')):$conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT); } else { $accountancy_code_buy = (GETPOST('accountancy_code_buy', 'alpha')?(GETPOST('accountancy_code_buy', 'alpha')):$conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index b3b3497dcf5..c8fc2f58e74 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -4491,8 +4491,7 @@ class Societe extends CommonObject $this->db->commit(); return 1; } - else - { + else { $this->error=$this->db->lasterror(); $this->db->rollback(); return -1; From 54fad02936cfc37624128117a54c22d9e48bd7db Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 8 Dec 2020 13:55:51 +0100 Subject: [PATCH 025/223] Fix PR --- htdocs/accountancy/customer/list.php | 2 +- htdocs/accountancy/supplier/list.php | 2 +- htdocs/langs/en_US/accountancy.lang | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 88464dcf95d..cb47e436cbd 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -631,7 +631,7 @@ if ($result) { print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } print '
'; - $s = '3. '.$langs->trans("DefaultForThirdparty").': '; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; $shelp = ''; $s .= ($objp->code_sell_t > 0 ? length_accountg($objp->code_sell_t) : ''.$langs->trans("NotDefined").''); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 6f1f4c25a9f..919130e80d3 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -610,7 +610,7 @@ if ($result) { print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } print '
'; - $s = '3. '.$langs->trans("DefaultForThirdparty").': '; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; $shelp = ''; $s .= ($objp->code_buy_t > 0 ? length_accountg($objp->code_buy_t) : ''.$langs->trans("NotDefined").''); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 32f7949f3ef..d0fbc1644b3 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -16,7 +16,8 @@ ThisService=This service ThisProduct=This product DefaultForService=Default for service DefaultForProduct=Default for product -DefaultForThirdparty=Default for thirdparty +ProductForThisThirdparty=Product for this thirdparty +ServiceForThisThirdparty=Service for this thirdparty CantSuggest=Can't suggest AccountancySetupDoneFromAccountancyMenu=Most setup of the accountancy is done from the menu %s ConfigAccountingExpert=Configuration of the module accounting (double entry) From 64fa2120b2e6e577e66fd1e93e5035a61c510af7 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 15 Dec 2020 08:40:14 +0100 Subject: [PATCH 026/223] FIX: Link to subaccount ledger --- htdocs/accountancy/bookkeeping/listbyaccount.php | 2 +- htdocs/langs/en_US/accountancy.lang | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 18661f8a887..cd15eea52be 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -380,7 +380,7 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); - $newcardbutton .= dolGetButtonTitle($langs->trans('VueByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + $newcardbutton .= dolGetButtonTitle($langs->trans('VueBySubAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); $newcardbutton .= '   '; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 7b406af0c79..14bebea22df 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -50,6 +50,7 @@ CountriesExceptMe=All countries except %s AccountantFiles=Export source documents ExportAccountingSourceDocHelp=With this tool, you can export the source events (list and PDFs) that were used to generate your accountancy. To export your journals, use the menu entry %s - %s. VueByAccountAccounting=View by accounting account +VueBySubAccountAccounting=View by accounting subaccount MainAccountForCustomersNotDefined=Main accounting account for customers not defined in setup MainAccountForSuppliersNotDefined=Main accounting account for vendors not defined in setup From 31e5709e0bd4545f534340f16c2b8c001fe16e66 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 15 Dec 2020 09:32:54 +0100 Subject: [PATCH 027/223] Revert "FIX: Link to subaccount ledger" This reverts commit 64fa2120b2e6e577e66fd1e93e5035a61c510af7. --- htdocs/accountancy/bookkeeping/listbyaccount.php | 2 +- htdocs/langs/en_US/accountancy.lang | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index cd15eea52be..18661f8a887 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -380,7 +380,7 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); - $newcardbutton .= dolGetButtonTitle($langs->trans('VueBySubAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + $newcardbutton .= dolGetButtonTitle($langs->trans('VueByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); $newcardbutton .= '   '; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 14bebea22df..7b406af0c79 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -50,7 +50,6 @@ CountriesExceptMe=All countries except %s AccountantFiles=Export source documents ExportAccountingSourceDocHelp=With this tool, you can export the source events (list and PDFs) that were used to generate your accountancy. To export your journals, use the menu entry %s - %s. VueByAccountAccounting=View by accounting account -VueBySubAccountAccounting=View by accounting subaccount MainAccountForCustomersNotDefined=Main accounting account for customers not defined in setup MainAccountForSuppliersNotDefined=Main accounting account for vendors not defined in setup From 7b739920a24aadfcf60bcec56e95a853fa812aa1 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Thu, 17 Dec 2020 13:18:40 +0100 Subject: [PATCH 028/223] NEW : Workstations management --- htdocs/admin/workstation.php | 513 ++++++++ htdocs/core/modules/modWorkstation.class.php | 522 ++++++++ .../workstation/mod_workstation_advanced.php | 150 +++ .../workstation/mod_workstation_standard.php | 151 +++ .../workstation/modules_workstation.php | 150 +++ htdocs/core/tpl/commonfields_add.tpl.php | 1 + htdocs/core/tpl/commonfields_edit.tpl.php | 1 + .../install/mysql/migration/13.0.0-14.0.0.sql | 40 + .../llx_workstation_workstation.key.sql | 27 + .../tables/llx_workstation_workstation.sql | 36 + .../llx_workstation_workstation_resource.sql | 22 + ...llx_workstation_workstation_user_group.sql | 22 + htdocs/langs/en_US/mrp.lang | 26 +- .../class/html.formresource.class.php | 8 +- .../workstation/class/workstation.class.php | 1054 +++++++++++++++++ .../class/workstation.class.php.back | 1052 ++++++++++++++++ .../class/workstationresource.class.php | 82 ++ .../class/workstationusergroup.class.php | 82 ++ htdocs/workstation/lib/workstation.lib.php | 65 + .../lib/workstation_workstation.lib.php | 85 ++ htdocs/workstation/workstation_agenda.php | 276 +++++ htdocs/workstation/workstation_card.php | 511 ++++++++ htdocs/workstation/workstation_document.php | 228 ++++ htdocs/workstation/workstation_list.php | 601 ++++++++++ htdocs/workstation/workstation_note.php | 183 +++ 25 files changed, 5884 insertions(+), 4 deletions(-) create mode 100755 htdocs/admin/workstation.php create mode 100755 htdocs/core/modules/modWorkstation.class.php create mode 100755 htdocs/core/modules/workstation/mod_workstation_advanced.php create mode 100755 htdocs/core/modules/workstation/mod_workstation_standard.php create mode 100755 htdocs/core/modules/workstation/modules_workstation.php create mode 100644 htdocs/install/mysql/migration/13.0.0-14.0.0.sql create mode 100755 htdocs/install/mysql/tables/llx_workstation_workstation.key.sql create mode 100755 htdocs/install/mysql/tables/llx_workstation_workstation.sql create mode 100755 htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql create mode 100755 htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql create mode 100755 htdocs/workstation/class/workstation.class.php create mode 100755 htdocs/workstation/class/workstation.class.php.back create mode 100644 htdocs/workstation/class/workstationresource.class.php create mode 100644 htdocs/workstation/class/workstationusergroup.class.php create mode 100755 htdocs/workstation/lib/workstation.lib.php create mode 100755 htdocs/workstation/lib/workstation_workstation.lib.php create mode 100755 htdocs/workstation/workstation_agenda.php create mode 100755 htdocs/workstation/workstation_card.php create mode 100755 htdocs/workstation/workstation_document.php create mode 100755 htdocs/workstation/workstation_list.php create mode 100755 htdocs/workstation/workstation_note.php diff --git a/htdocs/admin/workstation.php b/htdocs/admin/workstation.php new file mode 100755 index 00000000000..8f9ee369d4f --- /dev/null +++ b/htdocs/admin/workstation.php @@ -0,0 +1,513 @@ + + * Copyright (C) 2020 SuperAdmin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation/admin/setup.php + * \ingroup workstation + * \brief Workstation setup page. + */ + +// Load Dolibarr environment +require "../main.inc.php"; + +// Libraries +require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; +require_once DOL_DOCUMENT_ROOT . '/workstation/lib/workstation.lib.php'; +//require_once "../class/myclass.class.php"; + +// Translations +$langs->loadLangs(array("admin", "workstation@workstation")); + +// Access control +if (!$user->admin) accessforbidden(); + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +$value = GETPOST('value', 'alpha'); + +/*$arrayofparameters = array( + 'WORKSTATION_MYPARAM1'=>array('css'=>'minwidth200', 'enabled'=>1), + 'WORKSTATION_MYPARAM2'=>array('css'=>'minwidth500', 'enabled'=>1) +);*/ + +$error = 0; +$setupnotempty = 0; + + +/* + * Actions + */ + +if ((float) DOL_VERSION >= 6) +{ + include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; +} + +if ($action == 'updateMask') +{ + $maskconstorder = GETPOST('maskconstWorkstation', 'alpha'); + $maskorder = GETPOST('maskWorkstation', 'alpha'); + + if ($maskconstorder) $res = dolibarr_set_const($db, $maskconstorder, $maskorder, 'chaine', 0, '', $conf->entity); + + if (!$res > 0) $error++; + + if (!$error) + { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen') +{ + $modele = GETPOST('module', 'alpha'); + $tmpobjectkey = GETPOST('object'); + + $tmpobject = new $tmpobjectkey($db); + $tmpobject->initAsSpecimen(); + + // Search template files + $file = ''; $classname = ''; $filefound = 0; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $file = dol_buildpath($reldir."core/modules/workstation/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0); + if (file_exists($file)) + { + $filefound = 1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) + { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($tmpobject, $langs) > 0) + { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} + +// Activate a model +elseif ($action == 'set') +{ + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') +{ + $tmpobjectkey = GETPOST('object'); + + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $constforval = strtoupper($tmpobjectkey).'_ADDON_PDF'; + if ($conf->global->$constforval == "$value") dolibarr_del_const($db, $constforval, $conf->entity); + } +} + +// Set default model +elseif ($action == 'setdoc') +{ + $tmpobjectkey = GETPOST('object'); + $constforval = strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) + { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->$constforval = $value; + } + + // On active le modele + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $ret = addDocumentModel($value, $type, $label, $scandir); + } +} elseif ($action == 'setmod') +{ + // TODO Check if numbering module chosen can be activated + // by calling method canBeActivated + $tmpobjectkey = GETPOST('object'); + $constforval = 'WORKSTATION_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); +} + + + +/* + * View + */ + +$form = new Form($db); + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + +$page_name = "WorkstationSetup"; +llxHeader('', $langs->trans($page_name)); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($page_name), $linkback, 'object_workstation@workstation'); + +// Configuration header +$head = workstationAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', '', -1, "workstation@workstation"); + +// Setup page goes here +//echo ''.$langs->trans("WorkstationSetupPage").'

'; + + +if ($action == 'edit') +{ + print '
'; + print ''; + print ''; + + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) + { + print ''; + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print '
'; + + print '
'; + print ''; + print '
'; + + print '
'; + print '
'; +} else { + if (!empty($arrayofparameters)) + { + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) + { + $setupnotempty++; + + print ''; + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print ''.$conf->global->$key.'
'; + + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + }/* else { + print '
'.$langs->trans("NothingToSetup"); + }*/ +} + + +$moduledir = 'workstation'; +$myTmpObjects = array(); +$myTmpObjects['workstation'] = array('includerefgeneration'=>1, 'includedocgeneration'=>0); + + +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'MyObject') continue; + if ($myTmpObjectArray['includerefgeneration']) { + /* + * Orders Numbering model + */ + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectKey), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') + { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue; + + if ($module->isEnabled()) + { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $mytmpinstance = new $myTmpObjectKey($db); + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
'; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') + $nextval = $langs->trans($nextval); + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + else print $tmp; + print '
'; + $constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $file) + { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

\n"; + } + + if ($myTmpObjectArray['includedocgeneration']) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) + { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) + { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } + } else { + dol_print_error($db); + } + + print "\n"; + print "\n"; + print ''; + print ''; + print '\n"; + print '\n"; + print ''; + print ''; + print "\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) + { + foreach (array('', '/doc') as $valdir) + { + $realpath = $reldir."core/modules/".$moduledir.$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) + { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) + { + if (file_exists($dir.'/'.$file)) + { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified = 1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified = 0; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified = 0; + + if ($modulequalified) + { + print ''; + + // Active + if (in_array($name, $def)) + { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') + { + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) print $module->info($langs); + else print $module->description; + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + $constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $name) + { + print img_picto($langs->trans("Default"), 'on'); + } else { + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print ''; + if ($module->type == 'pdf') + { + print ''.img_object($langs->trans("Preview"), 'generic').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
'; + } +} + +/*if (empty($setupnotempty)) { + print '
'.$langs->trans("NothingToSetup"); +}*/ + +// Page end +print dol_get_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/htdocs/core/modules/modWorkstation.class.php b/htdocs/core/modules/modWorkstation.class.php new file mode 100755 index 00000000000..216d591670a --- /dev/null +++ b/htdocs/core/modules/modWorkstation.class.php @@ -0,0 +1,522 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2020 SuperAdmin + * + * 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 . + */ + +/** + * \defgroup workstation Module Workstation + * \brief Workstation module descriptor. + * + * \file htdocs/workstation/core/modules/modWorkstation.class.php + * \ingroup workstation + * \brief Description and activation file for module Workstation + */ +include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + +/** + * Description and activation class for module Workstation + */ +class modWorkstation extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs, $conf; + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 500000; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'workstation'; + // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' + // It is used to group modules by family in module setup page + $this->family = "other"; + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '90'; + // Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); + // Module label (no space allowed), used if translation string 'ModuleWorkstationName' not found (Workstation is name of module). + $this->name = preg_replace('/^mod/i', '', get_class($this)); + // Module description, used if translation string 'ModuleWorkstationDesc' not found (Workstation is name of module). + $this->description = "WorkstationsDescription"; + // Used only if file README.md and README-LL.md not found. + $this->descriptionlong = "Workstation description (Long)"; + $this->editor_name = 'Editor name'; + $this->editor_url = 'https://www.example.com'; + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' + $this->version = '1.0'; + // Url to the file with your last numberversion of this module + //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; + + // Key used in llx_const table to save module status enabled/disabled (where WORKSTATION is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + $this->picto = 'mrp'; + // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + // Set this to 1 if module has its own trigger directory (core/triggers) + 'triggers' => 0, + // Set this to 1 if module has its own login method file (core/login) + 'login' => 0, + // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 0, + // Set this to 1 if module has its own menus handler directory (core/menus) + 'menus' => 0, + // Set this to 1 if module overwrite template dir (core/tpl) + 'tpl' => 0, + // Set this to 1 if module has its own barcode directory (core/modules/barcode) + 'barcode' => 0, + // Set this to 1 if module has its own models directory (core/modules/xxx) + 'models' => 1, + // Set this to 1 if module has its own printing directory (core/modules/printing) + 'printing' => 0, + // Set this to 1 if module has its own theme directory (theme) + 'theme' => 0, + // Set this to relative path of css file if module has its own css file + 'css' => array( + // '/workstation/css/workstation.css.php', + ), + // Set this to relative path of js file if module must load a js on all pages + 'js' => array( + // '/workstation/js/workstation.js.php', + ), + // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all' + 'hooks' => array( + // 'data' => array( + // 'hookcontext1', + // 'hookcontext2', + // ), + // 'entity' => '0', + ), + // Set this to 1 if features of module are opened to external users + 'moduleforexternal' => 0, + ); + // Data directories to create when module is enabled. + // Example: this->dirs = array("/workstation/temp","/workstation/subdir"); + $this->dirs = array("/workstation/temp"); + // Config pages. Put here list of php page, stored into workstation/admin directory, to use to setup module. + $this->config_page_url = array("workstation.php"); + // Dependencies + // A condition to hide module + $this->hidden = false; + // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) + $this->depends = array(); + $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) + $this->langfiles = array("mrp"); + $this->phpmin = array(5, 5); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(11, -3); // Minimum version of Dolibarr required by module + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + //$this->automatic_activation = array('FR'=>'WorkstationWasAutomaticallyActivatedBecauseOfYourCountryChoice'); + //$this->always_enabled = true; // If true, can't be disabled + + // Constants + // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) + // Example: $this->const=array(1 => array('WORKSTATION_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1), + // 2 => array('WORKSTATION_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1) + // ); + $this->const = array(); + + // Some keys to add into the overwriting translation tables + /*$this->overwrite_translation = array( + 'en_US:ParentCompany'=>'Parent company or reseller', + 'fr_FR:ParentCompany'=>'Maison mère ou revendeur' + )*/ + + if (!isset($conf->workstation) || !isset($conf->workstation->enabled)) { + $conf->workstation = new stdClass(); + $conf->workstation->enabled = 0; + } + + // Array to add new pages in new tabs + $this->tabs = array(); + // Example: + // $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@workstation:$user->rights->workstation->read:/workstation/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1 + // $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@workstation:$user->rights->othermodule->read:/workstation/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // $this->tabs[] = array('data'=>'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // + // Where objecttype can be + // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) + // 'contact' to add a tab in contact view + // 'contract' to add a tab in contract view + // 'group' to add a tab in group view + // 'intervention' to add a tab in intervention view + // 'invoice' to add a tab in customer invoice view + // 'invoice_supplier' to add a tab in supplier invoice view + // 'member' to add a tab in fundation member view + // 'opensurveypoll' to add a tab in opensurvey poll view + // 'order' to add a tab in customer order view + // 'order_supplier' to add a tab in supplier order view + // 'payment' to add a tab in payment view + // 'payment_supplier' to add a tab in supplier payment view + // 'product' to add a tab in product view + // 'propal' to add a tab in propal view + // 'project' to add a tab in project view + // 'stock' to add a tab in stock view + // 'thirdparty' to add a tab in third party view + // 'user' to add a tab in user view + + // Dictionaries + $this->dictionaries = array(); + /* Example: + $this->dictionaries=array( + 'langs'=>'workstation@workstation', + // List of tables we want to see into dictonnary editor + 'tabname'=>array(MAIN_DB_PREFIX."table1", MAIN_DB_PREFIX."table2", MAIN_DB_PREFIX."table3"), + // Label of tables + 'tablib'=>array("Table1", "Table2", "Table3"), + // Request to select fields + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), + // Sort order + 'tabsqlsort'=>array("label ASC", "label ASC", "label ASC"), + // List of fields (result of select to show dictionary) + 'tabfield'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields to edit a record) + 'tabfieldvalue'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields for insert) + 'tabfieldinsert'=>array("code,label", "code,label", "code,label"), + // Name of columns with primary key (try to always name it 'rowid') + 'tabrowid'=>array("rowid", "rowid", "rowid"), + // Condition to show each dictionary + 'tabcond'=>array($conf->workstation->enabled, $conf->workstation->enabled, $conf->workstation->enabled) + ); + */ + + // Boxes/Widgets + // Add here list of php file(s) stored in workstation/core/boxes that contains a class to show a widget. + $this->boxes = array( + // 0 => array( + // 'file' => 'workstationwidget1.php@workstation', + // 'note' => 'Widget provided by Workstation', + // 'enabledbydefaulton' => 'Home', + // ), + // ... + ); + + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week + $this->cronjobs = array( + // 0 => array( + // 'label' => 'MyJob label', + // 'jobtype' => 'method', + // 'class' => '/workstation/class/workstation.class.php', + // 'objectname' => 'Workstation', + // 'method' => 'doScheduledJob', + // 'parameters' => '', + // 'comment' => 'Comment', + // 'frequency' => 2, + // 'unitfrequency' => 3600, + // 'status' => 0, + // 'test' => '$conf->workstation->enabled', + // 'priority' => 50, + // ), + ); + // Example: $this->cronjobs=array( + // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->workstation->enabled', 'priority'=>50), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->workstation->enabled', 'priority'=>50) + // ); + + // Permissions provided by this module + $this->rights = array(); + $r = 0; + // Add here entries to declare new permissions + /* BEGIN MODULEBUILDER PERMISSIONS */ + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Read objects of Workstation'; // Permission label + $this->rights[$r][4] = 'workstation'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $this->rights[$r][5] = 'read'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Create/Update objects of Workstation'; // Permission label + $this->rights[$r][4] = 'workstation'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $this->rights[$r][5] = 'write'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Delete objects of Workstation'; // Permission label + $this->rights[$r][4] = 'workstation'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $this->rights[$r][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->workstation->level1->level2) + $r++; + /* END MODULEBUILDER PERMISSIONS */ + + // Main menu entries to add + $this->menu = array(); + $r = 0; + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + /*$this->menu[$r++] = array( + 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'top', // This is a Top menu entry + 'titre'=>$langs->trans('GPAO'), + 'mainmenu'=>'gpao', + 'leftmenu'=>'', + 'url'=>'/workstation/workstationindex.php', + 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000 + $r, + 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->workstation->workstation->read' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + );*/ + /* END MODULEBUILDER TOPMENU */ + /* BEGIN MODULEBUILDER LEFTMENU WORKSTATION + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Top menu entry + 'titre'=>'Workstation', + 'mainmenu'=>'workstation', + 'leftmenu'=>'workstation', + 'url'=>'/workstation/workstationindex.php', + 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->workstation->workstation->read', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=workstation,fk_leftmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List_Workstation', + 'mainmenu'=>'workstation', + 'leftmenu'=>'workstation_workstation_list', + 'url'=>'/workstation/workstation_list.php', + 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->workstation->workstation->read', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=workstation,fk_leftmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New_Workstation', + 'mainmenu'=>'workstation', + 'leftmenu'=>'workstation_workstation_new', + 'url'=>'/workstation/workstation_card.php?action=create', + 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->workstation->workstation->write', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + */ + + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=mrp', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>$langs->trans('Workstations'), + 'mainmenu'=>'mrp', + 'leftmenu'=>'workstation_workstation', + 'url'=>'', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'mrp', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->workstation->enabled', + // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->workstation->workstation->read', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=mrp,fk_leftmenu=workstation_workstation', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>$langs->trans('WorkstationCreate'), + 'mainmenu'=>'mrp', + 'leftmenu'=>'workstation_workstation_left_create', + 'url'=>'/workstation/workstation_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'mrp', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->workstation->enabled', + // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->workstation->workstation->write', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + ); + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=mrp,fk_leftmenu=workstation_workstation', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>$langs->trans('List'), + 'mainmenu'=>'mrp', + 'leftmenu'=>'workstation_workstation_left_list', + 'url'=>'/workstation/workstation_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'mrp', + 'position'=>1101+$r, + // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->workstation->enabled', + // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->workstation->workstation->read', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + ); + + /* END MODULEBUILDER LEFTMENU WORKSTATION */ + // Exports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER EXPORT WORKSTATION */ + /* + $langs->load("workstation@workstation"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='WorkstationLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='workstation@workstation'; + // Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array + $keyforclass = 'Workstation'; $keyforclassfile='/workstation/class/workstation.class.php'; $keyforelement='workstation@workstation'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; + //unset($this->export_fields_array[$r]['t.fieldtoremove']); + //$keyforclass = 'WorkstationLine'; $keyforclassfile='/workstation/class/workstation.class.php'; $keyforelement='workstationline@workstation'; $keyforalias='tl'; + //include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='workstation'; $keyforaliasextra='extra'; $keyforelement='workstation@workstation'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$keyforselect='workstationline'; $keyforaliasextra='extraline'; $keyforelement='workstationline@workstation'; + //include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r] = array('workstationline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + //$this->export_special_array[$r] = array('t.field'=>'...'); + //$this->export_examplevalues_array[$r] = array('t.field'=>'Example'); + //$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp'); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'workstation as t'; + //$this->export_sql_end[$r] =' LEFT JOIN '.MAIN_DB_PREFIX.'workstation_line as tl ON tl.fk_workstation = t.rowid'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('workstation').')'; + $r++; */ + /* END MODULEBUILDER EXPORT WORKSTATION */ + + // Imports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER IMPORT WORKSTATION */ + /* + $langs->load("workstation@workstation"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='WorkstationLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='workstation@workstation'; + $keyforclass = 'Workstation'; $keyforclassfile='/workstation/class/workstation.class.php'; $keyforelement='workstation@workstation'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='workstation'; $keyforaliasextra='extra'; $keyforelement='workstation@workstation'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'workstation as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('workstation').')'; + $r++; */ + /* END MODULEBUILDER IMPORT WORKSTATION */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + global $conf, $langs; + + $result = $this->_load_tables('/workstation/sql/'); + if ($result < 0) return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + + // Create extrafields during init + //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + //$extrafields = new ExtraFields($this->db); + //$result1=$extrafields->addExtraField('workstation_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'workstation@workstation', '$conf->workstation->enabled'); + //$result2=$extrafields->addExtraField('workstation_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'workstation@workstation', '$conf->workstation->enabled'); + //$result3=$extrafields->addExtraField('workstation_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'workstation@workstation', '$conf->workstation->enabled'); + //$result4=$extrafields->addExtraField('workstation_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'workstation@workstation', '$conf->workstation->enabled'); + //$result5=$extrafields->addExtraField('workstation_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'workstation@workstation', '$conf->workstation->enabled'); + + // Permissions + $this->remove($options); + + $sql = array(); + + // Document templates + $moduledir = 'workstation'; + $myTmpObjects = array(); + $myTmpObjects['Workstation'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); + + foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'Workstation') continue; + if ($myTmpObjectArray['includerefgeneration']) { + $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/workstation/template_workstations.odt'; + $dirodt = DOL_DATA_ROOT.'/doctemplates/workstation'; + $dest = $dirodt.'/template_workstations.odt'; + + if (file_exists($src) && !file_exists($dest)) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + dol_mkdir($dirodt); + $result = dol_copy($src, $dest, 0, 0); + if ($result < 0) + { + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest); + return 0; + } + } + + $sql = array_merge($sql, array( + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".strtolower($myTmpObjectKey)."' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."','".strtolower($myTmpObjectKey)."',".$conf->entity.")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".strtolower($myTmpObjectKey)."' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".strtolower($myTmpObjectKey)."', ".$conf->entity.")" + )); + } + } + + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/htdocs/core/modules/workstation/mod_workstation_advanced.php b/htdocs/core/modules/workstation/mod_workstation_advanced.php new file mode 100755 index 00000000000..d9133b4063c --- /dev/null +++ b/htdocs/core/modules/workstation/mod_workstation_advanced.php @@ -0,0 +1,150 @@ + + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/workstation/mod_workstation_advanced.php + * \ingroup workstation + * \brief File containing class for advanced numbering model of Workstation + */ + +require_once DOL_DOCUMENT_ROOT . '/core/modules/workstation/modules_workstation.php'; + + +/** + * Class to manage customer Bom numbering rules advanced + */ +class mod_workstation_advanced extends ModeleNumRefWorkstation +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string Error message + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'advanced'; + + + /** + * Returns the description of the numbering model + * + * @return string Texte descripif + */ + public function info() + { + global $conf, $langs, $db; + + $langs->load("bills"); + + $form = new Form($db); + + $texte = $langs->trans('GenericNumRefModelDesc')."
\n"; + $texte .= '
'; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("Workstation"), $langs->transnoentities("Workstation")); + $tooltip .= $langs->trans("GenericMaskCodes2"); + $tooltip .= $langs->trans("GenericMaskCodes3"); + $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("Workstation"), $langs->transnoentities("Workstation")); + $tooltip .= $langs->trans("GenericMaskCodes5"); + + // Parametrage du prefix + $texte .= ''; + $texte .= ''; + + $texte .= ''; + + $texte .= ''; + + $texte .= '
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + $texte .= '
'; + + return $texte; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $conf, $db, $langs, $mysoc; + + $object = new Workstation($db); + $object->initAsSpecimen(); + + /*$old_code_client = $mysoc->code_client; + $old_code_type = $mysoc->typent_code; + $mysoc->code_client = 'CCCCCCCCCC'; + $mysoc->typent_code = 'TTTTTTTTTT';*/ + + $numExample = $this->getNextValue($object); + + /*$mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type;*/ + + if (!$numExample) + { + $numExample = $langs->trans('NotConfigured'); + } + return $numExample; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + // We get cursor rule + $mask = $conf->global->WORKSTATION_WORKSTATION_ADVANCED_MASK; + + if (!$mask) + { + $this->error = 'NotConfigured'; + return 0; + } + + $date = $object->date; + + $numFinal = get_next_value($db, $mask, 'workstation_workstation', 'ref', '', null, $date); + + return $numFinal; + } +} diff --git a/htdocs/core/modules/workstation/mod_workstation_standard.php b/htdocs/core/modules/workstation/mod_workstation_standard.php new file mode 100755 index 00000000000..87e94233c88 --- /dev/null +++ b/htdocs/core/modules/workstation/mod_workstation_standard.php @@ -0,0 +1,151 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/workstation/mod_workstation_standard.php + * \ingroup workstation + * \brief File of class to manage Workstation numbering rules standard + */ +require_once DOL_DOCUMENT_ROOT . '/core/modules/workstation/modules_workstation.php'; + +/** + * Class to manage customer order numbering rules standard + */ +class mod_workstation_standard extends ModeleNumRefWorkstation +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + public $prefix = 'WORKSTATION'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'standard'; + + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info() + { + global $langs; + return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + } + + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + return $this->prefix."0501-0001"; + } + + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."workstation_workstation"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) + { + $row = $db->fetch_row($resql); + if ($row) { $coyymm = substr($row[0], 0, 6); $max = $row[0]; } + } + if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) + { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + // First we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."workstation_workstation"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + //$sql .= " AND entity = ".$conf->entity; + + $resql = $db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + if ($obj) $max = intval($obj->max); + else $max = 0; + } else { + dol_syslog("mod_workstation_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = dol_now(); + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + else $num = sprintf("%04s", $max + 1); + + dol_syslog("mod_workstation_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } +} diff --git a/htdocs/core/modules/workstation/modules_workstation.php b/htdocs/core/modules/workstation/modules_workstation.php new file mode 100755 index 00000000000..bfd0f6c95ea --- /dev/null +++ b/htdocs/core/modules/workstation/modules_workstation.php @@ -0,0 +1,150 @@ + + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2014 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 + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/workstation/modules_workstation.php + * \ingroup workstation + * \brief File that contains parent class for workstations document models and parent class for workstations numbering models + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // required for use by classes that inherit + + +/** + * Parent class for documents models + */ +abstract class ModelePDFWorkstation extends CommonDocGenerator +{ + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + public static function liste_modeles($db, $maxfilenamelength = 0) + { + // phpcs:enable + global $conf; + + $type = 'workstation'; + $list = array(); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $list = getListOfModels($db, $type, $maxfilenamelength); + + return $list; + } +} + + + +/** + * Parent class to manage numbering of Workstation + */ +abstract class ModeleNumRefWorkstation +{ + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled() + { + return true; + } + + /** + * Returns the default description of the numbering template + * + * @return string Texte descripif + */ + public function info() + { + global $langs; + $langs->load("workstation@workstation"); + return $langs->trans("NoDescription"); + } + + /** + * Returns an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $langs; + $langs->load("workstation@workstation"); + return $langs->trans("NoExample"); + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + return true; + } + + /** + * Returns next assigned value + * + * @param Object $object Object we need next value for + * @return string Valeur + */ + public function getNextValue($object) + { + global $langs; + return $langs->trans("NotAvailable"); + } + + /** + * Returns version of numbering module + * + * @return string Valeur + */ + public function getVersion() + { + global $langs; + $langs->load("admin"); + + if ($this->version == 'development') return $langs->trans("VersionDevelopment"); + if ($this->version == 'experimental') return $langs->trans("VersionExperimental"); + if ($this->version == 'dolibarr') return DOL_VERSION; + if ($this->version) return $this->version; + return $langs->trans("NotAvailable"); + } +} diff --git a/htdocs/core/tpl/commonfields_add.tpl.php b/htdocs/core/tpl/commonfields_add.tpl.php index c7069b3d2aa..a0b0ce7a6e2 100644 --- a/htdocs/core/tpl/commonfields_add.tpl.php +++ b/htdocs/core/tpl/commonfields_add.tpl.php @@ -55,6 +55,7 @@ foreach ($object->fields as $key => $val) print ''; if (!empty($val['picto'])) { print img_picto('', $val['picto']); } if (in_array($val['type'], array('int', 'integer'))) $value = GETPOST($key, 'int'); + elseif ($val['type'] == 'double') $value = price2num(GETPOST($key, 'alphanohtml')); elseif ($val['type'] == 'text' || $val['type'] == 'html') $value = GETPOST($key, 'restricthtml'); else $value = GETPOST($key, 'alpha'); if ($val['noteditable']) print $object->showOutputField($val, $key, $value, '', '', '', 0); diff --git a/htdocs/core/tpl/commonfields_edit.tpl.php b/htdocs/core/tpl/commonfields_edit.tpl.php index 946d8c0b504..76a9fafe417 100644 --- a/htdocs/core/tpl/commonfields_edit.tpl.php +++ b/htdocs/core/tpl/commonfields_edit.tpl.php @@ -53,6 +53,7 @@ foreach ($object->fields as $key => $val) print ''; if (!empty($val['picto'])) { print img_picto('', $val['picto']); } if (in_array($val['type'], array('int', 'integer'))) $value = GETPOSTISSET($key) ?GETPOST($key, 'int') : $object->$key; + elseif ($val['type'] == 'double') $value = GETPOSTISSET($key) ? price2num(GETPOST($key, 'alphanohtml')) : $object->$key; elseif (preg_match('/^(text|html)/', $val['type'])) { $tmparray = explode(':', $val['type']); if (!empty($tmparray[1])) { diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql new file mode 100644 index 00000000000..a75de31a905 --- /dev/null +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -0,0 +1,40 @@ +CREATE TABLE llx_workstation_workstation( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + label varchar(255), + type varchar(7), + note_public text, + entity int DEFAULT 1, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status smallint NOT NULL, + nb_operators_required integer, + thm_operator_estimated double, + thm_machine_estimated double + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; + +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_rowid (rowid); +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_ref (ref); +ALTER TABLE llx_workstation_workstation ADD CONSTRAINT llx_workstation_workstation_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_status (status); + +CREATE TABLE llx_workstation_workstation_resource( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + tms timestamp, + fk_resource integer, + fk_workstation integer +) ENGINE=innodb; + +CREATE TABLE llx_workstation_workstation_usergroup( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + tms timestamp, + fk_usergroup integer, + fk_workstation integer +) ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql b/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql new file mode 100755 index 00000000000..2e013ee0128 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql @@ -0,0 +1,27 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_rowid (rowid); +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_ref (ref); +ALTER TABLE llx_workstation_workstation ADD CONSTRAINT llx_workstation_workstation_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_workstation_workstation ADD INDEX idx_workstation_workstation_status (status); +-- END MODULEBUILDER INDEXES + +--ALTER TABLE llx_workstation_workstation ADD UNIQUE INDEX uk_workstation_workstation_fieldxy(fieldx, fieldy); + +--ALTER TABLE llx_workstation_workstation ADD CONSTRAINT llx_workstation_workstation_fk_field FOREIGN KEY (fk_field) REFERENCES llx_workstation_myotherobject(rowid); + diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation.sql b/htdocs/install/mysql/tables/llx_workstation_workstation.sql new file mode 100755 index 00000000000..5c141ed59df --- /dev/null +++ b/htdocs/install/mysql/tables/llx_workstation_workstation.sql @@ -0,0 +1,36 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +CREATE TABLE llx_workstation_workstation( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + label varchar(255), + type varchar(7), + note_public text, + entity int DEFAULT 1, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status smallint NOT NULL, + nb_operators_required integer, + thm_operator_estimated double, + thm_machine_estimated double + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql b/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql new file mode 100755 index 00000000000..1ab019f4385 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql @@ -0,0 +1,22 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +CREATE TABLE llx_workstation_workstation_resource( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + tms timestamp, + fk_resource integer, + fk_workstation integer +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql b/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql new file mode 100755 index 00000000000..9bffb4f30c9 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql @@ -0,0 +1,22 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 https://www.gnu.org/licenses/. + + +CREATE TABLE llx_workstation_workstation_usergroup( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + tms timestamp, + fk_usergroup integer, + fk_workstation integer +) ENGINE=innodb; diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 902f167d819..ec999a473a4 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -77,4 +77,28 @@ UnitCost=Unit cost TotalCost=Total cost BOMTotalCost=The cost to produce this BOM based on cost of each quantity and product to consume (use Cost price if defined, else Average Weighted Price if defined, else the Best purchase price) GoOnTabProductionToProduceFirst=You must first have started the production to close a Manufacturing Order (See tab '%s'). But you can Cancel it. -ErrorAVirtualProductCantBeUsedIntoABomOrMo=A kit can't be used into a BOM or a MO \ No newline at end of file +ErrorAVirtualProductCantBeUsedIntoABomOrMo=A kit can't be used into a BOM or a MO +Workstation=Workstation +Workstations=Workstations +WorkstationsDescription=Workstations management +WorkstationSetup = Workstations setup +WorkstationSetupPage = Workstations setup page +WorkstationAbout = About Workstation +WorkstationAboutPage = Workstations about page +WorkstationList=Workstation list +WorkstationCreate=Add new workstation +ConfirmEnableWorkstation=Are you sure you want to enable workstation %s ? +EnableAWorkstation=Enable a workstation +ConfirmDisableWorkstation=Are you sure you want to disable workstation %s ? +DisableAWorkstation=Disable a workstation +DeleteWorkstation=Supprimer +NbOperatorsRequired=Number of operators required +THMOperatorEstimated=Estimated operator THM +THMMachineEstimated=Estimated machine THM +WorkstationType=Workstation type +Human=Human +Machine=Machine +HumanMachine=Human / Machine +WorkstationArea=Workstation area +Machines=Machines +THMEstimatedHelp=This rate makes it possible to define a forecast cost of the item diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index 0b6239b01e4..46085c126e0 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -77,7 +77,7 @@ class FormResource * @param string $morecss More css * @return string HTML string with */ - public function select_resource_list($selected = '', $htmlname = 'fk_resource', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $event = array(), $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '') + public function select_resource_list($selected = '', $htmlname = 'fk_resource', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $event = array(), $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '', $multiple=false) { // phpcs:enable global $conf, $user, $langs; @@ -89,6 +89,8 @@ class FormResource $resources_used = $resourcestat->fetch_all('ASC', 't.rowid', $limit, 0, $filter); + if (!is_array($selected)) $selected = array($selected); + if ($outputmode != 2) { $out = '
'; @@ -106,7 +108,7 @@ class FormResource } // Construct $out and $outarray - $out .= ''."\n"; if ($showempty) $out .= ''."\n"; $num = 0; @@ -123,7 +125,7 @@ class FormResource $label = $resourcestat->lines[$i]->ref ? $resourcestat->lines[$i]->ref : ''.$resourcestat->lines[$i]->label; if ($resourceclass != 'Dolresource') $label .= ' ('.$langs->trans($resourceclass).')'; - if ($selected > 0 && $selected == $resourcestat->lines[$i]->id) + if ((is_object($selected[0]) && $selected[0]->id == $resourcestat->lines[$i]->id) || (!is_object($selected[0]) && in_array($resourcestat->lines[$i]->id, $selected))) { $out .= ''; } else { diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php new file mode 100755 index 00000000000..acedb6759d9 --- /dev/null +++ b/htdocs/workstation/class/workstation.class.php @@ -0,0 +1,1054 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/workstation.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for Workstation (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Workstation + */ +class Workstation extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'workstation'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'workstation'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'workstation_workstation'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * @var string String with name of icon for workstation. Must be the part after the 'object_' into object_workstation.png + */ + public $picto = 'mrp'; + + + const STATUS_DISABLED = 0; + const STATUS_ENABLED = 1; + + + /** + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200' + * 'help' is a string visible as a tooltip on field + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'picto'=>'mrp', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>1, 'noteditable'=>'0', 'default'=>'', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'showoncombobox'=>'1',), + 'type' => array('type'=>'select', 'label'=>'Type', 'enabled'=>'1', 'position'=>32, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('HUMAN'=>'Human', 'MACHINE'=>'Machine', 'BOTH'=>'HumanMachine'),), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>512, 'notnull'=>-1, 'visible'=>-2,), + 'nb_operators_required' => array('type'=>'integer', 'label'=>'NbOperatorsRequired', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_operator_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp','label'=>'THMOperatorEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_machine_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp', 'label'=>'THMMachineEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Disabled', '1'=>'Enabled'),), + ); + public $rowid; + public $ref; + public $label; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + public $status; + public $nb_operators_required; + public $thm_operator_estimated; + public $thm_machine_estimated; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'workstation_workstationline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + //public $fk_element = 'fk_workstation'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Workstationline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables = array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + //protected $childtablesoncascade = array('workstation_workstationdet'); + + /** + * @var WorkstationLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + dol_include_once('/workstation/class/workstationusergroup.class.php'); + dol_include_once('/workstation/class/workstationresource.class.php'); + + $this->db = $db; + + $this->fields['ref']['default'] = $this->getNextNumRef(); + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->workstation->workstation->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + global $db; + + $id = $this->createCommon($user, $notrigger); + + // Usergroups + $groups = GETPOST('groups'); + if(empty($groups)) $groups = $this->usergroups; // createFromClone + if(!empty($groups)) { + foreach ($groups as $id_group) { + $ws_usergroup = new WorkstationUserGroup($db); + $ws_usergroup->fk_workstation = $id; + $ws_usergroup->fk_usergroup = $id_group; + $ws_usergroup->createCommon($user); + $this->usergroups[] = $id_group; + } + } + + // Resources + $resources = GETPOST('resources'); + if(empty($resources)) $resources = $this->resources; // createFromClone + if(!empty($resources)) { + foreach ($resources as $id_resource) { + $ws_resource = new WorkstationResource($db); + $ws_resource->fk_workstation = $id; + $ws_resource->fk_resource = $id_resource; + $ws_resource->createCommon($user); + $this->resources[] = $id_resource; + } + } + + return $id; + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetch($fromid); + if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines(); + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + if (property_exists($object, 'label')) $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + if (property_exists($object, 'status')) { $object->status = self::STATUS_DISABLED; } + if (property_exists($object, 'date_creation')) { $object->date_creation = dol_now(); } + if (property_exists($object, 'date_modification')) { $object->date_modification = null; } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) + { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) + { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) + { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->create($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) + { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) + { + $error++; + } + } + + if (!$error) + { + // copy external contacts if same company + if (property_exists($this, 'socid') && $this->socid == $object->socid) + { + if ($this->copy_linked_contact($object, 'external') < 0) + $error++; + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + + $this->usergroups = WorkstationUserGroup::getAllGroupsOfWorkstation($this->id); + $this->resources = WorkstationResource::getAllResourcesOfWorkstation($this->id); + + if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key.'='.$value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' '.$this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) + { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + + // Usergroups + $groups = GETPOST('groups'); + WorkstationUserGroup::deleteAllGroupsOfWorkstation($this->id); + $this->usergroups=array(); + + foreach ($groups as $id_group) { + $ws_usergroup = new WorkstationUserGroup($this->db); + $ws_usergroup->fk_workstation = $this->id; + $ws_usergroup->fk_usergroup = $id_group; + $ws_usergroup->createCommon($user); + $this->usergroups[] = $id_group; + } + + // Resources + $resources = GETPOST('resources'); + WorkstationResource::deleteAllResourcesOfWorkstation($this->id); + $this->resources=array(); + if(!empty($resources)) { + foreach ($resources as $id_resource) { + $ws_resource = new WorkstationResource($this->db); + $ws_resource->fk_workstation = $this->id; + $ws_resource->fk_resource = $id_resource; + $ws_resource->createCommon($user); + $this->resources[] = $id_resource; + } + } + + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) + { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) + { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->workstation_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life + { + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."'"; + if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; + $sql .= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) + { + // Call trigger + $result = $this->call_trigger('WORKSTATION_VALIDATE', $user); + if ($result < 0) $error++; + // End call triggers + } + } + + if (!$error) + { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) + { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'workstation/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'workstation/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { $error++; $this->error = $this->db->lasterror(); } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->workstation->dir_output.'/workstation/'.$oldref; + $dirdest = $conf->workstation->dir_output.'/workstation/'.$newref; + if (!$error && file_exists($dirsource)) + { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) + { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->workstation->dir_output.'/workstation/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) + { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) + { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) + { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setStatus($status, $notrigger = 0) + { + global $user; + + $this->status = $status; + + if(empty($status)) $this->setDisabled($user, $notrigger); + else $this->setEnabled($user, $notrigger); + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setEnabled($user, $notrigger = 0) + { + return $this->setStatusCommon($user, self::STATUS_ENABLED, $notrigger, 'WORKSTATION_ENABLED'); + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDisabled($user, $notrigger = 0) + { + return $this->setStatusCommon($user, self::STATUS_DISABLED, $notrigger, 'WORKSTATION_DISABLED'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("Workstation").''; + $label .= '
'; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + if (isset($this->status)) { + $label .= '
'.$langs->trans("Status").": ".$this->getLibStatut(5); + } + + $url = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; + if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; + } + + $linkclose = ''; + if (empty($notooltip)) + { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label = $langs->trans("ShowWorkstation"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + + $linkstart = ''; + $linkend = ''; + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
No photo
'; + } else { + $result .= '
No photo
'; + } + + $result .= '
'; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) $result .= $this->ref; + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('workstationdao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $result = $hookmanager->resPrint; + else $result .= $hookmanager->resPrint; + + return $result; + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) + { + global $langs; + //$langs->load("workstation@workstation"); + $this->labelStatus[self::STATUS_DISABLED] = $langs->trans('Disabled'); + $this->labelStatus[self::STATUS_ENABLED] = $langs->trans('Enabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + //if ($status == self::STATUS_CANCELED) $statusType = 'status6'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql .= ' fk_user_creat, fk_user_modif'; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql .= ' WHERE t.rowid = '.$id; + $result = $this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new WorkstationLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.$this->id)); + + if (is_numeric($result)) + { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("workstation@workstation"); + + if (empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) { + $conf->global->WORKSTATION_WORKSTATION_ADDON = 'mod_workstation_standard'; + } + + if (!empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) + { + $mybool = false; + + $file = $conf->global->WORKSTATION_WORKSTATION_ADDON.".php"; + $classname = $conf->global->WORKSTATION_WORKSTATION_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/workstation/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) + { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') + { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 0; + + $langs->load("workstation@workstation"); + + if (!dol_strlen($modele)) { + $modele = 'standard_workstation'; + + if ($this->model_pdf) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->WORKSTATION_ADDON_PDF)) { + $modele = $conf->global->WORKSTATION_ADDON_PDF; + } + } + + $modelpath = "core/modules/workstation/doc/"; + + if ($includedocgeneration) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} diff --git a/htdocs/workstation/class/workstation.class.php.back b/htdocs/workstation/class/workstation.class.php.back new file mode 100755 index 00000000000..f4666c352ce --- /dev/null +++ b/htdocs/workstation/class/workstation.class.php.back @@ -0,0 +1,1052 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/workstation.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for Workstation (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Workstation + */ +class Workstation extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'workstation'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'workstation'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'workstation_workstation'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for workstation. Must be the part after the 'object_' into object_workstation.png + */ + public $picto = 'workstation@workstation'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_CANCELED = 9; + + + /** + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200' + * 'help' is a string visible as a tooltip on field + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'help'=>"Help text", 'showoncombobox'=>'1',), + 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3,), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validé', '9'=>'Annulé'),), + 'nb_operators_required' => array('type'=>'integer', 'label'=>'NbOperatorsRequired', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_operator_estimated' => array('type'=>'double', 'label'=>'THMOperatorEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_machine_estimated' => array('type'=>'double', 'label'=>'THMMachineEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + ); + public $rowid; + public $ref; + public $label; + public $description; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + public $status; + public $nb_operators_required; + public $thm_operator_estimated; + public $thm_machine_estimated; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'workstation_workstationline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + //public $fk_element = 'fk_workstation'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Workstationline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables = array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + //protected $childtablesoncascade = array('workstation_workstationdet'); + + /** + * @var WorkstationLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->workstation->workstation->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + return $this->createCommon($user, $notrigger); + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines(); + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + if (property_exists($object, 'label')) $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } + if (property_exists($object, 'date_creation')) { $object->date_creation = dol_now(); } + if (property_exists($object, 'date_modification')) { $object->date_modification = null; } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) + { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) + { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) + { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) + { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) + { + $error++; + } + } + + if (!$error) + { + // copy external contacts if same company + if (property_exists($this, 'socid') && $this->socid == $object->socid) + { + if ($this->copy_linked_contact($object, 'external') < 0) + $error++; + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key.'='.$value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' '.$this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) + { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) + { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) + { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->workstation_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life + { + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."'"; + if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; + $sql .= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) + { + // Call trigger + $result = $this->call_trigger('WORKSTATION_VALIDATE', $user); + if ($result < 0) $error++; + // End call triggers + } + } + + if (!$error) + { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) + { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'workstation/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'workstation/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { $error++; $this->error = $this->db->lasterror(); } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->workstation->dir_output.'/workstation/'.$oldref; + $dirdest = $conf->workstation->dir_output.'/workstation/'.$newref; + if (!$error && file_exists($dirsource)) + { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) + { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->workstation->dir_output.'/workstation/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) + { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) + { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) + { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'WORKSTATION_UNVALIDATE'); + } + + /** + * Set cancel status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function cancel($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_VALIDATED) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'WORKSTATION_CLOSE'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'WORKSTATION_REOPEN'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("Workstation").''; + $label .= '
'; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + if (isset($this->status)) { + $label .= '
'.$langs->trans("Status").": ".$this->getLibStatut(5); + } + + $url = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; + if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; + } + + $linkclose = ''; + if (empty($notooltip)) + { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label = $langs->trans("ShowWorkstation"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + + $linkstart = ''; + $linkend = ''; + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
No photo
'; + } else { + $result .= '
No photo
'; + } + + $result .= ''; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) $result .= $this->ref; + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('workstationdao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $result = $hookmanager->resPrint; + else $result .= $hookmanager->resPrint; + + return $result; + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) + { + global $langs; + //$langs->load("workstation@workstation"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Enabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Disabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + if ($status == self::STATUS_CANCELED) $statusType = 'status6'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql .= ' fk_user_creat, fk_user_modif'; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql .= ' WHERE t.rowid = '.$id; + $result = $this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new WorkstationLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.$this->id)); + + if (is_numeric($result)) + { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("workstation@workstation"); + + if (empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) { + $conf->global->WORKSTATION_WORKSTATION_ADDON = 'mod_workstation_standard'; + } + + if (!empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) + { + $mybool = false; + + $file = $conf->global->WORKSTATION_WORKSTATION_ADDON.".php"; + $classname = $conf->global->WORKSTATION_WORKSTATION_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/workstation/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) + { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') + { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 0; + + $langs->load("workstation@workstation"); + + if (!dol_strlen($modele)) { + $modele = 'standard_workstation'; + + if ($this->model_pdf) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->WORKSTATION_ADDON_PDF)) { + $modele = $conf->global->WORKSTATION_ADDON_PDF; + } + } + + $modelpath = "core/modules/workstation/doc/"; + + if ($includedocgeneration) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} + + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + +/** + * Class WorkstationLine. You can also remove this and generate a CRUD class for lines objects. + */ +class WorkstationLine extends CommonObjectLine +{ + // To complete with content of an object WorkstationLine + // We should have a field rowid, fk_workstation and position + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } +} diff --git a/htdocs/workstation/class/workstationresource.class.php b/htdocs/workstation/class/workstationresource.class.php new file mode 100644 index 00000000000..2cae732377a --- /dev/null +++ b/htdocs/workstation/class/workstationresource.class.php @@ -0,0 +1,82 @@ + array ('type' => 'integer'), + 'fk_resource' => array ('type' => 'integer') + ); + + /** + * WorkstationResource constructor. + * @param DoliDB $db Database connector + */ + public function __construct($db) + { + $this->db = $db; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + static public function getAllResourcesOfWorkstation($fk_workstation) { + + global $db; + + $obj = new self($db); + $sql = 'SELECT fk_resource FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; + $resql = $db->query($sql); + + $TRes = array(); + if(!empty($resql)) { + while($res = $db->fetch_object($resql)) { + $TRes[] = $res->fk_resource; + } + } + + return $TRes; + + } + + static public function deleteAllResourcesOfWorkstation($fk_workstation) { + + global $db; + + $obj = new self($db); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; + $resql = $db->query($sql); + + if(empty($resql)) return 0; + + return 1; + + } + +} diff --git a/htdocs/workstation/class/workstationusergroup.class.php b/htdocs/workstation/class/workstationusergroup.class.php new file mode 100644 index 00000000000..af643a6d28e --- /dev/null +++ b/htdocs/workstation/class/workstationusergroup.class.php @@ -0,0 +1,82 @@ + array ('type' => 'integer'), + 'fk_usergroup' => array ('type' => 'integer') + ); + + /** + * WorkstationUserGroup constructor. + * @param DoliDB $db Database connector + */ + public function __construct($db) + { + $this->db = $db; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + static public function getAllGroupsOfWorkstation($fk_workstation) { + + global $db; + + $obj = new self($db); + $sql = 'SELECT fk_usergroup FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; + $resql = $db->query($sql); + + $TRes = array(); + if(!empty($resql)) { + while($res = $db->fetch_object($resql)) { + $TRes[] = $res->fk_usergroup; + } + } + + return $TRes; + + } + + static public function deleteAllGroupsOfWorkstation($fk_workstation) { + + global $db; + + $obj = new self($db); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; + $resql = $db->query($sql); + + if(empty($resql)) return 0; + + return 1; + + } + +} diff --git a/htdocs/workstation/lib/workstation.lib.php b/htdocs/workstation/lib/workstation.lib.php new file mode 100755 index 00000000000..526323ec45d --- /dev/null +++ b/htdocs/workstation/lib/workstation.lib.php @@ -0,0 +1,65 @@ +. + */ + +/** + * \file workstation/lib/workstation.lib.php + * \ingroup workstation + * \brief Library files with common functions for Workstation + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function workstationAdminPrepareHead() +{ + global $langs, $conf; + + $langs->load("workstation@workstation"); + + $h = 0; + $head = array(); + $head[$h][0] = DOL_URL_ROOT . "/admin/workstation.php"; + $head[$h][1] = $langs->trans("Settings"); + $head[$h][2] = 'settings'; + $h++; + + /* + $head[$h][0] = dol_buildpath("/workstation/admin/myobject_extrafields.php", 1); + $head[$h][1] = $langs->trans("ExtraFields"); + $head[$h][2] = 'myobject_extrafields'; + $h++; + */ + + /*$head[$h][0] = require_once "/admin/about.php"; + $head[$h][1] = $langs->trans("About"); + $head[$h][2] = 'about'; + $h++;*/ + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'workstation'); + + return $head; +} diff --git a/htdocs/workstation/lib/workstation_workstation.lib.php b/htdocs/workstation/lib/workstation_workstation.lib.php new file mode 100755 index 00000000000..1c6b7492f0c --- /dev/null +++ b/htdocs/workstation/lib/workstation_workstation.lib.php @@ -0,0 +1,85 @@ +. + */ + +/** + * \file lib/workstation_workstation.lib.php + * \ingroup workstation + * \brief Library files with common functions for Workstation + */ + +/** + * Prepare array of tabs for Workstation + * + * @param Workstation $object Workstation + * @return array Array of tabs + */ +function workstationPrepareHead($object) +{ + global $db, $langs, $conf; + + $langs->load("workstation@workstation"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/workstation/workstation_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) + { + $nbNote = 0; + if (!empty($object->note_private)) $nbNote++; + if (!empty($object->note_public)) $nbNote++; + $head[$h][0] = dol_buildpath('/workstation/workstation_note.php', 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); + $head[$h][2] = 'note'; + $h++; + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; + $upload_dir = $conf->workstation->dir_output."/workstation/".dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); + $nbLinks = Link::count($db, $object->element, $object->id); + $head[$h][0] = dol_buildpath("/workstation/workstation_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= ''.($nbFiles + $nbLinks).''; + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = dol_buildpath("/workstation/workstation_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'workstation@workstation'); + + complete_head_from_modules($conf, $langs, $object, $head, $h, 'workstation@workstation', 'remove'); + + return $head; +} diff --git a/htdocs/workstation/workstation_agenda.php b/htdocs/workstation/workstation_agenda.php new file mode 100755 index 00000000000..132acc02bee --- /dev/null +++ b/htdocs/workstation/workstation_agenda.php @@ -0,0 +1,276 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation_agenda.php + * \ingroup workstation + * \brief Tab of events on Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) $actioncode = '0'; +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ?GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) $sortfield = 'a.datep,a.id'; +if (!$sortorder) $sortorder = 'DESC,DESC'; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity]."/".$object->id; + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $object->id); + +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + +/* + * Actions + */ + +$parameters = array('id'=>$id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers + { + $actioncode = ''; + $search_agenda_label = ''; + } +} + + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) +{ + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = ''; + llxHeader('', $title, $help_url); + + if (!empty($conf->notification->enabled)) $langs->load("mails"); + $head = workstationPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("Workstation"), -1, 'mrp'); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.=''; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
'; + + print dol_get_fiche_end(); + + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin='.urlencode($object->element.'@'.$object->module).'&originid='.urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'].'?id='.$object->id; + $out .= '&backtopage='.urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) + { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
'; + + if (!empty($conf->agenda->enabled)) + { + if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) + { + print ''.$langs->trans("AddAction").''; + } else { + print ''.$langs->trans("AddAction").''; + } + } + + print '
'; + + if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) + { + $param = '&id='.$object->id.'&socid='.$socid; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); + if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); + + + //print load_fiche_titre($langs->trans("ActionsOnWorkstation"), '', ''); + + // List of all actions + $filters = array(); + $filters['search_agenda_label'] = $search_agenda_label; + + // TODO Replace this with same code than into list.php + show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_card.php b/htdocs/workstation/workstation_card.php new file mode 100755 index 00000000000..5ec3a1f6842 --- /dev/null +++ b/htdocs/workstation/workstation_card.php @@ -0,0 +1,511 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation_card.php + * \ingroup workstation + * \brief Page to create/edit/view workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); +dol_include_once('/workstation/class/workstationusergroup.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'workstationcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$groups = GETPOST('groups'); +$resources = GETPOST('resources'); +//$lineid = GETPOST('lineid', 'int'); + +// Initialize technical objects +$object = new Workstation($db); +//$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationcard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +//$extrafields->fetch_name_optionals_label($object->table_element); + +//$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key, 'alpha')) $search[$key] = GETPOST('search_'.$key, 'alpha'); +} + +if (empty($action) && empty($id) && empty($ref)) $action = 'view'; + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +$permissiontoread = $user->rights->workstation->workstation->read; +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->workstation->workstation->delete; +$permissionnote = $user->rights->workstation->workstation->write; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->workstation->workstation->write; // Used by the include of actions_dellink.inc.php +$upload_dir = $conf->workstation->multidir_output[isset($object->entity) ? $object->entity : 1]; + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->statut == $object::STATUS_DRAFT) ? 1 : 0); +//$result = restrictedArea($user, 'workstation', $object->id, '', '', 'fk_soc', 'rowid', $isdraft); + +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + $error = 0; + + $backurlforlist = dol_buildpath('/workstation/workstation_list.php', 1); + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist; + else $backtopage = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); + } + } + + $triggermodname = 'WORKSTATION_WORKSTATION_MODIFY'; // Name of trigger action code to execute when we modify record + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Actions when linking object each other + include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + + // Action to move up and down lines of object + //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + if ($action == 'confirm_enable' && $confirm == "yes" && $permissiontoadd) { + + if(!empty($object->id)) $object->setStatus(1); + + } elseif ($action == 'confirm_disable' && $confirm == "yes" && $permissiontoadd) { + + if(!empty($object->id)) $object->setStatus(0); + + } + +} + + + + +/* + * View + * + * Put here all code to build page + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$formresource = new FormResource($db); + +$title = $langs->trans("Workstation"); +$help_url = ''; +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +?> + +trans("NewObject", $langs->transnoentitiesnoconv("Workstation")), '', 'object_'.$object->picto); + + print '
'; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + print dol_get_fiche_head(array(), ''); + + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; + + print ''; + print ''; + + print ''; + print ''; + + // Other attributes + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print '
'; + print $langs->trans('Groups'); + print ''; + print img_picto('', 'group'); + print $form->select_dolgroups($groups, 'groups', 1, '', 0, '', '', $object->entity, true); + print '
'; + print $langs->trans('Machines'); + print ''; + print img_picto('', 'resource'); + print $formresource->select_resource_list($resources, 'resources', '', '', 0, '', '', $object->entity, true, 0, '', true); + print '
'."\n"; + + print dol_get_fiche_end(); + + print '
'; + print ''; + print '  '; + print ''; // Cancel for create does not post form if we don't know the backtopage + print '
'; + + print '
'; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') +{ + print load_fiche_titre($langs->trans("Workstation"), '', 'object_'.$object->picto); + + print '
'; + print ''; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + print dol_get_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; + + print ''; + print ''; + + print ''; + print ''; + + // Other attributes + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + + print '
'; + print $langs->trans('Groups'); + print ''; + print img_picto('', 'group'); + print $form->select_dolgroups(empty($groups) ? $object->usergroups : $groups, 'groups', 1, '', 0, '', '', $object->entity, true); + print '
'; + print $langs->trans('Machines'); + print ''; + print img_picto('', 'resource'); + print $formresource->select_resource_list(empty($resources) ? $object->resources : $resources, 'resources', '', '', 0, '', '', $object->entity, true, 0, '', true); + print '
'; + + print dol_get_fiche_end(); + + print '
'; + print '   '; + print '
'; + + print '
'; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals(); + + $head = workstationPrepareHead($object); + print dol_get_fiche_head($head, 'card', $langs->trans("Workstation"), -1, $object->picto); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWorkstation'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } + // Clone confirmation + if ($action == 'clone') { + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + } + + // Confirmation of action xxxx + if ($action == 'enable') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('EnableAWorkstation'), $langs->trans("ConfirmEnableWorkstation", $object->ref), 'confirm_enable', $formquestion, 0, 1, 220); + } elseif ($action == 'disable') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DisableAWorkstation'), $langs->trans("ConfirmDisableWorkstation", $object->ref), 'confirm_disable', $formquestion, 0, 1, 220); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref .= '
'.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + //if ($action != 'classify') $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' '; + $morehtmlref .= ' : '; + if ($action == 'classify') { + //$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
'; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + print '
'; + print ''."\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field + //unset($object->fields['fk_project']); // Hide field already shown in banner + //unset($object->fields['fk_soc']); // Hide field already shown in banner + if($object->type === 'MACHINE') $object->fields['nb_operators_required']['visible'] = 0; + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + // Groups + if($object->type !== 'MACHINE') { + $toprint = array(); + foreach ($object->usergroups as $id_group) { + $g = new UserGroup($db); + $g->fetch($id_group); + $toprint[] = '
  • ' . $g->getNomUrl(1) . '
  • '; + } + print ''; + } + + // Resources + if($object->type !== 'HUMAN') { + $toprint = array(); + foreach ($object->resources as $id_resource) { + $r = new Dolresource($db); + $r->fetch($id_resource); + $toprint[] = '
  • ' . $r->getNomUrl(1) . '
  • '; + } + print ''; + } + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
    ' . $langs->trans('Groups') . ''; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    ' . $langs->trans('Machines') . ''; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    '; + print '
    '; + print '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + + // Buttons for actions + + if ($action != 'presend' && $action != 'editline') { + print '
    '."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + + // Modify + if ($permissiontoadd) { + print ''.$langs->trans("Modify").''."\n"; + } else { + print ''.$langs->trans('Modify').''."\n"; + } + + // Clone + if ($permissiontoadd) { + print ''.$langs->trans("ToClone").''."\n"; + } + + + if ($permissiontoadd) + { + if ($object->status == $object::STATUS_ENABLED) { + print ''.$langs->trans("Disable").''."\n"; + } else { + print ''.$langs->trans("Enable").''."\n"; + } + } + + + // Delete (need delete permission, or if draft, just need create/modify permission) + if ($permissiontodelete) + { + print ''.$langs->trans('Delete').''."\n"; + } else { + print ''.$langs->trans('Delete').''."\n"; + } + } + print '
    '."\n"; + } + +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_document.php b/htdocs/workstation/workstation_document.php new file mode 100755 index 00000000000..104ea93c4db --- /dev/null +++ b/htdocs/workstation/workstation_document.php @@ -0,0 +1,228 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation_document.php + * \ingroup workstation + * \brief Tab for documents linked to Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "companies", "other", "mails")); + + +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm'); +$id = (GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int')); +$ref = GETPOST('ref', 'alpha'); + +// Get parameters +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortorder) $sortorder = "ASC"; +if (!$sortfield) $sortfield = "name"; +//if (! $sortfield) $sortfield="position_name"; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationdocument', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity ? $object->entity : $conf->entity]."/workstation/".get_exdir(0, 0, 0, 1, $object); + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $object->id); + +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + + +/* + * Actions + */ + +include_once DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; + + +/* + * View + */ + +$form = new Form($db); + +$title = $langs->trans("Workstation").' - '.$langs->trans("Files"); +$help_url = ''; +//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +llxHeader('', $title, $help_url); + +if ($object->id) +{ + /* + * Show tabs + */ + $head = workstationPrepareHead($object); + + print dol_get_fiche_head($head, 'document', $langs->trans("Workstation"), -1, $object->picto); + + + // Build file list + $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ?SORT_DESC:SORT_ASC), 1); + $totalsize = 0; + foreach ($filearray as $key => $file) + { + $totalsize += $file['size']; + } + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + + print '
    '; + print ''; + + // Number of files + print ''; + + // Total size + print ''; + + print '
    '.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
    '.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
    '; + + print '
    '; + + print dol_get_fiche_end(); + + $modulepart = 'workstation'; + //$permission = $user->rights->workstation->workstation->write; + $permission = 1; + //$permtoedit = $user->rights->workstation->workstation->write; + $permtoedit = 1; + $param = '&id='.$object->id; + + //$relativepathwithnofile='workstation/' . dol_sanitizeFileName($object->id).'/'; + $relativepathwithnofile = 'workstation/'.dol_sanitizeFileName($object->ref).'/'; + + include_once DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; +} else { + accessforbidden('', 0, 1); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_list.php b/htdocs/workstation/workstation_list.php new file mode 100755 index 00000000000..c9aa575fad2 --- /dev/null +++ b/htdocs/workstation/workstation_list.php @@ -0,0 +1,601 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation_list.php + * \ingroup workstation + * \brief List page for workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; + +// load workstation libraries +require_once __DIR__.'/class/workstation.class.php'; + +// for other modules +//dol_include_once('/othermodule/class/otherobject.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'workstationlist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationlist')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +//$extrafields->fetch_name_optionals_label($object->table_element_line); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. +if (!$sortorder) $sortorder = "ASC"; + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); +$search = array(); + +foreach ($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key, 'alpha') !== '') $search[$key] = GETPOST('search_'.$key, 'alpha'); + if(in_array($key, array('type', 'status')) && GETPOST('search_'.$key, 'alpha') == -1) $search[$key] = ''; +} + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) +{ + if ($val['searchall']) $fieldstosearchall['t.'.$key] = $val['label']; +} + +// Definition of array of fields for columns +$arrayfields = array(); +foreach ($object->fields as $key => $val) +{ + // If $val['visible']==0, then we never show the field + if (!empty($val['visible'])) { + $visible = dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=>$val['help'] + ); + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$permissiontoread = $user->rights->workstation->workstation->read; +$permissiontoadd = $user->rights->workstation->workstation->write; +$permissiontodelete = $user->rights->workstation->workstation->delete; + +// Security check +if (empty($conf->workstation->enabled)) accessforbidden('Module not enabled'); +$socid = 0; +if ($user->socid > 0) // Protection if external user +{ + //$socid = $user->socid; + accessforbidden(); +} +//$result = restrictedArea($user, 'workstation', $id, ''); +//if (!$permissiontoread) accessforbidden(); + + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers + { + foreach ($object->fields as $key => $val) + { + $search[$key] = ''; + } + $toselect = ''; + $search_array_options = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) + { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'Workstation'; + $objectlabel = 'Workstation'; + $uploaddir = $conf->workstation->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * View + */ + +$form = new Form($db); + +$now = dol_now(); + +//$help_url="EN:Module_Workstation|FR:Module_Workstation_FR|ES:Módulo_Workstation"; +$help_url = ''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Workstations")); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +foreach ($object->fields as $key => $val) +{ + $sql .= 't.'.$key.', '; +} +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.' as options_'.$key.', ' : ''); +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; +if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; +else $sql .= " WHERE 1 = 1"; +foreach ($search as $key => $val) +{ + if ($key == 'status' && $search[$key] == -1) continue; + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if (strpos($object->fields[$key]['type'], 'integer:') === 0) { + if ($search[$key] == '-1') $search[$key] = ''; + $mode_search = 2; + } + if ($search[$key] != '') $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); +} +if ($search_all) $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); +// Add where from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +/* If a group by is required +$sql.= " GROUP BY "; +foreach($object->fields as $key => $val) +{ + $sql.='t.'.$key.', '; +} +// Add fields from extrafields +if (! empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); +} +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters, $object); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql=preg_replace('/,\s*$/','', $sql); +*/ + +$sql .= $db->order($sortfield, $sortorder); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) +{ + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); + if (($page * $limit) > $nbtotalofrecords) // if total of record found is smaller than page * limit, goto and load page 0 + { + $page = 0; + $offset = 0; + } +} +// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. +if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) +{ + $num = $nbtotalofrecords; +} else { + if ($limit) $sql .= $db->plimit($limit + 1, $offset); + + $resql = $db->query($sql); + if (!$resql) + { + dol_print_error($db); + exit; + } + + $num = $db->num_rows($resql); +} + +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) +{ + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +print ''; + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); +if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); +foreach ($search as $key => $val) +{ + if (is_array($search[$key]) && count($search[$key])) foreach ($search[$key] as $skey) $param .= '&search_'.$key.'[]='.urlencode($skey); + else $param .= '&search_'.$key.'='.urlencode($search[$key]); +} +if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); +// Add $param from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>$langs->trans("Validate"), + //'generate_doc'=>$langs->trans("ReGeneratePDF"), + //'builddoc'=>$langs->trans("PDFMerge"), + //'presend'=>$langs->trans("SendByMail"), +); +if ($permissiontodelete) $arrayofmassactions['predelete'] = ''.$langs->trans("Delete"); +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) $arrayofmassactions = array(); +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
    '."\n"; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/workstation/workstation_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendWorkstationRef"; +$modelmail = "workstation"; +$objecttmp = new Workstation($db); +$trackid = 'xxxx'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) +{ + foreach ($fieldstosearchall as $key => $val) $fieldstosearchall[$key] = $langs->trans($val); + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; +} + +$moreforfilter = ''; +/*$moreforfilter.='
    '; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
    ';*/ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; +else $moreforfilter = $hookmanager->resPrint; + +if (!empty($moreforfilter)) +{ + print '
    '; + print $moreforfilter; + print '
    '; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) +{ + $cssforfield = (empty($val['css']) ? '' : $val['css']); + if ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield .= ($cssforfield ? ' ' : '').'right'; + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) +{ + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield .= ($cssforfield ? ' ' : '').'right'; + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) +{ + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) + { + if (preg_match('/\$object/', $val)) $needToFetchEachLine++; // There is at least one compute field that use $object + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +while ($i < ($limit ? min($num, $limit) : $num)) +{ + $obj = $db->fetch_object($resql); + if (empty($obj)) break; // Should not happen + + // Store properties in $object + $object->setVarsFromFetchObj($obj); + + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) + { + $cssforfield = (empty($val['css']) ? '' : $val['css']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + + if (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif ($key == 'ref') $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status'))) $cssforfield .= ($cssforfield ? ' ' : '').'right'; + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if ($key == 'status') print $object->getLibStatut(5); + else print $object->showOutputField($val, $key, $object->$key, ''); + print ''; + if (!$i) $totalarray['nbfield']++; + if (!empty($val['isameasure'])) + { + if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print ''; + if (!$i) $totalarray['nbfield']++; + + print ''."\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) +{ + $colspan = 1; + foreach ($arrayfields as $key => $val) { if (!empty($val['checked'])) $colspan++; } + print ''; +} + + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
    '; + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + elseif (strpos($val['type'], 'integer:') === 0) { + print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth125', 1); + } elseif (!preg_match('/^(date|timestamp)/', $val['type'])) print ''; + print ''; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
    '; + if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + { + $selected = 0; + if (in_array($object->id, $arrayofselected)) $selected = 1; + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    '."\n"; +print '
    '."\n"; + +print '
    '."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) +{ + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty = 0; + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_workstation', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_note.php b/htdocs/workstation/workstation_note.php new file mode 100755 index 00000000000..b8e85ddaf6f --- /dev/null +++ b/htdocs/workstation/workstation_note.php @@ -0,0 +1,183 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file workstation_note.php + * \ingroup workstation + * \brief Tab for notes on Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationnote', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $id); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity]."/".$object->id; + +$permissionnote = $user->rights->workstation->workstation->write; // Used by the include of actions_setnotes.inc.php +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once + + +/* + * View + */ + +$form = new Form($db); + +//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; +$help_url = ''; +llxHeader('', $langs->trans('Workstation'), $help_url); + +if ($id > 0 || !empty($ref)) +{ + $object->fetch_thirdparty(); + + $head = workstationPrepareHead($object); + + print dol_get_fiche_head($head, 'note', $langs->trans("Workstation"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + + + $cssclass = "titlefield"; + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close(); From da9defe0ce2c120f35b6b170ae42b81279959166 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 21 Dec 2020 11:34:51 +0000 Subject: [PATCH 029/223] Fixing style errors. --- .../resource/class/html.formresource.class.php | 2 +- htdocs/workstation/class/workstation.class.php | 12 ++++++------ .../class/workstationresource.class.php | 15 +++++++-------- .../class/workstationusergroup.class.php | 15 +++++++-------- htdocs/workstation/workstation_card.php | 17 +++++------------ htdocs/workstation/workstation_list.php | 2 +- 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index 46085c126e0..4a9b467c32c 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -77,7 +77,7 @@ class FormResource * @param string $morecss More css * @return string HTML string with */ - public function select_resource_list($selected = '', $htmlname = 'fk_resource', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $event = array(), $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '', $multiple=false) + public function select_resource_list($selected = '', $htmlname = 'fk_resource', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $event = array(), $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '', $multiple = false) { // phpcs:enable global $conf, $user, $langs; diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index acedb6759d9..42533c4100f 100755 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -233,8 +233,8 @@ class Workstation extends CommonObject // Usergroups $groups = GETPOST('groups'); - if(empty($groups)) $groups = $this->usergroups; // createFromClone - if(!empty($groups)) { + if (empty($groups)) $groups = $this->usergroups; // createFromClone + if (!empty($groups)) { foreach ($groups as $id_group) { $ws_usergroup = new WorkstationUserGroup($db); $ws_usergroup->fk_workstation = $id; @@ -246,8 +246,8 @@ class Workstation extends CommonObject // Resources $resources = GETPOST('resources'); - if(empty($resources)) $resources = $this->resources; // createFromClone - if(!empty($resources)) { + if (empty($resources)) $resources = $this->resources; // createFromClone + if (!empty($resources)) { foreach ($resources as $id_resource) { $ws_resource = new WorkstationResource($db); $ws_resource->fk_workstation = $id; @@ -490,7 +490,7 @@ class Workstation extends CommonObject $resources = GETPOST('resources'); WorkstationResource::deleteAllResourcesOfWorkstation($this->id); $this->resources=array(); - if(!empty($resources)) { + if (!empty($resources)) { foreach ($resources as $id_resource) { $ws_resource = new WorkstationResource($this->db); $ws_resource->fk_workstation = $this->id; @@ -677,7 +677,7 @@ class Workstation extends CommonObject $this->status = $status; - if(empty($status)) $this->setDisabled($user, $notrigger); + if (empty($status)) $this->setDisabled($user, $notrigger); else $this->setEnabled($user, $notrigger); } diff --git a/htdocs/workstation/class/workstationresource.class.php b/htdocs/workstation/class/workstationresource.class.php index 2cae732377a..b9897b6f541 100644 --- a/htdocs/workstation/class/workstationresource.class.php +++ b/htdocs/workstation/class/workstationresource.class.php @@ -46,7 +46,8 @@ class WorkstationResource extends CommonObject } } - static public function getAllResourcesOfWorkstation($fk_workstation) { + static public function getAllResourcesOfWorkstation($fk_workstation) + { global $db; @@ -55,17 +56,17 @@ class WorkstationResource extends CommonObject $resql = $db->query($sql); $TRes = array(); - if(!empty($resql)) { - while($res = $db->fetch_object($resql)) { + if (!empty($resql)) { + while ($res = $db->fetch_object($resql)) { $TRes[] = $res->fk_resource; } } return $TRes; - } - static public function deleteAllResourcesOfWorkstation($fk_workstation) { + static public function deleteAllResourcesOfWorkstation($fk_workstation) + { global $db; @@ -73,10 +74,8 @@ class WorkstationResource extends CommonObject $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; $resql = $db->query($sql); - if(empty($resql)) return 0; + if (empty($resql)) return 0; return 1; - } - } diff --git a/htdocs/workstation/class/workstationusergroup.class.php b/htdocs/workstation/class/workstationusergroup.class.php index af643a6d28e..1221476203c 100644 --- a/htdocs/workstation/class/workstationusergroup.class.php +++ b/htdocs/workstation/class/workstationusergroup.class.php @@ -46,7 +46,8 @@ class WorkstationUserGroup extends CommonObject } } - static public function getAllGroupsOfWorkstation($fk_workstation) { + static public function getAllGroupsOfWorkstation($fk_workstation) + { global $db; @@ -55,17 +56,17 @@ class WorkstationUserGroup extends CommonObject $resql = $db->query($sql); $TRes = array(); - if(!empty($resql)) { - while($res = $db->fetch_object($resql)) { + if (!empty($resql)) { + while ($res = $db->fetch_object($resql)) { $TRes[] = $res->fk_usergroup; } } return $TRes; - } - static public function deleteAllGroupsOfWorkstation($fk_workstation) { + static public function deleteAllGroupsOfWorkstation($fk_workstation) + { global $db; @@ -73,10 +74,8 @@ class WorkstationUserGroup extends CommonObject $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$obj->table_element.' WHERE fk_workstation = '.$fk_workstation; $resql = $db->query($sql); - if(empty($resql)) return 0; + if (empty($resql)) return 0; return 1; - } - } diff --git a/htdocs/workstation/workstation_card.php b/htdocs/workstation/workstation_card.php index 5ec3a1f6842..d28aecce67d 100755 --- a/htdocs/workstation/workstation_card.php +++ b/htdocs/workstation/workstation_card.php @@ -161,15 +161,10 @@ if (empty($reshook)) include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; if ($action == 'confirm_enable' && $confirm == "yes" && $permissiontoadd) { - - if(!empty($object->id)) $object->setStatus(1); - + if (!empty($object->id)) $object->setStatus(1); } elseif ($action == 'confirm_disable' && $confirm == "yes" && $permissiontoadd) { - - if(!empty($object->id)) $object->setStatus(0); - + if (!empty($object->id)) $object->setStatus(0); } - } @@ -418,11 +413,11 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field //unset($object->fields['fk_project']); // Hide field already shown in banner //unset($object->fields['fk_soc']); // Hide field already shown in banner - if($object->type === 'MACHINE') $object->fields['nb_operators_required']['visible'] = 0; + if ($object->type === 'MACHINE') $object->fields['nb_operators_required']['visible'] = 0; include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; // Groups - if($object->type !== 'MACHINE') { + if ($object->type !== 'MACHINE') { $toprint = array(); foreach ($object->usergroups as $id_group) { $g = new UserGroup($db); @@ -435,7 +430,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Resources - if($object->type !== 'HUMAN') { + if ($object->type !== 'HUMAN') { $toprint = array(); foreach ($object->resources as $id_resource) { $r = new Dolresource($db); @@ -469,7 +464,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (empty($reshook)) { - // Modify if ($permissiontoadd) { print ''.$langs->trans("Modify").''."\n"; @@ -503,7 +497,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } print ''."\n"; } - } // End of page diff --git a/htdocs/workstation/workstation_list.php b/htdocs/workstation/workstation_list.php index c9aa575fad2..c544446aabb 100755 --- a/htdocs/workstation/workstation_list.php +++ b/htdocs/workstation/workstation_list.php @@ -116,7 +116,7 @@ $search = array(); foreach ($object->fields as $key => $val) { if (GETPOST('search_'.$key, 'alpha') !== '') $search[$key] = GETPOST('search_'.$key, 'alpha'); - if(in_array($key, array('type', 'status')) && GETPOST('search_'.$key, 'alpha') == -1) $search[$key] = ''; + if (in_array($key, array('type', 'status')) && GETPOST('search_'.$key, 'alpha') == -1) $search[$key] = ''; } // List of fields to search into when doing a "search in all" From 5d23ab19828cd62d19f7b73caecec8c6150612dc Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Mon, 21 Dec 2020 12:38:13 +0100 Subject: [PATCH 030/223] FIX : file .back --- .../class/workstation.class.php.back | 1052 ----------------- 1 file changed, 1052 deletions(-) delete mode 100755 htdocs/workstation/class/workstation.class.php.back diff --git a/htdocs/workstation/class/workstation.class.php.back b/htdocs/workstation/class/workstation.class.php.back deleted file mode 100755 index f4666c352ce..00000000000 --- a/htdocs/workstation/class/workstation.class.php.back +++ /dev/null @@ -1,1052 +0,0 @@ - - * Copyright (C) ---Put here your own copyright and developer email--- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file class/workstation.class.php - * \ingroup workstation - * \brief This file is a CRUD class file for Workstation (Create/Read/Update/Delete) - */ - -// Put here all includes required by your class file -require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; -//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; -//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; - -/** - * Class for Workstation - */ -class Workstation extends CommonObject -{ - /** - * @var string ID of module. - */ - public $module = 'workstation'; - - /** - * @var string ID to identify managed object. - */ - public $element = 'workstation'; - - /** - * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. - */ - public $table_element = 'workstation_workstation'; - - /** - * @var int Does this object support multicompany module ? - * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table - */ - public $ismultientitymanaged = 0; - - /** - * @var int Does object support extrafields ? 0=No, 1=Yes - */ - public $isextrafieldmanaged = 1; - - /** - * @var string String with name of icon for workstation. Must be the part after the 'object_' into object_workstation.png - */ - public $picto = 'workstation@workstation'; - - - const STATUS_DRAFT = 0; - const STATUS_VALIDATED = 1; - const STATUS_CANCELED = 9; - - - /** - * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') - * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" - * 'label' the translation key. - * 'picto' is code of a picto to show before value in forms - * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) - * 'position' is the sort order of field. - * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). - * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) - * 'noteditable' says if field is not editable (1 or 0) - * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. - * 'index' if we want an index in database. - * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). - * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. - * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). - * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200' - * 'help' is a string visible as a tooltip on field - * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record - * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. - * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") - * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. - * 'comment' is not used. You can store here any text of your choice. It is not used by application. - * - * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. - */ - - // BEGIN MODULEBUILDER PROPERTIES - /** - * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. - */ - public $fields=array( - 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), - 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), - 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'help'=>"Help text", 'showoncombobox'=>'1',), - 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3,), - 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), - 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), - 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), - 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), - 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), - 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), - 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), - 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validé', '9'=>'Annulé'),), - 'nb_operators_required' => array('type'=>'integer', 'label'=>'NbOperatorsRequired', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), - 'thm_operator_estimated' => array('type'=>'double', 'label'=>'THMOperatorEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), - 'thm_machine_estimated' => array('type'=>'double', 'label'=>'THMMachineEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), - ); - public $rowid; - public $ref; - public $label; - public $description; - public $note_public; - public $note_private; - public $date_creation; - public $tms; - public $fk_user_creat; - public $fk_user_modif; - public $import_key; - public $status; - public $nb_operators_required; - public $thm_operator_estimated; - public $thm_machine_estimated; - // END MODULEBUILDER PROPERTIES - - - // If this object has a subtable with lines - - /** - * @var int Name of subtable line - */ - //public $table_element_line = 'workstation_workstationline'; - - /** - * @var int Field with ID of parent key if this object has a parent - */ - //public $fk_element = 'fk_workstation'; - - /** - * @var int Name of subtable class that manage subtable lines - */ - //public $class_element_line = 'Workstationline'; - - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables = array(); - - /** - * @var array List of child tables. To know object to delete on cascade. - * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will - * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object - */ - //protected $childtablesoncascade = array('workstation_workstationdet'); - - /** - * @var WorkstationLine[] Array of subtable lines - */ - //public $lines = array(); - - - - /** - * Constructor - * - * @param DoliDb $db Database handler - */ - public function __construct(DoliDB $db) - { - global $conf, $langs; - - $this->db = $db; - - if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; - if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; - - // Example to show how to set values of fields definition dynamically - /*if ($user->rights->workstation->workstation->read) { - $this->fields['myfield']['visible'] = 1; - $this->fields['myfield']['noteditable'] = 0; - }*/ - - // Unset fields that are disabled - foreach ($this->fields as $key => $val) - { - if (isset($val['enabled']) && empty($val['enabled'])) - { - unset($this->fields[$key]); - } - } - - // Translate some data of arrayofkeyval - if (is_object($langs)) - { - foreach ($this->fields as $key => $val) - { - if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) - { - foreach ($val['arrayofkeyval'] as $key2 => $val2) - { - $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); - } - } - } - } - } - - /** - * Create object into database - * - * @param User $user User that creates - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int <0 if KO, Id of created object if OK - */ - public function create(User $user, $notrigger = false) - { - return $this->createCommon($user, $notrigger); - } - - /** - * Clone an object into another one - * - * @param User $user User that creates - * @param int $fromid Id of object to clone - * @return mixed New object created, <0 if KO - */ - public function createFromClone(User $user, $fromid) - { - global $langs, $extrafields; - $error = 0; - - dol_syslog(__METHOD__, LOG_DEBUG); - - $object = new self($this->db); - - $this->db->begin(); - - // Load source object - $result = $object->fetchCommon($fromid); - if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines(); - - // get lines so they will be clone - //foreach($this->lines as $line) - // $line->fetch_optionals(); - - // Reset some properties - unset($object->id); - unset($object->fk_user_creat); - unset($object->import_key); - - // Clear fields - if (property_exists($object, 'ref')) $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; - if (property_exists($object, 'label')) $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } - if (property_exists($object, 'date_creation')) { $object->date_creation = dol_now(); } - if (property_exists($object, 'date_modification')) { $object->date_modification = null; } - // ... - // Clear extrafields that are unique - if (is_array($object->array_options) && count($object->array_options) > 0) - { - $extrafields->fetch_name_optionals_label($this->table_element); - foreach ($object->array_options as $key => $option) - { - $shortkey = preg_replace('/options_/', '', $key); - if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) - { - //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; - unset($object->array_options[$key]); - } - } - } - - // Create clone - $object->context['createfromclone'] = 'createfromclone'; - $result = $object->createCommon($user); - if ($result < 0) { - $error++; - $this->error = $object->error; - $this->errors = $object->errors; - } - - if (!$error) - { - // copy internal contacts - if ($this->copy_linked_contact($object, 'internal') < 0) - { - $error++; - } - } - - if (!$error) - { - // copy external contacts if same company - if (property_exists($this, 'socid') && $this->socid == $object->socid) - { - if ($this->copy_linked_contact($object, 'external') < 0) - $error++; - } - } - - unset($object->context['createfromclone']); - - // End - if (!$error) { - $this->db->commit(); - return $object; - } else { - $this->db->rollback(); - return -1; - } - } - - /** - * Load object in memory from the database - * - * @param int $id Id object - * @param string $ref Ref - * @return int <0 if KO, 0 if not found, >0 if OK - */ - public function fetch($id, $ref = null) - { - $result = $this->fetchCommon($id, $ref); - if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); - return $result; - } - - /** - * Load object lines in memory from the database - * - * @return int <0 if KO, 0 if not found, >0 if OK - */ - public function fetchLines() - { - $this->lines = array(); - - $result = $this->fetchLinesCommon(); - return $result; - } - - - /** - * Load list of objects in memory from the database. - * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK - */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') - { - global $conf; - - dol_syslog(__METHOD__, LOG_DEBUG); - - $records = array(); - - $sql = 'SELECT '; - $sql .= $this->getFieldList(); - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; - else $sql .= ' WHERE 1 = 1'; - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; - } - - if (!empty($sortfield)) { - $sql .= $this->db->order($sortfield, $sortorder); - } - if (!empty($limit)) { - $sql .= ' '.$this->db->plimit($limit, $offset); - } - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - $i = 0; - while ($i < ($limit ? min($limit, $num) : $num)) - { - $obj = $this->db->fetch_object($resql); - - $record = new self($this->db); - $record->setVarsFromFetchObj($obj); - - $records[$record->id] = $record; - - $i++; - } - $this->db->free($resql); - - return $records; - } else { - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); - - return -1; - } - } - - /** - * Update object into database - * - * @param User $user User that modifies - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int <0 if KO, >0 if OK - */ - public function update(User $user, $notrigger = false) - { - return $this->updateCommon($user, $notrigger); - } - - /** - * Delete object in database - * - * @param User $user User that deletes - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int <0 if KO, >0 if OK - */ - public function delete(User $user, $notrigger = false) - { - return $this->deleteCommon($user, $notrigger); - //return $this->deleteCommon($user, $notrigger, 1); - } - - /** - * Delete a line of object in database - * - * @param User $user User that delete - * @param int $idline Id of line to delete - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int >0 if OK, <0 if KO - */ - public function deleteLine(User $user, $idline, $notrigger = false) - { - if ($this->status < 0) - { - $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; - return -2; - } - - return $this->deleteLineCommon($user, $idline, $notrigger); - } - - - /** - * Validate object - * - * @param User $user User making status change - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers - * @return int <=0 if OK, 0=Nothing done, >0 if KO - */ - public function validate($user, $notrigger = 0) - { - global $conf, $langs; - - require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - - $error = 0; - - // Protection - if ($this->status == self::STATUS_VALIDATED) - { - dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); - return 0; - } - - /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->write)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->workstation_advance->validate)))) - { - $this->error='NotEnoughPermissions'; - dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); - return -1; - }*/ - - $now = dol_now(); - - $this->db->begin(); - - // Define new ref - if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life - { - $num = $this->getNextNumRef(); - } else { - $num = $this->ref; - } - $this->newref = $num; - - if (!empty($num)) { - // Validate - $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; - $sql .= " SET ref = '".$this->db->escape($num)."',"; - $sql .= " status = ".self::STATUS_VALIDATED; - if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."'"; - if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; - $sql .= " WHERE rowid = ".$this->id; - - dol_syslog(get_class($this)."::validate()", LOG_DEBUG); - $resql = $this->db->query($sql); - if (!$resql) - { - dol_print_error($this->db); - $this->error = $this->db->lasterror(); - $error++; - } - - if (!$error && !$notrigger) - { - // Call trigger - $result = $this->call_trigger('WORKSTATION_VALIDATE', $user); - if ($result < 0) $error++; - // End call triggers - } - } - - if (!$error) - { - $this->oldref = $this->ref; - - // Rename directory if dir was a temporary ref - if (preg_match('/^[\(]?PROV/i', $this->ref)) - { - // Now we rename also files into index - $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'workstation/".$this->db->escape($this->newref)."'"; - $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'workstation/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; - $resql = $this->db->query($sql); - if (!$resql) { $error++; $this->error = $this->db->lasterror(); } - - // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments - $oldref = dol_sanitizeFileName($this->ref); - $newref = dol_sanitizeFileName($num); - $dirsource = $conf->workstation->dir_output.'/workstation/'.$oldref; - $dirdest = $conf->workstation->dir_output.'/workstation/'.$newref; - if (!$error && file_exists($dirsource)) - { - dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); - - if (@rename($dirsource, $dirdest)) - { - dol_syslog("Rename ok"); - // Rename docs starting with $oldref with $newref - $listoffiles = dol_dir_list($conf->workstation->dir_output.'/workstation/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); - foreach ($listoffiles as $fileentry) - { - $dirsource = $fileentry['name']; - $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); - $dirsource = $fileentry['path'].'/'.$dirsource; - $dirdest = $fileentry['path'].'/'.$dirdest; - @rename($dirsource, $dirdest); - } - } - } - } - } - - // Set new ref and current status - if (!$error) - { - $this->ref = $num; - $this->status = self::STATUS_VALIDATED; - } - - if (!$error) - { - $this->db->commit(); - return 1; - } else { - $this->db->rollback(); - return -1; - } - } - - - /** - * Set draft status - * - * @param User $user Object user that modify - * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers - * @return int <0 if KO, >0 if OK - */ - public function setDraft($user, $notrigger = 0) - { - // Protection - if ($this->status <= self::STATUS_DRAFT) - { - return 0; - } - - /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) - { - $this->error='Permission denied'; - return -1; - }*/ - - return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'WORKSTATION_UNVALIDATE'); - } - - /** - * Set cancel status - * - * @param User $user Object user that modify - * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers - * @return int <0 if KO, 0=Nothing done, >0 if OK - */ - public function cancel($user, $notrigger = 0) - { - // Protection - if ($this->status != self::STATUS_VALIDATED) - { - return 0; - } - - /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) - { - $this->error='Permission denied'; - return -1; - }*/ - - return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'WORKSTATION_CLOSE'); - } - - /** - * Set back to validated status - * - * @param User $user Object user that modify - * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers - * @return int <0 if KO, 0=Nothing done, >0 if OK - */ - public function reopen($user, $notrigger = 0) - { - // Protection - if ($this->status != self::STATUS_CANCELED) - { - return 0; - } - - /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->write)) - || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation_advance->validate)))) - { - $this->error='Permission denied'; - return -1; - }*/ - - return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'WORKSTATION_REOPEN'); - } - - /** - * Return a link to the object card (with optionaly the picto) - * - * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) - * @param string $option On what the link point to ('nolink', ...) - * @param int $notooltip 1=Disable tooltip - * @param string $morecss Add more css on link - * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking - * @return string String with URL - */ - public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) - { - global $conf, $langs, $hookmanager; - - if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips - - $result = ''; - - $label = img_picto('', $this->picto).' '.$langs->trans("Workstation").''; - $label .= '
    '; - $label .= ''.$langs->trans('Ref').': '.$this->ref; - if (isset($this->status)) { - $label .= '
    '.$langs->trans("Status").": ".$this->getLibStatut(5); - } - - $url = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$this->id; - - if ($option != 'nolink') - { - // Add param to save lastsearch_values or not - $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); - if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; - if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; - } - - $linkclose = ''; - if (empty($notooltip)) - { - if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) - { - $label = $langs->trans("ShowWorkstation"); - $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; - } - $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; - $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; - } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); - - $linkstart = ''; - $linkend = ''; - - $result .= $linkstart; - - if (empty($this->showphoto_on_popup)) { - if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); - } else { - if ($withpicto) { - require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - - list($class, $module) = explode('@', $this->picto); - $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); - $filearray = dol_dir_list($upload_dir, "files"); - $filename = $filearray[0]['name']; - if (!empty($filename)) { - $pospoint = strpos($filearray[0]['name'], '.'); - - $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); - if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { - $result .= '
    No photo
    '; - } else { - $result .= '
    No photo
    '; - } - - $result .= ''; - } else { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); - } - } - } - - if ($withpicto != 2) $result .= $this->ref; - - $result .= $linkend; - //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); - - global $action, $hookmanager; - $hookmanager->initHooks(array('workstationdao')); - $parameters = array('id'=>$this->id, 'getnomurl'=>$result); - $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks - if ($reshook > 0) $result = $hookmanager->resPrint; - else $result .= $hookmanager->resPrint; - - return $result; - } - - /** - * Return the label of the status - * - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto - * @return string Label of status - */ - public function getLibStatut($mode = 0) - { - return $this->LibStatut($this->status, $mode); - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Return the status - * - * @param int $status Id status - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto - * @return string Label of status - */ - public function LibStatut($status, $mode = 0) - { - // phpcs:enable - if (empty($this->labelStatus) || empty($this->labelStatusShort)) - { - global $langs; - //$langs->load("workstation@workstation"); - $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft'); - $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); - $this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); - $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft'); - $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Enabled'); - $this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Disabled'); - } - - $statusType = 'status'.$status; - //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; - if ($status == self::STATUS_CANCELED) $statusType = 'status6'; - - return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); - } - - /** - * Load the info information in the object - * - * @param int $id Id of object - * @return void - */ - public function info($id) - { - $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; - $sql .= ' fk_user_creat, fk_user_modif'; - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - $sql .= ' WHERE t.rowid = '.$id; - $result = $this->db->query($sql); - if ($result) - { - if ($this->db->num_rows($result)) - { - $obj = $this->db->fetch_object($result); - $this->id = $obj->rowid; - if ($obj->fk_user_author) - { - $cuser = new User($this->db); - $cuser->fetch($obj->fk_user_author); - $this->user_creation = $cuser; - } - - if ($obj->fk_user_valid) - { - $vuser = new User($this->db); - $vuser->fetch($obj->fk_user_valid); - $this->user_validation = $vuser; - } - - if ($obj->fk_user_cloture) - { - $cluser = new User($this->db); - $cluser->fetch($obj->fk_user_cloture); - $this->user_cloture = $cluser; - } - - $this->date_creation = $this->db->jdate($obj->datec); - $this->date_modification = $this->db->jdate($obj->datem); - $this->date_validation = $this->db->jdate($obj->datev); - } - - $this->db->free($result); - } else { - dol_print_error($this->db); - } - } - - /** - * Initialise object with example values - * Id must be 0 if object instance is a specimen - * - * @return void - */ - public function initAsSpecimen() - { - $this->initAsSpecimenCommon(); - } - - /** - * Create an array of lines - * - * @return array|int array of lines if OK, <0 if KO - */ - public function getLinesArray() - { - $this->lines = array(); - - $objectline = new WorkstationLine($this->db); - $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.$this->id)); - - if (is_numeric($result)) - { - $this->error = $this->error; - $this->errors = $this->errors; - return $result; - } else { - $this->lines = $result; - return $this->lines; - } - } - - /** - * Returns the reference to the following non used object depending on the active numbering module. - * - * @return string Object free reference - */ - public function getNextNumRef() - { - global $langs, $conf; - $langs->load("workstation@workstation"); - - if (empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) { - $conf->global->WORKSTATION_WORKSTATION_ADDON = 'mod_workstation_standard'; - } - - if (!empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) - { - $mybool = false; - - $file = $conf->global->WORKSTATION_WORKSTATION_ADDON.".php"; - $classname = $conf->global->WORKSTATION_WORKSTATION_ADDON; - - // Include file with class - $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); - foreach ($dirmodels as $reldir) - { - $dir = dol_buildpath($reldir."core/modules/workstation/"); - - // Load file with numbering class (if found) - $mybool |= @include_once $dir.$file; - } - - if ($mybool === false) - { - dol_print_error('', "Failed to include file ".$file); - return ''; - } - - if (class_exists($classname)) { - $obj = new $classname(); - $numref = $obj->getNextValue($this); - - if ($numref != '' && $numref != '-1') - { - return $numref; - } else { - $this->error = $obj->error; - //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); - return ""; - } - } else { - print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; - return ""; - } - } else { - print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); - return ""; - } - } - - /** - * Create a document onto disk according to template module. - * - * @param string $modele Force template to use ('' to not force) - * @param Translate $outputlangs objet lang a utiliser pour traduction - * @param int $hidedetails Hide details of lines - * @param int $hidedesc Hide description - * @param int $hideref Hide ref - * @param null|array $moreparams Array to provide more information - * @return int 0 if KO, 1 if OK - */ - public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) - { - global $conf, $langs; - - $result = 0; - $includedocgeneration = 0; - - $langs->load("workstation@workstation"); - - if (!dol_strlen($modele)) { - $modele = 'standard_workstation'; - - if ($this->model_pdf) { - $modele = $this->model_pdf; - } elseif (!empty($conf->global->WORKSTATION_ADDON_PDF)) { - $modele = $conf->global->WORKSTATION_ADDON_PDF; - } - } - - $modelpath = "core/modules/workstation/doc/"; - - if ($includedocgeneration) { - $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); - } - - return $result; - } - - /** - * Action executed by scheduler - * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' - * Use public function doScheduledJob($param1, $param2, ...) to get parameters - * - * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) - */ - public function doScheduledJob() - { - global $conf, $langs; - - //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; - - $error = 0; - $this->output = ''; - $this->error = ''; - - dol_syslog(__METHOD__, LOG_DEBUG); - - $now = dol_now(); - - $this->db->begin(); - - // ... - - $this->db->commit(); - - return $error; - } -} - - -require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; - -/** - * Class WorkstationLine. You can also remove this and generate a CRUD class for lines objects. - */ -class WorkstationLine extends CommonObjectLine -{ - // To complete with content of an object WorkstationLine - // We should have a field rowid, fk_workstation and position - - /** - * @var int Does object support extrafields ? 0=No, 1=Yes - */ - public $isextrafieldmanaged = 0; - - /** - * Constructor - * - * @param DoliDb $db Database handler - */ - public function __construct(DoliDB $db) - { - $this->db = $db; - } -} From 5116337e0bcd2f47958157ab982b3e3ef10ad5dd Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Mon, 21 Dec 2020 13:29:44 +0100 Subject: [PATCH 031/223] FIX : stickler feedbacks --- htdocs/admin/workstation.php | 2 +- htdocs/core/modules/modWorkstation.class.php | 2 +- .../workstation/mod_workstation_advanced.php | 1 + .../workstation/mod_workstation_standard.php | 1 + .../workstation/modules_workstation.php | 1 + .../llx_workstation_workstation.key.sql | 2 +- .../tables/llx_workstation_workstation.sql | 2 +- .../llx_workstation_workstation_resource.sql | 2 +- ...llx_workstation_workstation_user_group.sql | 2 +- .../class/html.formresource.class.php | 1 + .../workstation/class/workstation.class.php | 8 ++--- .../class/workstationresource.class.php | 36 +++++++++++++++++++ .../class/workstationusergroup.class.php | 36 +++++++++++++++++++ htdocs/workstation/lib/workstation.lib.php | 2 +- .../lib/workstation_workstation.lib.php | 2 +- htdocs/workstation/workstation_agenda.php | 2 +- htdocs/workstation/workstation_card.php | 4 +-- htdocs/workstation/workstation_document.php | 2 +- htdocs/workstation/workstation_list.php | 2 +- htdocs/workstation/workstation_note.php | 2 +- 20 files changed, 94 insertions(+), 18 deletions(-) diff --git a/htdocs/admin/workstation.php b/htdocs/admin/workstation.php index 8f9ee369d4f..502a573e98b 100755 --- a/htdocs/admin/workstation.php +++ b/htdocs/admin/workstation.php @@ -1,6 +1,6 @@ - * Copyright (C) 2020 SuperAdmin + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/core/modules/modWorkstation.class.php b/htdocs/core/modules/modWorkstation.class.php index 216d591670a..499dcc5de48 100755 --- a/htdocs/core/modules/modWorkstation.class.php +++ b/htdocs/core/modules/modWorkstation.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2018-2019 Nicolas ZABOURI * Copyright (C) 2019-2020 Frédéric France - * Copyright (C) 2020 SuperAdmin + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/core/modules/workstation/mod_workstation_advanced.php b/htdocs/core/modules/workstation/mod_workstation_advanced.php index d9133b4063c..cf9a1247e2b 100755 --- a/htdocs/core/modules/workstation/mod_workstation_advanced.php +++ b/htdocs/core/modules/workstation/mod_workstation_advanced.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2008 Raphael Bertrand (Resultic) * Copyright (C) 2019 Frédéric France + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/core/modules/workstation/mod_workstation_standard.php b/htdocs/core/modules/workstation/mod_workstation_standard.php index 87e94233c88..0e793953f46 100755 --- a/htdocs/core/modules/workstation/mod_workstation_standard.php +++ b/htdocs/core/modules/workstation/mod_workstation_standard.php @@ -1,6 +1,7 @@ * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/core/modules/workstation/modules_workstation.php b/htdocs/core/modules/workstation/modules_workstation.php index bfd0f6c95ea..ec6c2fc945b 100755 --- a/htdocs/core/modules/workstation/modules_workstation.php +++ b/htdocs/core/modules/workstation/modules_workstation.php @@ -6,6 +6,7 @@ * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2012 Juanjo Menent * Copyright (C) 2014 Marcos García + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql b/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql index 2e013ee0128..6bdf16aa6d7 100755 --- a/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql +++ b/htdocs/install/mysql/tables/llx_workstation_workstation.key.sql @@ -1,4 +1,4 @@ --- Copyright (C) ---Put here your own copyright and developer email--- +-- Copyright (C) 2020 Gauthier VERDOL -- -- 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 diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation.sql b/htdocs/install/mysql/tables/llx_workstation_workstation.sql index 5c141ed59df..a4d9fd4dbc8 100755 --- a/htdocs/install/mysql/tables/llx_workstation_workstation.sql +++ b/htdocs/install/mysql/tables/llx_workstation_workstation.sql @@ -1,4 +1,4 @@ --- Copyright (C) ---Put here your own copyright and developer email--- +-- Copyright (C) 2020 Gauthier VERDOL -- -- 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 diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql b/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql index 1ab019f4385..92463ade696 100755 --- a/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql +++ b/htdocs/install/mysql/tables/llx_workstation_workstation_resource.sql @@ -1,4 +1,4 @@ --- Copyright (C) ---Put here your own copyright and developer email--- +-- Copyright (C) 2020 Gauthier VERDOL -- -- 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 diff --git a/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql b/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql index 9bffb4f30c9..9ecccc88d82 100755 --- a/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql +++ b/htdocs/install/mysql/tables/llx_workstation_workstation_user_group.sql @@ -1,4 +1,4 @@ --- Copyright (C) ---Put here your own copyright and developer email--- +-- Copyright (C) 2020 Gauthier VERDOL -- -- 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 diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php index 4a9b467c32c..30d7a13a194 100644 --- a/htdocs/resource/class/html.formresource.class.php +++ b/htdocs/resource/class/html.formresource.class.php @@ -75,6 +75,7 @@ class FormResource * @param int $outputmode 0=HTML select string, 1=Array, 2=without form tag * @param int $limit Limit number of answers * @param string $morecss More css + * @param bool $multiple add [] in the name of element and add 'multiple' attribut * @return string HTML string with */ public function select_resource_list($selected = '', $htmlname = 'fk_resource', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $event = array(), $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '', $multiple = false) diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index 42533c4100f..31497cbc919 100755 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -1,6 +1,6 @@ - * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 2020 Gauthier VERDOL * * 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 @@ -667,7 +667,7 @@ class Workstation extends CommonObject /** * Set draft status * - * @param User $user Object user that modify + * @param int $status New status to set * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers * @return int <0 if KO, >0 if OK */ @@ -677,8 +677,8 @@ class Workstation extends CommonObject $this->status = $status; - if (empty($status)) $this->setDisabled($user, $notrigger); - else $this->setEnabled($user, $notrigger); + if (empty($status)) return $this->setDisabled($user, $notrigger); + else return $this->setEnabled($user, $notrigger); } diff --git a/htdocs/workstation/class/workstationresource.class.php b/htdocs/workstation/class/workstationresource.class.php index b9897b6f541..cfb6706058d 100644 --- a/htdocs/workstation/class/workstationresource.class.php +++ b/htdocs/workstation/class/workstationresource.class.php @@ -1,4 +1,30 @@ + * Copyright (C) 2020 Gauthier VERDOL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/workstationresource.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for WorkstationResource (Create/Read/Update/Delete) + */ + +/** + * Class for WorkstationResource + */ class WorkstationResource extends CommonObject { @@ -46,6 +72,11 @@ class WorkstationResource extends CommonObject } } + /** + * Function used to get an array with all resources linked to a workstation + * @param int $fk_workstation id of workstation we need to get linked resources + * @return array + */ static public function getAllResourcesOfWorkstation($fk_workstation) { @@ -65,6 +96,11 @@ class WorkstationResource extends CommonObject return $TRes; } + /** + * Function used to remove all resources linked to a workstation + * @param int $fk_workstation id of workstation we need to remove linked resources + * @return int + */ static public function deleteAllResourcesOfWorkstation($fk_workstation) { diff --git a/htdocs/workstation/class/workstationusergroup.class.php b/htdocs/workstation/class/workstationusergroup.class.php index 1221476203c..6b6bcb5cb4c 100644 --- a/htdocs/workstation/class/workstationusergroup.class.php +++ b/htdocs/workstation/class/workstationusergroup.class.php @@ -1,4 +1,30 @@ + * Copyright (C) 2020 Gauthier VERDOL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/workstationusergroup.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for WorkstationUserGroup (Create/Read/Update/Delete) + */ + +/** + * Class for WorkstationUserGroup + */ class WorkstationUserGroup extends CommonObject { @@ -46,6 +72,11 @@ class WorkstationUserGroup extends CommonObject } } + /** + * Function used to get an array with all usergroups linked to a workstation + * @param int $fk_workstation id of workstation we need to get linked usergroups + * @return array + */ static public function getAllGroupsOfWorkstation($fk_workstation) { @@ -65,6 +96,11 @@ class WorkstationUserGroup extends CommonObject return $TRes; } + /** + * Function used to remove all usergroups linked to a workstation + * @param int $fk_workstation id of workstation we need to remove linked usergroups + * @return int + */ static public function deleteAllGroupsOfWorkstation($fk_workstation) { diff --git a/htdocs/workstation/lib/workstation.lib.php b/htdocs/workstation/lib/workstation.lib.php index 526323ec45d..18307d0cd3a 100755 --- a/htdocs/workstation/lib/workstation.lib.php +++ b/htdocs/workstation/lib/workstation.lib.php @@ -1,5 +1,5 @@ * * 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 diff --git a/htdocs/workstation/lib/workstation_workstation.lib.php b/htdocs/workstation/lib/workstation_workstation.lib.php index 1c6b7492f0c..cc7fcc58f89 100755 --- a/htdocs/workstation/lib/workstation_workstation.lib.php +++ b/htdocs/workstation/lib/workstation_workstation.lib.php @@ -1,5 +1,5 @@ * * 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 diff --git a/htdocs/workstation/workstation_agenda.php b/htdocs/workstation/workstation_agenda.php index 132acc02bee..e2951554488 100755 --- a/htdocs/workstation/workstation_agenda.php +++ b/htdocs/workstation/workstation_agenda.php @@ -1,6 +1,6 @@ - * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/workstation/workstation_card.php b/htdocs/workstation/workstation_card.php index d28aecce67d..e5d51b20c84 100755 --- a/htdocs/workstation/workstation_card.php +++ b/htdocs/workstation/workstation_card.php @@ -422,7 +422,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea foreach ($object->usergroups as $id_group) { $g = new UserGroup($db); $g->fetch($id_group); - $toprint[] = '
  • ' . $g->getNomUrl(1) . '
  • '; + $toprint[] = '
  • ' . $g->getNomUrl(1) . '
  • '; } print '' . $langs->trans('Groups') . ''; print '
      ' . implode(' ', $toprint) . '
    '; @@ -435,7 +435,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea foreach ($object->resources as $id_resource) { $r = new Dolresource($db); $r->fetch($id_resource); - $toprint[] = '
  • ' . $r->getNomUrl(1) . '
  • '; + $toprint[] = '
  • ' . $r->getNomUrl(1) . '
  • '; } print '' . $langs->trans('Machines') . ''; print '
      ' . implode(' ', $toprint) . '
    '; diff --git a/htdocs/workstation/workstation_document.php b/htdocs/workstation/workstation_document.php index 104ea93c4db..89a34f55549 100755 --- a/htdocs/workstation/workstation_document.php +++ b/htdocs/workstation/workstation_document.php @@ -1,6 +1,6 @@ - * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/workstation/workstation_list.php b/htdocs/workstation/workstation_list.php index c544446aabb..d4da9bd246f 100755 --- a/htdocs/workstation/workstation_list.php +++ b/htdocs/workstation/workstation_list.php @@ -1,6 +1,6 @@ - * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 2020 Gauthier VERDOL * * 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 diff --git a/htdocs/workstation/workstation_note.php b/htdocs/workstation/workstation_note.php index b8e85ddaf6f..a9d8a7f3fc2 100755 --- a/htdocs/workstation/workstation_note.php +++ b/htdocs/workstation/workstation_note.php @@ -1,6 +1,6 @@ - * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 2020 Gauthier VERDOL * * 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 From 64a62bf2c2ac0d5747aa14f012e5098d853599b8 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Tue, 22 Dec 2020 09:37:30 +0100 Subject: [PATCH 032/223] FIX (PR #15346 comment) use dol_mktime, not mktime --- htdocs/core/class/extrafields.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index b5d4852d128..1144cf5c682 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -2181,12 +2181,12 @@ class ExtraFields if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) { // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc. $value_key = array( - 'start' => mktime( + 'start' => dol_mktime( 0, 0, 0, GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int')), - 'end' => mktime( + 'end' => dol_mktime( 23, 59, 59, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), From fefc9040ab56747c450ce90de70a0360e1090fe6 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 22 Dec 2020 12:52:01 +0100 Subject: [PATCH 033/223] NEW : Display extrafields (for lines/det into line tr instead of ugly other tr --- composer.json | 2 +- htdocs/core/class/commonobjectline.class.php | 251 +++++++++++++++++++ htdocs/core/class/extrafields.class.php | 37 ++- htdocs/core/tpl/objectline_create.tpl.php | 7 +- htdocs/core/tpl/objectline_edit.tpl.php | 14 +- htdocs/core/tpl/objectline_view.tpl.php | 13 +- 6 files changed, 293 insertions(+), 31 deletions(-) diff --git a/composer.json b/composer.json index bd81e101cfc..a943fbe0aa3 100644 --- a/composer.json +++ b/composer.json @@ -59,4 +59,4 @@ "ext-zip" : "ODT, Excel and file compression support", "ext-xml" : "Excel support" } -} \ No newline at end of file +} diff --git a/htdocs/core/class/commonobjectline.class.php b/htdocs/core/class/commonobjectline.class.php index 0d4cfbe4f34..806e0f2a663 100644 --- a/htdocs/core/class/commonobjectline.class.php +++ b/htdocs/core/class/commonobjectline.class.php @@ -100,4 +100,255 @@ abstract class CommonObjectLine extends CommonObject // Currently we need function at end of file CommonObject for all object lines. Should find a way to avoid duplicate code. // For the moment we use the extends on CommonObject until PHP min is 5.4 so use Traits. + + /** + * Function to show lines of extrafields with output datas. + * This function is responsible to output the and according to correct number of columns received into $params['colspan'] + * + * @param Extrafields $extrafields Extrafield Object + * @param string $mode Show output ('view') or input ('create' or 'edit') for extrafield + * @param array $params Optional parameters. Example: array('style'=>'class="oddeven"', 'colspan'=>$colspan) + * @param string $keysuffix Suffix string to add after name and id of field (can be used to avoid duplicate names) + * @param string $keyprefix Prefix string to add before name and id of field (can be used to avoid duplicate names) + * @param string $onetrtd All fields in same tr td. Used by objectline_create.tpl.php for example. + * @return string + */ + public function showOptionals($extrafields, $mode = 'view', $params = null, $keysuffix = '', $keyprefix = '', $onetrtd = 0) + { + global $db, $conf, $langs, $action, $form, $hookmanager; + + if (!is_object($form)) $form = new Form($db); + + $out = ''; + + $parameters = array(); + $reshook = $hookmanager->executeHooks('showOptionals', $parameters, $this, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) + { + if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label']) > 0) + { + $out .= "\n"; + $out .= ' '; + $out .= "\n"; + + $extrafields_collapse_num = ''; + $e = 0; + foreach ($extrafields->attributes[$this->table_element]['label'] as $key=>$label) + { + // Show only the key field in params + if (is_array($params) && array_key_exists('onlykey', $params) && $key != $params['onlykey']) continue; + + // Test on 'enabled' ('enabled' is different than 'list' = 'visibility') + $enabled = 1; + if ($enabled && isset($extrafields->attributes[$this->table_element]['enabled'][$key])) + { + $enabled = dol_eval($extrafields->attributes[$this->table_element]['enabled'][$key], 1); + } + if (empty($enabled)) continue; + + $visibility = 1; + if ($visibility && isset($extrafields->attributes[$this->table_element]['list'][$key])) + { + $visibility = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1); + } + + $perms = 1; + if ($perms && isset($extrafields->attributes[$this->table_element]['perms'][$key])) + { + $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1); + } + + if (($mode == 'create') && abs($visibility) != 1 && abs($visibility) != 3) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list + elseif (($mode == 'edit') && abs($visibility) != 1 && abs($visibility) != 3 && abs($visibility) != 4) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list and <> 4 = not visible at the creation + elseif ($mode == 'view' && empty($visibility)) continue; + if (empty($perms)) continue; + // Load language if required + if (!empty($extrafields->attributes[$this->table_element]['langfile'][$key])) { + $langs->load($extrafields->attributes[$this->table_element]['langfile'][$key]); + } + + switch ($mode) { + case "view": + $value = $this->array_options["options_".$key.$keysuffix]; // Value may be clean or formated later + break; + case "create": + case "edit": + // We get the value of property found with GETPOST so it takes into account: + // default values overwrite, restore back to list link, ... (but not 'default value in database' of field) + $check = 'alphanohtml'; + if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('html', 'text'))) { + $check = 'restricthtml'; + } + $getposttemp = GETPOST($keyprefix.'options_'.$key.$keysuffix, $check, 3); // GETPOST can get value from GET, POST or setup of default values overwrite. + // GETPOST("options_" . $key) can be 'abc' or array(0=>'abc') + if (is_array($getposttemp) || $getposttemp != '' || GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)) + { + if (is_array($getposttemp)) { + // $getposttemp is an array but following code expects a comma separated string + $value = implode(",", $getposttemp); + } else { + $value = $getposttemp; + } + } else { + $value = $this->array_options["options_".$key]; // No GET, no POST, no default value, so we take value of object. + } + //var_dump($keyprefix.' - '.$key.' - '.$keysuffix.' - '.$keyprefix.'options_'.$key.$keysuffix.' - '.$this->array_options["options_".$key.$keysuffix].' - '.$getposttemp.' - '.$value); + break; + } + + if ($extrafields->attributes[$this->table_element]['type'][$key] == 'separate') + { + $extrafields_collapse_num = ''; + $extrafield_param = $extrafields->attributes[$this->table_element]['param'][$key]; + if (!empty($extrafield_param) && is_array($extrafield_param)) { + $extrafield_param_list = array_keys($extrafield_param['options']); + + if (count($extrafield_param_list) > 0) { + $extrafield_collapse_display_value = intval($extrafield_param_list[0]); + + if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) { + $extrafields_collapse_num = $extrafields->attributes[$this->table_element]['pos'][$key]; + } + } + } + + $out .= $extrafields->showSeparator($key, $this, 0, 'line'); + } else { + $class = (!empty($extrafields->attributes[$this->table_element]['hidden'][$key]) ? 'hideobject ' : ''); + $csstyle = ''; + if (is_array($params) && count($params) > 0) { + if (array_key_exists('class', $params)) { + $class .= $params['class'].' '; + } + if (array_key_exists('style', $params)) { + $csstyle = $params['style']; + } + } + + // add html5 elements + $domData = ' data-element="extrafield"'; + $domData .= ' data-targetelement="'.$this->element.'"'; + $domData .= ' data-targetid="'.$this->id.'"'; + + $html_id = (empty($this->id) ? '' : 'extrarow-'.$this->element.'_'.$key.'_'.$this->id); + + // Convert date into timestamp format (value in memory must be a timestamp) + if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('date', 'datetime'))) + { + $datenotinstring = $this->array_options['options_'.$key]; + if (!is_numeric($this->array_options['options_'.$key])) // For backward compatibility + { + $datenotinstring = $this->db->jdate($datenotinstring); + } + $value = (GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)) ? dol_mktime(GETPOST($keyprefix.'options_'.$key.$keysuffix."hour", 'int', 3), GETPOST($keyprefix.'options_'.$key.$keysuffix."min", 'int', 3), 0, GETPOST($keyprefix.'options_'.$key.$keysuffix."month", 'int', 3), GETPOST($keyprefix.'options_'.$key.$keysuffix."day", 'int', 3), GETPOST($keyprefix.'options_'.$key.$keysuffix."year", 'int', 3)) : $datenotinstring; + } + // Convert float submited string into real php numeric (value in memory must be a php numeric) + if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('price', 'double'))) + { + $value = (GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix) || $value) ? price2num($value) : $this->array_options['options_'.$key]; + } + + // HTML, text, select, integer and varchar: take into account default value in database if in create mode + if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('html', 'text', 'varchar', 'select', 'int'))) + { + if ($action == 'create') $value = (GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix) || $value) ? $value : $extrafields->attributes[$this->table_element]['default'][$key]; + } + + $labeltoshow = $langs->trans($label); + $helptoshow = $langs->trans($extrafields->attributes[$this->table_element]['help'][$key]); + + $out .= '
    '; + $out .= '
    attributes[$this->table_element]['help'][$key])) $out .= $form->textwithpicto($labeltoshow, $helptoshow); + else $out .= $labeltoshow; + if ($mode != 'view' && !empty($extrafields->attributes[$this->table_element]['required'][$key])) $out .= ' *'; + } else { + if ($mode != 'view' && !empty($extrafields->attributes[$this->table_element]['required'][$key])) $out .= ' fieldrequired'; + $out .= '">'; + if (!empty($extrafields->attributes[$this->table_element]['help'][$key])) $out .= $form->textwithpicto($labeltoshow, $helptoshow); + else $out .= $labeltoshow; + } + $out .= '
    '; + + $html_id = !empty($this->id) ? $this->element.'_extras_'.$key.'_'.$this->id : ''; + + $out .= '
    '; + + switch ($mode) { + case "view": + $out .= $extrafields->showOutputField($key, $value); + break; + case "create": + $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id, $this->table_element); + break; + case "edit": + $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id, $this->table_element); + break; + } + + $out .= '
    '; + + /*for($ii = 0; $ii < ($colspan - 1); $ii++) + { + $out .=''; + }*/ + + if (!empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && (($e % 2) == 1)) $out .= '
    '; + else $out .= ''; + $e++; + } + } + $out .= "\n"; + // Add code to manage list depending on others + if (!empty($conf->use_javascript_ajax)) { + $out .= ' + '."\n"; + } + + $out .= ' '."\n"; + } + } + + $out .= $hookmanager->resPrint; + + return $out; + } } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index d041aba45f4..e6a11b17c67 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1912,15 +1912,28 @@ class ExtraFields * @param string $key Key of attribute * @param string $object Object * @param int $colspan Value of colspan to use (it must includes the first column with title) + * @param string $typeform "card" for from display, "line" for docuement line display (exstraiedls on propal line, order line, etc...) * @return string HTML code with line for separator */ - public function showSeparator($key, $object, $colspan = 2) + public function showSeparator($key, $object, $colspan = 2, $typeform='card') { global $langs; - $out = ''; + if ($typeform=='card') { + $tagtype='tr'; + $tagtype_dyn='td'; + }elseif ($typeform=='line') { + $tagtype='div'; + $tagtype_dyn='span'; + } + + $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">'; + $out .= '<'.$tagtype_dyn.' '.(!empty($colspan)?'colspan="' . $colspan . '"':'').'>'; + $out .=''; $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]); - $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; $extrafield_param = $this->attributes[$object->table_element]['param'][$key]; if (!empty($extrafield_param) && is_array($extrafield_param)) { @@ -1930,27 +1943,27 @@ class ExtraFields $extrafield_collapse_display_value = intval($extrafield_param_list[0]); if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) { // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup. - $collapse_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); - $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key]; + $collapse_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.(!empty($object->id)?'_'.$object->id:'')]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.(!empty($object->id)?'_'.$object->id:'')] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); + $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:''); $out .= ''; $out .= ''."\n"; - } - - $out .= ' '."\n"; - } - } - - $out .= $hookmanager->resPrint; - - return $out; - } } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 0e0f5acd4a4..0800a568d84 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1902,19 +1902,20 @@ class ExtraFields * @param string $key Key of attribute * @param string $object Object * @param int $colspan Value of colspan to use (it must includes the first column with title) - * @param string $typeform "card" for from display, "line" for docuement line display (exstraiedls on propal line, order line, etc...) + * @param string $display_type "card" for form display, "line" for document line display (extrafields on propal line, order line, etc...) * @return string HTML code with line for separator */ - public function showSeparator($key, $object, $colspan = 2, $typeform='card') + public function showSeparator($key, $object, $colspan = 2, $display_type = 'card') { global $langs; - if ($typeform=='card') { + if ($display_type=='card') { $tagtype='tr'; $tagtype_dyn='td'; - }elseif ($typeform=='line') { + }elseif ($display_type=='line') { $tagtype='div'; $tagtype_dyn='span'; + $colspan=0; } $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">'; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index cced0915681..dcc2257f2c5 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -321,7 +321,7 @@ if ($nolinesbefore) { } if (is_object($objectline)) { print '
    '; - print $objectline->showOptionals($extrafields, 'edit', array(), '', '', 1); + print $objectline->showOptionals($extrafields, 'edit', array(), '', '', 1, 'line'); print '
    '; } echo ''; diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 3115e4e2f0c..a174c82544d 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -129,7 +129,7 @@ $coldisplay++; if (!empty($extrafields)) { print '
    '; - print $line->showOptionals($extrafields, 'edit', array('class'=>'tredited'), '', '', 1); + print $line->showOptionals($extrafields, 'edit', array('class'=>'tredited'), '', '', 1, 'line'); print '
    '; } diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php index 337970412de..e4ca44438f7 100644 --- a/htdocs/core/tpl/objectline_view.tpl.php +++ b/htdocs/core/tpl/objectline_view.tpl.php @@ -162,7 +162,7 @@ if (($line->info_bits & 2) == 2) { if (!empty($extrafields)) { print '
    '; - print $line->showOptionals($extrafields, 'view', array(), '', '', 1); + print $line->showOptionals($extrafields, 'view', array(), '', '', 1, 'line'); print '
    '; } } From ff25003025626eaa74514c42ff52aea9bc3d22e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 5 Jan 2021 08:59:46 +0100 Subject: [PATCH 058/223] fix unknown variable --- .../bank/class/api_bankaccounts.class.php | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index 9ab02d8b18a..be37ec23403 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -81,10 +81,8 @@ class BankAccounts extends DolibarrApi $sql .= " AND c.fk_categorie = ".$this->db->escape($category)." AND c.fk_account = t.rowid "; } // Add sql filters - if ($sqlfilters) - { - if (!DolibarrApi::_checkFilters($sqlfilters)) - { + if ($sqlfilters) { + if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; @@ -93,8 +91,7 @@ class BankAccounts extends DolibarrApi $sql .= $this->db->order($sortfield, $sortorder); if ($limit) { - if ($page < 0) - { + if ($page < 0) { $page = 0; } $offset = $limit * $page; @@ -222,12 +219,10 @@ class BankAccounts extends DolibarrApi throw new RestException(404, 'The BankAccount for bankaccount_to_id provided does not exist.'); } - if ($accountto->currency_code == $accountfrom->currency_code) - { + if ($accountto->currency_code == $accountfrom->currency_code) { $amount_to = $amount; } else { - if (!$amount_to || empty($amount_to)) - { + if (!$amount_to || empty($amount_to)) { throw new RestException(422, 'You must provide amount_to value since bankaccount_from and bankaccount_to does not share the same currency.'); } } @@ -244,8 +239,7 @@ class BankAccounts extends DolibarrApi $typefrom = 'PRE'; $typeto = 'VIR'; - if ($accountto->courant == Account::TYPE_CASH || $accountfrom->courant == Account::TYPE_CASH) - { + if ($accountto->courant == Account::TYPE_CASH || $accountfrom->courant == Account::TYPE_CASH) { // This is transfer of change $typefrom = 'LIQ'; $typeto = 'LIQ'; @@ -291,8 +285,7 @@ class BankAccounts extends DolibarrApi $error++; } - if (!$error) - { + if (!$error) { $this->db->commit(); return array( @@ -327,12 +320,13 @@ class BankAccounts extends DolibarrApi } foreach ($request_data as $field => $value) { - if ($field == 'id') continue; + if ($field == 'id') { + continue; + } $account->$field = $value; } - if ($account->update(DolibarrApiAccess::$user) > 0) - { + if ($account->update(DolibarrApiAccess::$user) > 0) { return $this->get($id); } else { throw new RestException(500, $account->error); @@ -380,8 +374,9 @@ class BankAccounts extends DolibarrApi { $account = array(); foreach (BankAccounts::$FIELDS as $field) { - if (!isset($data[$field])) + if (!isset($data[$field])) { throw new RestException(400, "$field field missing"); + } $account[$field] = $data[$field]; } return $account; @@ -433,10 +428,8 @@ class BankAccounts extends DolibarrApi $sql .= " WHERE fk_account = ".$id; // Add sql filters - if ($sqlfilters) - { - if (!DolibarrApi::_checkFilters($sqlfilters)) - { + if ($sqlfilters) { + if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; @@ -457,7 +450,7 @@ class BankAccounts extends DolibarrApi } } } else { - throw new RestException(503, 'Error when retrieving list of account lines: '.$accountLine->error); + throw new RestException(503, 'Error when retrieving list of account lines: '.$this->db->lasterror()); } return $list; @@ -476,8 +469,8 @@ class BankAccounts extends DolibarrApi * @param string $cheque_writer Name of cheque writer {@from body} * @param string $cheque_bank Bank of cheque writer {@from body} * @param string $accountancycode Accountancy code {@from body} - * @param int $datev Payment date value (timestamp) {@from body} {@type timestamp} - * @param string $num_releve Bank statement numero {@from body} + * @param int $datev Payment date value (timestamp) {@from body} {@type timestamp} + * @param string $num_releve Bank statement numero {@from body} * @return int ID of line * * @url POST {id}/lines @@ -502,8 +495,11 @@ class BankAccounts extends DolibarrApi $cheque_number, $category, DolibarrApiAccess::$user, - $cheque_writer, $cheque_bank, $accountancycode, - $datev, $num_releve + $cheque_writer, + $cheque_bank, + $accountancycode, + $datev, + $num_releve ); if ($result < 0) { throw new RestException(503, 'Error when adding line to account: '.$account->error); From f845adf3431cde836d9238bf1ce1c866451d9b7c Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 5 Jan 2021 09:57:35 +0100 Subject: [PATCH 059/223] FIX use GETPOST before --- htdocs/admin/accountant.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/accountant.php b/htdocs/admin/accountant.php index 3647c10f5ea..8f20ab43c84 100644 --- a/htdocs/admin/accountant.php +++ b/htdocs/admin/accountant.php @@ -114,53 +114,53 @@ print ''.$langs->trans( // Name print ''; -print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"').'>'."\n"; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"').'>'."\n"; // Address print ''; -print ''."\n"; +print ''."\n"; print ''; -print ''."\n"; +print ''."\n"; print ''; -print ''."\n"; +print ''."\n"; // Country print ''; print img_picto('', 'globe-americas', 'class="paddingrightonly"'); -print $form->select_country((!empty($conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY) ? $conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY : GETPOST('country_id', 'int')), 'country_id'); +print $form->select_country((GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : (!empty($conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY) ? $conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY : '')), 'country_id'); if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); print ''."\n"; print ''; -$formcompany->select_departement((!empty($conf->global->MAIN_INFO_ACCOUNTANT_STATE) ? $conf->global->MAIN_INFO_ACCOUNTANT_STATE : GETPOST('state_id', 'alpha')), (!empty($conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY) ? $conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY : GETPOST('country_id', 'int')), 'state_id'); +$formcompany->select_departement((GETPOSTISSET('state_id') ? GETPOST('state_id', 'alpha') : (!empty($conf->global->MAIN_INFO_ACCOUNTANT_STATE) ? $conf->global->MAIN_INFO_ACCOUNTANT_STATE : '')), (GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : (!empty($conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY) ? $conf->global->MAIN_INFO_ACCOUNTANT_COUNTRY : '')), 'state_id'); print ''."\n"; print ''; print img_picto('', 'object_phoning', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; print ''; print img_picto('', 'object_phoning_fax', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; print ''; print img_picto('', 'object_email', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Web print ''; print img_picto('', 'globe', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Code print ''; -print ''."\n"; +print ''."\n"; // Note print ''; From 889d73d8e3a8c5aeabb57754c60bb8b21e91ce93 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 5 Jan 2021 10:16:24 +0100 Subject: [PATCH 060/223] FIX avoid php8 warning --- htdocs/admin/company.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index fd3f7505778..2801951974e 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -393,18 +393,18 @@ print ''.$langs->trans( // Name print ''; -print 'global->MAIN_INFO_SOCIETE_NOM) ? ' autofocus="autofocus"' : '').'>'."\n"; +print 'global->MAIN_INFO_SOCIETE_NOM) ? ' autofocus="autofocus"' : '').'>'."\n"; // Address print ''; -print ''."\n"; +print ''."\n"; // Zip print ''; -print ''."\n"; +print ''."\n"; print ''; -print ''."\n"; +print ''."\n"; // Country print ''; @@ -431,25 +431,25 @@ print ''."\n"; // Phone print ''; print img_picto('', 'object_phoning', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Fax print ''; print img_picto('', 'object_phoning_fax', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Email print ''; print img_picto('', 'object_email', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Web print ''; print img_picto('', 'globe', '', false, 0, 0, '', 'paddingright'); -print ''; +print ''; print ''."\n"; // Barcode @@ -457,7 +457,7 @@ if (!empty($conf->barcode->enabled)) { print ''; print ''; print ''; - print ''; + print ''; print ''; } @@ -549,7 +549,7 @@ $langs->load("companies"); // Managing Director(s) print ''; -print ''; +print ''; // GDPR contact print ''; @@ -559,7 +559,7 @@ print ''; -print ''; +print ''; // Juridical Status print ''; From 4b45c5e72365aa61eab5ab4487fd0df2d5f25bac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Jan 2021 12:29:13 +0100 Subject: [PATCH 061/223] Trans --- htdocs/core/lib/project.lib.php | 8 +++++--- htdocs/langs/en_US/projects.lang | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 74e624ca7cb..3c8a79a9249 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -2526,13 +2526,15 @@ function getTaskProgressBadge($task, $label = '', $tooltip = '') if (doubleval($progressCalculated) > doubleval($task->progress * $warningRatio)) { $badgeClass .= 'badge-danger'; - if (empty($tooltip)) $tooltip = $task->progress.'% < '.$langs->trans("Expected").' '.$progressCalculated.'%'; + if (empty($tooltip)) { + $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; + } } elseif (doubleval($progressCalculated) > doubleval($task->progress)) { // warning if close at 10% $badgeClass .= 'badge-warning'; - if (empty($tooltip)) $tooltip = $task->progress.'% < '.$langs->trans("Expected").' '.$progressCalculated.'%'; + if (empty($tooltip)) $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } else { $badgeClass .= 'badge-success'; - if (empty($tooltip)) $tooltip = $task->progress.'% >= '.$langs->trans("Expected").' '.$progressCalculated.'%'; + if (empty($tooltip)) $tooltip = $task->progress.'% >= '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } } } diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index f5f6bf3dd9d..2aedbd53377 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -85,6 +85,7 @@ ProgressCalculated=Progress on consumption WhichIamLinkedTo=which I'm linked to WhichIamLinkedToProject=which I'm linked to project Time=Time +TimeConsumed=Consumed ListOfTasks=List of tasks GoToListOfTimeConsumed=Go to list of time consumed GanttView=Gantt View From 8dc4e5929c694cf712aa4a0b215081d2b17464a0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Jan 2021 12:43:57 +0100 Subject: [PATCH 062/223] Fix var not defined --- htdocs/comm/action/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index b37762a644a..dc0ada64eb3 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -214,6 +214,7 @@ llxHeader('', $langs->trans("Agenda"), $help_url); $form = new Form($db); $companystatic = new Societe($db); $contactstatic = new Contact($db); +$userstatic = new User($db); $now = dol_now(); $nowarray = dol_getdate($now); @@ -1071,7 +1072,6 @@ if (count($listofextcals)) { $event->id = $icalevent['UID']; $event->ref = $event->id; - $userId = $userstatic->findUserIdByEmail($namecal); if (!empty($userId) && $userId > 0) { From 9764f086d30c5cd29292ffe5a8ae3c16a56bedd4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Jan 2021 14:27:42 +0100 Subject: [PATCH 063/223] Fix Field code is mandatory but not field note in tax dictionary --- htdocs/admin/dict.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index d06f8a2ce31..05149030f9e 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -692,7 +692,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($value == 'sortorder') continue; // For a column name 'sortorder', we use the field name 'position' if ((!GETPOSTISSET($value) || GETPOST($value) == '') && (!in_array($listfield[$f], array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto')) // Fields that are not mandatory - && (!($id == 10 && $listfield[$f] == 'code')) // Code is mandatory fir table 10 + && ($id != 10 || ($listfield[$f] != 'code' && $listfield[$f] != 'note')) // Field code and note is not mandatory for dictionary table 10 ) ) { $ok = 0; @@ -757,9 +757,9 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($_POST["accountancy_code"] <= 0) $_POST["accountancy_code"] = ''; // If empty, we force to null if ($_POST["accountancy_code_sell"] <= 0) $_POST["accountancy_code_sell"] = ''; // If empty, we force to null if ($_POST["accountancy_code_buy"] <= 0) $_POST["accountancy_code_buy"] = ''; // If empty, we force to null - if ($id == 10 && GETPOSTISSET("code")) // Spaces are not allowed into code + if ($id == 10 && GETPOSTISSET("code")) // Spaces are not allowed into code for tax dictionary { - $_POST["code"] = preg_replace('/\s/', '', $_POST["code"]); + $_POST["code"] = preg_replace('/[^a-zA-Z0-9\-\+]/', '', $_POST["code"]); } // If check ok and action add, add the line @@ -826,8 +826,13 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $result = $db->query($sql); if ($result) // Add is ok { - setEventMessages($langs->transnoentities("RecordSaved"), null, 'mesgs'); - $_POST = array('id'=>$id); // Clean $_POST array, we keep only + setEventMessages($langs->transnoentities("RecordCreatedSuccessfully"), null, 'mesgs'); + + // Clean $_POST array, we keep only id of dictionary + if ($id == 10 && GETPOST('country', 'int') > 0) { + $search_country_id = GETPOST('country', 'int'); + } + $_POST = array('id'=>$id); } else { if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { setEventMessages($langs->transnoentities("ErrorRecordAlreadyExists"), null, 'errors'); From 27c32560c6e359b7fbe6cdd81dbd4201fed05a57 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 5 Jan 2021 14:46:50 +0100 Subject: [PATCH 064/223] Merge develop --- ChangeLog | 6 +- htdocs/commande/list.php | 2 +- htdocs/compta/accounting-files.php | 17 +- htdocs/compta/bank/class/account.class.php | 6 +- .../bank/class/api_bankaccounts.class.php | 26 +- htdocs/compta/paiement.php | 6 +- htdocs/contrat/card.php | 3 +- htdocs/core/boxes/box_fournisseurs.php | 11 +- htdocs/core/class/CMailFile.class.php | 34 +- htdocs/core/class/commonobject.class.php | 1 + htdocs/core/class/html.formmail.class.php | 301 +++++++----------- htdocs/core/lib/functions.lib.php | 2 +- htdocs/core/lib/sendings.lib.php | 2 +- htdocs/core/tpl/object_discounts.tpl.php | 12 +- htdocs/expedition/contact.php | 4 +- htdocs/expedition/list.php | 4 +- htdocs/fourn/commande/list.php | 2 +- htdocs/loan/class/paymentloan.class.php | 2 +- htdocs/loan/payment/payment.php | 4 +- htdocs/reception/contact.php | 9 +- htdocs/reception/list.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 2 +- htdocs/user/list.php | 2 +- .../email_unpaid_invoices_to_customers.php | 2 +- 24 files changed, 208 insertions(+), 254 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4877363e6be..ecf20be261f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -57,7 +57,6 @@ NEW: add option TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT NEW: add option to define a default warehouse at user level NEW: add option to include products without alert in replenish NEW: add order by lastname and firstname by default in get sales representatives -NEW: add param to not show links when output tags NEW: add PDF document templates for warehouses (list of stock) NEW: add a prospect status for the contact with managment of custom icon NEW: add public note on products ; this also partially fix the #14342 @@ -80,7 +79,7 @@ NEW: appearance tab in TakePOS with more visual parameters NEW: better currency rate editor NEW: can build vendor invoice from vendor orders NEW: can change a product in lines of a recurring invoice or contract -NEW: can change size of logo on PDF documents +NEW: can set the size of the logo on PDF documents NEW: can change VAT rate of all lines of a draft object in one step NEW: can define date range of validity of a login during creation NEW: can disable, from edit page, the whole web site @@ -189,7 +188,7 @@ NEW: show line number on intervention card (via MAIN_VIEW_LINE_NUMBER) NEW: Add some fields to link website page to an other object NEW: fill ECM src object fields in dol_add_file_process NEW: conf to allow to show the full tree in warehouse popup -NEW: can use THEME_DARKMODEENABLED=2 for a preview of theme in dark mode +NEW: can use parameter ?THEME_DARKMODEENABLED=2 for a preview of theme in dark mode NEW: can force the antivirus from conf file or autoprepend ini setup NEW: can add event to log into blockedlog module with a constant NEW: add property cssview when declaring fields of an object @@ -208,6 +207,7 @@ NEW: add a message in error_log after detection of SQL or script injection NEW: add validation of MX domain for emails NEW: calculate the virtual stock in transverse mode ( not on getEntity('commande'), ... but on getEntity('stock') ) NEW: Graphics can be horizontal bars +NEW: add param to not show links when output tags APIs NEW: API get contacts list of a given order diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 5fa4a3adfaa..885081e84a1 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -46,7 +46,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; // Load translation files required by the page -$langs->loadLangs(array("orders", 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks')); +$langs->loadLangs(array("orders", 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks', 'products')); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 734d21b1c87..02098e986ba 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -549,16 +549,17 @@ if (!empty($conf->multicompany->enabled) && is_object($mc)) print '
    '; $listofchoices = array( - 'selectinvoices'=>array('label'=>'Invoices', 'lang'=>'bills'), - 'selectsupplierinvoices'=>array('label'=>'BillsSuppliers', 'lang'=>'bills'), - 'selectexpensereports'=>array('label'=>'ExpenseReports', 'lang'=>'trips'), - 'selectdonations'=>array('label'=>'Donations', 'lang'=>'donation'), - 'selectpaymentsofsalaries'=>array('label'=>'SalariesPayments', 'lang'=>'salaries'), - 'selectsocialcontributions'=>array('label'=>'SocialContributions'), - 'selectvariouspayment'=>array('label'=>'VariousPayment'), - 'selectloanspayment'=>array('label'=>'PaymentLoan'), + 'selectinvoices'=>array('label'=>'Invoices', 'lang'=>'bills', 'enabled' => !empty($conf->facture->enabled)), + 'selectsupplierinvoices'=>array('label'=>'BillsSuppliers', 'lang'=>'bills', 'enabled' => !empty($conf->supplier_invoice->enabled)), + 'selectexpensereports'=>array('label'=>'ExpenseReports', 'lang'=>'trips', 'enabled' => !empty($conf->expensereport->enabled)), + 'selectdonations'=>array('label'=>'Donations', 'lang'=>'donation', 'enabled' => !empty($conf->don->enabled)), + 'selectsocialcontributions'=>array('label'=>'SocialContributions', 'enabled' => !empty($conf->tax->enabled)), + 'selectpaymentsofsalaries'=>array('label'=>'SalariesPayments', 'lang'=>'salaries', 'enabled' => !empty($conf->salaries->enabled)), + 'selectvariouspayment'=>array('label'=>'VariousPayment', 'enabled' => !empty($conf->banque->enabled)), + 'selectloanspayment'=>array('label'=>'PaymentLoan', 'enabled' => !empty($conf->loan->enabled)), ); foreach ($listofchoices as $choice => $val) { + if (empty($val['enabled'])) continue; // list not qualified $checked = (((!GETPOSTISSET('search') && $action != 'searchfiles') || GETPOST($choice)) ? ' checked="checked"' : ''); print '
    '; } diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 76b22e29a96..e0f48e9498b 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -493,9 +493,10 @@ class Account extends CommonObject * @param string $banque Bank of cheque writer * @param string $accountancycode When we record a free bank entry, we must provide accounting account if accountancy module is on. * @param int $datev Date value + * @param string $num_releve Label of bank receipt for reconciliation * @return int Rowid of added entry, <0 if KO */ - public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null) + public function addline($date, $oper, $label, $amount, $num_chq, $categorie, User $user, $emetteur = '', $banque = '', $accountancycode = '', $datev = null, $num_releve = '') { // Deprecation warning if (is_numeric($oper)) { @@ -555,6 +556,7 @@ class Account extends CommonObject $accline->fk_account = $this->rowid; $accline->fk_type = $oper; $accline->numero_compte = $accountancycode; + $accline->num_releve = $num_releve; if ($num_chq) { $accline->num_chq = $num_chq; @@ -1886,6 +1888,7 @@ class AccountLine extends CommonObject $sql .= ", emetteur,banque"; $sql .= ", rappro"; $sql .= ", numero_compte"; + $sql .= ", num_releve"; $sql .= ") VALUES ("; $sql .= "'".$this->db->idate($this->datec)."'"; $sql .= ", '".$this->db->idate($this->dateo)."'"; @@ -1900,6 +1903,7 @@ class AccountLine extends CommonObject $sql .= ", ".($this->bank_chq ? "'".$this->db->escape($this->bank_chq)."'" : "null"); $sql .= ", ".(int) $this->rappro; $sql .= ", ".($this->numero_compte ? "'".$this->db->escape($this->numero_compte)."'" : "''"); + $sql .= ", ".($this->num_releve ? "'".$this->db->escape($this->num_releve)."'" : "null"); $sql .= ")"; dol_syslog(get_class($this)."::insert", LOG_DEBUG); diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index 35104e5ed25..9ab02d8b18a 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -466,20 +466,23 @@ class BankAccounts extends DolibarrApi /** * Add a line to an account * - * @param int $id ID of account - * @param int $date Payment date (timestamp) {@from body} {@type timestamp} - * @param string $type Payment mode (TYP,VIR,PRE,LIQ,VAD,CB,CHQ...) {@from body} - * @param string $label Label {@from body} - * @param float $amount Amount (may be 0) {@from body} - * @param int $category Category - * @param string $cheque_number Cheque numberl {@from body} - * @param string $cheque_writer Name of cheque writer {@from body} - * @param string $cheque_bank Bank of cheque writer {@from body} + * @param int $id ID of account + * @param int $date Payment date (timestamp) {@from body} {@type timestamp} + * @param string $type Payment mode (TYP,VIR,PRE,LIQ,VAD,CB,CHQ...) {@from body} + * @param string $label Label {@from body} + * @param float $amount Amount (may be 0) {@from body} + * @param int $category Category + * @param string $cheque_number Cheque numero {@from body} + * @param string $cheque_writer Name of cheque writer {@from body} + * @param string $cheque_bank Bank of cheque writer {@from body} + * @param string $accountancycode Accountancy code {@from body} + * @param int $datev Payment date value (timestamp) {@from body} {@type timestamp} + * @param string $num_releve Bank statement numero {@from body} * @return int ID of line * * @url POST {id}/lines */ - public function addLine($id, $date, $type, $label, $amount, $category = 0, $cheque_number = '', $cheque_writer = '', $cheque_bank = '') + public function addLine($id, $date, $type, $label, $amount, $category = 0, $cheque_number = '', $cheque_writer = '', $cheque_bank = '', $accountancycode = '', $datev = null, $num_releve = '') { if (!DolibarrApiAccess::$user->rights->banque->modifier) { throw new RestException(401); @@ -499,7 +502,8 @@ class BankAccounts extends DolibarrApi $cheque_number, $category, DolibarrApiAccess::$user, - $cheque_writer, $cheque_bank + $cheque_writer, $cheque_bank, $accountancycode, + $datev, $num_releve ); if ($result < 0) { throw new RestException(503, 'Error when adding line to account: '.$account->error); diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index a03fd03ffef..83393a52cb6 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -710,10 +710,10 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie // Price print ''.price($sign * $objp->total_ttc).''; - // Received or paid back + // Received + already paid print ''.price($sign * $paiement); - if ($creditnotes) print '+'.price($creditnotes); - if ($deposits) print '+'.price($deposits); + if ($creditnotes) print '+'.price($creditnotes).''; + if ($deposits) print '+'.price($deposits).''; print ''; // Remain to take or to pay back diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 3906d376243..678ed9bbbd6 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -374,8 +374,7 @@ if (empty($reshook)) $action = 'create'; } } - } elseif ($action == 'classin' && $user->rights->contrat->creer) - { + } elseif ($action == 'classin' && $user->rights->contrat->creer) { $object->setProject(GETPOST('projectid')); } diff --git a/htdocs/core/boxes/box_fournisseurs.php b/htdocs/core/boxes/box_fournisseurs.php index 44e2682585e..7d1c72b3036 100644 --- a/htdocs/core/boxes/box_fournisseurs.php +++ b/htdocs/core/boxes/box_fournisseurs.php @@ -137,10 +137,13 @@ class box_fournisseurs extends ModeleBoxes $line++; } - if ($num == 0) $this->info_box_contents[$line][0] = array( - 'td' => 'class="center opacitymedium"', - 'text'=>$langs->trans("NoRecordedSuppliers"), - ); + if ($num == 0) { + $langs->load("suppliers"); + $this->info_box_contents[$line][0] = array( + 'td' => 'class="center opacitymedium"', + 'text'=>$langs->trans("NoRecordedSuppliers"), + ); + } $this->db->free($result); } else { diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index c942127aab3..e96adea7531 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2003 Jean-Louis Bergamo * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2019 Frédéric France + * Copyright (C) 2019-2020 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -950,15 +950,14 @@ class CMailFile * Read a file on disk and return encoded content for emails (mode = 'mail') * * @param string $sourcefile Path to file to encode - * @return int <0 if KO, encoded string if OK + * @return int|string <0 if KO, encoded string if OK */ private function _encode_file($sourcefile) { // phpcs:enable $newsourcefile = dol_osencode($sourcefile); - if (is_readable($newsourcefile)) - { + if (is_readable($newsourcefile)) { $contents = file_get_contents($newsourcefile); // Need PHP 4.3 $encoded = chunk_split(base64_encode($contents), 76, $this->eol); // 76 max is defined into http://tools.ietf.org/html/rfc2047 return $encoded; @@ -983,27 +982,24 @@ class CMailFile // phpcs:enable global $conf, $dolibarr_main_data_root; - if (@is_writeable($dolibarr_main_data_root)) // Avoid fatal error on fopen with open_basedir - { + if (@is_writeable($dolibarr_main_data_root)) { // Avoid fatal error on fopen with open_basedir $outputfile = $dolibarr_main_data_root."/dolibarr_mail.log"; $fp = fopen($outputfile, "w"); - if ($this->sendmode == 'mail') - { + if ($this->sendmode == 'mail') { fputs($fp, $this->headers); fputs($fp, $this->eol); // This eol is added by the mail function, so we add it in log fputs($fp, $this->message); - } elseif ($this->sendmode == 'smtps') - { + } elseif ($this->sendmode == 'smtps') { fputs($fp, $this->smtps->log); // this->smtps->log is filled only if MAIN_MAIL_DEBUG was set to on - } elseif ($this->sendmode == 'swiftmailer') - { + } elseif ($this->sendmode == 'swiftmailer') { fputs($fp, $this->logger->dump()); // this->logger is filled only if MAIN_MAIL_DEBUG was set to on } fclose($fp); - if (!empty($conf->global->MAIN_UMASK)) + if (!empty($conf->global->MAIN_UMASK)) { @chmod($outputfile, octdec($conf->global->MAIN_UMASK)); + } } } @@ -1016,8 +1012,7 @@ class CMailFile */ public function checkIfHTML($msg) { - if (!preg_match('/^[\s\t]*styleCSS)) $out .= $this->styleCSS; $out .= "css)) - { + if (!empty($this->css)) { // Style CSS $this->styleCSS = '