diff --git a/ChangeLog b/ChangeLog
index ede0e10a89f..32277ea29ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -27,8 +27,68 @@ Following changes may create regressions for some external modules, but were nec
* If your logo was visible on the menu bar, you must upload a new logo into 'Home-Setup-Company/Organization' to have it visible agin in menu.
-***** ChangeLog for 10.0.2 compared to 10.0.1 *****
+***** ChangeLog for 10.0.3 compared to 10.0.2 *****
+FIX: #11702
+FIX: #11861 No consistent code to manage measuring units
+FIX: #11942
+FIX: #12026
+FIX: #12040
+FIX: #12041
+FIX: #12054
+FIX: #12083
+FIX: #12088
+FIX: access to public interface when origin email has an alias.
+FIX: Alias name is not into the email recipient label.
+FIX: allow standalone credit note even if no invoice
+FIX: an admin can not access his own permissions after enabling advanced
+FIX: an admin can not access his own permissions after enabling advanced permissions
+FIX: Attachement of linked files on ticket when sending a message
+FIX: avoid non numeric warning
+FIX: Bad currency var used in stripe for connect
+FIX: Bad list of ticket on public interface for ticket emailcollector
+FIX: Can't modify vendor invoice if transfered into accountancy
+FIX: change product type must be allowed if we activate hidden conf
+FIX: colspan on VAT quadri report
+FIX: CSS
+FIX: Debug feature orderstoinvoice for suppliers
+FIX: do not output return code on screen after a select of bank account
+FIX: Edit of ticket module parameters erased others
+FIX: empty cache when we want to load specific warehouses in select
+FIX: escape email alias
+FIX: expedition.class.php
+FIX: Export of leave request show the number of open days
+FIX: Filtering the HTTP Header "Accept-Language".
+FIX: Filter on project on ticket list
+FIX: Filter "Open all" of ticket was ko.
+FIX: Force downlaod of file with .noexe as octet-stream mime type
+FIX: form not closed.
+FIX: hidden conf to prevent from changing product_type
+FIX: If product account not suggested during bind, it is not preselected
+FIX: If we share invoice, we need to see discount created from a deposit on each entity
+FIX: Import of product using units
+FIX: label of thirdparty is wrong on open project list
+FIX: Look and feel v10
+FIX: missing begin()
+FIX: missing "$this->id" in "fetch" function
+FIX: navigation on ticket tab of projects
+FIX: new invoice with generic thirdparty in takepos
+FIX: Pb in units of shipments
+FIX: regression with option to hide picto on top menu
+FIX: selection of project i am contact of.
+FIX: Send email from expense report card.
+FIX: shipping card: missing user error messages when classifying closed or billed
+FIX: SQL injection on qty
+FIX: stripe payment when there is a quote into address
+FIX: Substitution of __PROJECT_XXX__ not done
+FIX: TakePOS no invoice validation control and good payment translate
+FIX: the access of the bank account of one user
+FIX: top menu right padding
+FIX: Update of leave request when CSRF with token is on
+FIX: Var not enough sanitized
+FIX: wrong test
+FIX: XSS
+***** ChangeLog for 10.0.2 compared to 10.0.1 *****
FIX: #10460 compatibility with MariaDB 10.4
FIX: #11401 Adherent unknown language key
FIX: #11422 Can't edit his own events with standard rights
diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php
index b5f0c06738a..2958a229d24 100644
--- a/htdocs/accountancy/bookkeeping/list.php
+++ b/htdocs/accountancy/bookkeeping/list.php
@@ -518,9 +518,9 @@ else $buttonLabel = $langs->trans("ExportList");
// Button re-export
if (! empty($conf->global->ACCOUNTING_REEXPORT)) {
- $newcardbutton =''.img_picto($langs->trans("Activated"), 'switch_on').' ';
+ $newcardbutton =''.img_picto($langs->trans("Activated"), 'switch_on').' ';
} else {
- $newcardbutton =''.img_picto($langs->trans("Disabled"), 'switch_off').' ';
+ $newcardbutton =''.img_picto($langs->trans("Disabled"), 'switch_off').' ';
}
$newcardbutton.= ''.$langs->trans("IncludeDocsAlreadyExported").'';
diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php
index 4eab81ea49f..0eeccbd3395 100644
--- a/htdocs/accountancy/index.php
+++ b/htdocs/accountancy/index.php
@@ -88,7 +88,7 @@ if ($conf->accounting->enabled)
}
- print load_fiche_titre($langs->trans("AccountancyArea"), $showtutorial . $resultboxes['selectboxlist'], 'accountancy');
+ print load_fiche_titre($langs->trans("AccountancyArea"), $resultboxes['selectboxlist'], 'accountancy', 0, '', '', $showtutorial);
print '
';
@@ -488,7 +482,7 @@ while ($i < min($num, $limit))
$reshook=$hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
// Action column
- print '
';
+ 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;
diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php
index 73e26de8aea..d8e5387f075 100644
--- a/htdocs/bom/class/bom.class.php
+++ b/htdocs/bom/class/bom.class.php
@@ -513,7 +513,7 @@ class BOM extends CommonObject
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
* @return int <=0 if OK, 0=Nothing done, >0 if KO
*/
- public function valid($user, $notrigger = 0)
+ public function validate($user, $notrigger = 0)
{
global $conf, $langs;
@@ -524,7 +524,7 @@ class BOM extends CommonObject
// Protection
if ($this->statut == self::STATUS_VALIDATED)
{
- dol_syslog(get_class($this)."::valid action abandonned: already validated", LOG_WARNING);
+ dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING);
return 0;
}
@@ -553,14 +553,14 @@ class BOM extends CommonObject
$this->newref = $num;
// Validate
- $sql = "UPDATE ".MAIN_DB_PREFIX."bom_bom";
+ $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
$sql.= " SET ref = '".$this->db->escape($num)."',";
$sql.= " status = ".self::STATUS_VALIDATED.",";
$sql.= " date_valid='".$this->db->idate($now)."',";
$sql.= " fk_user_valid = ".$user->id;
$sql.= " WHERE rowid = ".$this->id;
- dol_syslog(get_class($this)."::valid()", LOG_DEBUG);
+ dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
$resql=$this->db->query($sql);
if (! $resql)
{
@@ -597,7 +597,7 @@ class BOM extends CommonObject
$dirdest = $conf->bom->dir_output.'/'.$newref;
if (! $error && file_exists($dirsource))
{
- dol_syslog(get_class($this)."::valid() rename dir ".$dirsource." into ".$dirdest);
+ dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
if (@rename($dirsource, $dirdest))
{
@@ -640,64 +640,78 @@ class BOM extends CommonObject
* 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)
+ public function setDraft($user, $notrigger = 0)
{
- global $conf, $langs;
+ // Protection
+ if ($this->status <= self::STATUS_DRAFT)
+ {
+ return 0;
+ }
- $error=0;
+ /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->write))
+ || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->bom_advance->validate))))
+ {
+ $this->error='Permission denied';
+ return -1;
+ }*/
- // Protection
- if ($this->status <= self::STATUS_DRAFT)
- {
- return 0;
- }
-
- /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->write))
- || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->bom_advance->validate))))
- {
- $this->error='Permission denied';
- return -1;
- }*/
-
- $this->db->begin();
-
- $sql = "UPDATE ".MAIN_DB_PREFIX."bom";
- $sql.= " SET status = ".self::STATUS_DRAFT;
- $sql.= " WHERE rowid = ".$this->id;
-
- dol_syslog(get_class($this)."::setDraft", LOG_DEBUG);
- if ($this->db->query($sql))
- {
- if (! $error)
- {
- $this->oldcopy= clone $this;
- }
-
- if (!$error) {
- // Call trigger
- $result=$this->call_trigger('BOM_UNVALIDATE', $user);
- if ($result < 0) $error++;
- }
-
- if (!$error) {
- $this->status=self::STATUS_DRAFT;
- $this->db->commit();
- return 1;
- } else {
- $this->db->rollback();
- return -1;
- }
- }
- else
- {
- $this->error=$this->db->error();
- $this->db->rollback();
- return -1;
- }
+ return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'BOM_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->bom->write))
+ || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->bom_advance->validate))))
+ {
+ $this->error='Permission denied';
+ return -1;
+ }*/
+
+ return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'BOM_CLOSE');
+ }
+
+ /**
+ * 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 reopen($user, $notrigger = 0)
+ {
+ // Protection
+ if ($this->status != self::STATUS_CANCELED)
+ {
+ return 0;
+ }
+
+ /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->write))
+ || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->bom->bom_advance->validate))))
+ {
+ $this->error='Permission denied';
+ return -1;
+ }*/
+
+ return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'BOM_REOPEN');
+ }
+
+
/**
* Return a link to the object card (with optionaly the picto)
*
@@ -1052,7 +1066,7 @@ class BOMLine extends CommonObject
'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>1, 'visible'=>-1, 'position'=>60, 'notnull'=>-1,),
'qty' => array('type'=>'double(24,8)', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>1, 'position'=>100, 'notnull'=>1, 'isameasure'=>'1',),
'efficiency' => array('type'=>'double(8,4)', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>1, 'default'=>1, 'position'=>110, 'notnull'=>1, 'css'=>'maxwidth50imp', 'help'=>'ValueOfMeansLoss'),
- 'position' => array('type'=>'integer', 'label'=>'Rank', 'enabled'=>1, 'visible'=>0, 'position'=>200, 'notnull'=>1,),
+ 'position' => array('type'=>'integer', 'label'=>'Rank', 'enabled'=>1, 'visible'=>0, 'default'=>0, 'position'=>200, 'notnull'=>1,),
'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,),
);
public $rowid;
diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php
index efb11a7e22b..a7fe41a478c 100644
--- a/htdocs/comm/action/list.php
+++ b/htdocs/comm/action/list.php
@@ -21,7 +21,7 @@
*/
/**
- * \file htdocs/comm/action/list.php
+ * \file htdocs/comm/action/list.php
* \ingroup agenda
* \brief Page to list actions
*/
@@ -239,7 +239,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
$sql = "SELECT";
if ($usergroup > 0) $sql.=" DISTINCT";
$sql.= " s.nom as societe, s.rowid as socid, s.client, s.email as socemail,";
-$sql.= " a.id, a.label, a.note, a.datep as dp, a.datep2 as dp2,";
+$sql.= " a.id, a.label, a.note, a.datep as dp, a.datep2 as dp2, a.fulldayevent, a.location,";
$sql.= ' a.fk_user_author,a.fk_user_action,';
$sql.= " a.fk_contact, a.note, a.percent as percent,";
$sql.= " a.fk_element, a.elementtype, a.datec, a.tms as datem,";
@@ -247,7 +247,9 @@ $sql.= " c.code as type_code, c.libelle as type_label,";
$sql.= " sp.lastname, sp.firstname, sp.email, sp.phone, sp.address, sp.phone as phone_pro, sp.phone_mobile, sp.phone_perso, sp.fk_pays as country_id";
// Add fields from extrafields
-foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+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();
@@ -286,14 +288,14 @@ if (! empty($actioncode))
elseif ($actioncode == 'AC_ALL_AUTO') $sql.= " AND c.type = 'systemauto'";
else
{
- if (is_array($actioncode))
- {
- $sql.=" AND c.code IN ('".implode("','", $actioncode)."')";
- }
- else
- {
- $sql.=" AND c.code IN ('".implode("','", explode(',', $actioncode))."')";
- }
+ if (is_array($actioncode))
+ {
+ $sql.=" AND c.code IN ('".implode("','", $actioncode)."')";
+ }
+ else
+ {
+ $sql.=" AND c.code IN ('".implode("','", explode(',', $actioncode))."')";
+ }
}
}
}
@@ -460,7 +462,7 @@ if ($resql)
print $form->selectDate($datestart, 'datestart', 0, 0, 1, '', 1, 0);
print '
';
}
- if (! empty($arrayfields['a.datep2']['checked'])) {
+ if (! empty($arrayfields['a.datep2']['checked'])) {
print '
';
+ print '' . $langs->trans("ToClone") . ''."\n";
}
/*
diff --git a/htdocs/mrp/ChangeLog.md b/htdocs/mrp/ChangeLog.md
new file mode 100644
index 00000000000..416bad1d559
--- /dev/null
+++ b/htdocs/mrp/ChangeLog.md
@@ -0,0 +1,5 @@
+# CHANGELOG MRP FOR DOLIBARR ERP CRM
+
+## 1.0
+Initial version
+
diff --git a/htdocs/mrp/README.md b/htdocs/mrp/README.md
new file mode 100644
index 00000000000..b23e31fb577
--- /dev/null
+++ b/htdocs/mrp/README.md
@@ -0,0 +1,3 @@
+# MRP Module
+
+Module to manage Manufacturing Orders (MO)
\ No newline at end of file
diff --git a/htdocs/mrp/admin/setup.php b/htdocs/mrp/admin/setup.php
new file mode 100644
index 00000000000..8d7df29b383
--- /dev/null
+++ b/htdocs/mrp/admin/setup.php
@@ -0,0 +1,151 @@
+
+ * Copyright (C) 2019 Alicealalalamdskfldmjgdfgdfhfghgfh Adminson
+ *
+ * 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 mrp/admin/setup.php
+ * \ingroup mrp
+ * \brief Mrp setup page.
+ */
+
+// 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) die("Include of main fails");
+
+global $langs, $user;
+
+// Libraries
+require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php";
+require_once '../lib/mrp.lib.php';
+//require_once "../class/myclass.class.php";
+
+// Translations
+$langs->loadLangs(array("admin", "mrp"));
+
+// Access control
+if (! $user->admin) accessforbidden();
+
+// Parameters
+$action = GETPOST('action', 'alpha');
+$backtopage = GETPOST('backtopage', 'alpha');
+
+$arrayofparameters=array(
+ 'MRP_MYPARAM1'=>array('css'=>'minwidth200','enabled'=>1),
+ 'MRP_MYPARAM2'=>array('css'=>'minwidth500','enabled'=>1)
+);
+
+
+
+/*
+ * Actions
+ */
+
+if ((float) DOL_VERSION >= 6)
+{
+ include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+}
+
+
+
+/*
+ * View
+ */
+
+$page_name = "MrpSetup";
+llxHeader('', $langs->trans($page_name));
+
+// Subheader
+$linkback = ''.$langs->trans("BackToModuleList").'';
+
+print load_fiche_titre($langs->trans($page_name), $linkback, 'object_mrp');
+
+// Configuration header
+$head = mrpAdminPrepareHead();
+dol_fiche_head($head, 'settings', '', -1, "mrp");
+
+// Setup page goes here
+echo ''.$langs->trans("MrpSetupPage").'
';
+
+ 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("ActionsOnMo"), '', '');
+
+ // 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);
+ }
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php
new file mode 100644
index 00000000000..f15b45b96e5
--- /dev/null
+++ b/htdocs/mrp/mo_card.php
@@ -0,0 +1,550 @@
+
+ * 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 mo_card.php
+ * \ingroup mrp
+ * \brief Page to create/edit/view mo
+ */
+
+//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
+
+
+// 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/class/html.formfile.class.php';
+dol_include_once('/mrp/class/mo.class.php');
+dol_include_once('/mrp/lib/mrp_mo.lib.php');
+
+// Load translation files required by the page
+$langs->loadLangs(array("mrp", "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'):'mocard'; // To manage different context of search
+$backtopage = GETPOST('backtopage', 'alpha');
+//$lineid = GETPOST('lineid', 'int');
+
+// Initialize technical objects
+$object=new Mo($db);
+$extrafields = new ExtraFields($db);
+$diroutputmassaction=$conf->mrp->dir_output . '/temp/massgeneration/'.$user->id;
+$hookmanager->initHooks(array('mocard','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=trim(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.
+
+// Security check - Protection if external user
+//if ($user->societe_id > 0) access_forbidden();
+//if ($user->societe_id > 0) $socid = $user->societe_id;
+//$isdraft = (($object->statut == Mo::STATUS_DRAFT) ? 1 : 0);
+//$result = restrictedArea($user, 'mrp', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
+
+$permissionnote=$user->rights->mrp->write; // Used by the include of actions_setnotes.inc.php
+$permissiondellink=$user->rights->mrp->write; // Used by the include of actions_dellink.inc.php
+$permissionedit=$user->rights->mrp->write; // Used by the include of actions_lineupdown.inc.php
+$permissiontoadd=$user->rights->mrp->write; // Used by the include of actions_addupdatedelete.inc.php
+
+
+
+/*
+ * Actions
+ *
+ * Put here all code to do according to value of "action" parameter
+ */
+
+$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;
+
+ $permissiontodelete = $user->rights->mrp->delete || ($permissiontoadd && $object->status == 0);
+ $backurlforlist = dol_buildpath('/mrp/mo_list.php', 1);
+ if (empty($backtopage)) {
+ if (empty($id)) $backtopage = $backurlforlist;
+ else $backtopage = dol_buildpath('/mrp/mo_card.php', 1).'?id='.($id > 0 ? $id : '__ID__');
+ }
+ $triggermodname = 'MRP_MO_MODIFY'; // Name of trigger action code to execute when we modify record
+
+ // Actions cancel, add, update, delete or clone
+ 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';
+
+ // Actions to send emails
+ $trigger_name='MO_SENTBYMAIL';
+ $autocopy='MAIN_MAIL_AUTOCOPY_MO_TO';
+ $trackid='mo'.$object->id;
+ include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
+}
+
+
+
+
+/*
+ * View
+ *
+ * Put here all code to build page
+ */
+
+$form=new Form($db);
+$formfile=new FormFile($db);
+
+llxHeader('', $langs->trans('Mo'), '');
+
+// Example : Adding jquery code
+print '';
+
+
+// Part to create
+if ($action == 'create')
+{
+ print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Mo")), '', 'cubes');
+
+ print '';
+}
+
+// Part to edit record
+if (($id || $ref) && $action == 'edit')
+{
+ print load_fiche_titre($langs->trans("Mo"), '', 'cubes');
+
+ print '';
+}
+
+// Part to show record
+if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create')))
+{
+ $res = $object->fetch_optionals();
+
+ $head = moPrepareHead($object);
+ dol_fiche_head($head, 'card', $langs->trans("Mo"), -1, $object->picto);
+
+ $formconfirm = '';
+
+ // Confirmation to delete
+ if ($action == 'delete')
+ {
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteMo'), $langs->trans('ConfirmDeleteMo'), 'confirm_delete', '', 0, 1);
+ }
+ // Confirmation to delete line
+ if ($action == 'deleteline')
+ {
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 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('ConfirmCloneMo', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
+ }
+
+ // Confirmation of action xxxx
+ if ($action == 'xxx')
+ {
+ $formquestion=array();
+ /*
+ $forcecombo=0;
+ if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
+ $formquestion = array(
+ // 'text' => $langs->trans("ConfirmClone"),
+ // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
+ // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
+ // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
+ );
+ */
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220);
+ }
+
+ // Call Hook formConfirm
+ $parameters = array('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='
'."\n";
+ }
+
+
+ // Select mail models is same action as presend
+ if (GETPOST('modelselected')) {
+ $action = 'presend';
+ }
+
+ if ($action != 'presend')
+ {
+ print '
';
+ print ''; // ancre
+
+ // Documents
+ /*$objref = dol_sanitizeFileName($object->ref);
+ $relativepath = $comref . '/' . $comref . '.pdf';
+ $filedir = $conf->mrp->dir_output . '/' . $objref;
+ $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id;
+ $genallowed = $user->rights->mrp->read; // If you can read, you can build the PDF to read content
+ $delallowed = $user->rights->mrp->create; // If you can create/edit, you can remove a file on card
+ print $formfile->showdocuments('mrp', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
+ */
+
+ // Show links to link elements
+ $linktoelem = $form->showLinkToObjectBlock($object, null, array('mo'));
+ $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
+
+
+ print '
';
+
+ $MAXEVENT = 10;
+
+ $morehtmlright = '';
+ $morehtmlright.= $langs->trans("SeeAll");
+ $morehtmlright.= '';
+
+ // List of actions on element
+ include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
+ $formactions = new FormActions($db);
+ $somethingshown = $formactions->showactions($object, 'mo', $socid, 1, '', $MAXEVENT, '', $morehtmlright);
+
+ print '
';
+ }
+
+ //Select mail models is same action as presend
+ /*
+ if (GETPOST('modelselected')) $action = 'presend';
+
+ // Presend form
+ $modelmail='inventory';
+ $defaulttopic='InformationMessage';
+ $diroutput = $conf->product->dir_output.'/inventory';
+ $trackid = 'stockinv'.$object->id;
+
+ include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
+ */
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/mrp/mo_document.php b/htdocs/mrp/mo_document.php
new file mode 100644
index 00000000000..09f34ae583e
--- /dev/null
+++ b/htdocs/mrp/mo_document.php
@@ -0,0 +1,167 @@
+
+ * 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 mo_document.php
+ * \ingroup mrp
+ * \brief Tab for documents linked to Mo
+ */
+
+// 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('/mrp/class/mo.class.php');
+dol_include_once('/mrp/lib/mrp_mo.lib.php');
+
+// Load translation files required by the page
+$langs->loadLangs(array("mrp","companies","other","mails"));
+
+
+$action=GETPOST('action', 'aZ09');
+$confirm=GETPOST('confirm');
+$id=(GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int'));
+$ref = GETPOST('ref', 'alpha');
+
+// Security check - Protection if external user
+//if ($user->societe_id > 0) access_forbidden();
+//if ($user->societe_id > 0) $socid = $user->societe_id;
+//$result = restrictedArea($user, 'mrp', $id);
+
+// Get parameters
+$sortfield = GETPOST("sortfield", 'alpha');
+$sortorder = GETPOST("sortorder", 'alpha');
+$page = GETPOST("page", 'int');
+if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
+$offset = $conf->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 Mo($db);
+$extrafields = new ExtraFields($db);
+$diroutputmassaction=$conf->mrp->dir_output . '/temp/massgeneration/'.$user->id;
+$hookmanager->initHooks(array('modocument','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->mrp->multidir_output[$object->entity?$object->entity:$conf->entity] . "/mo/" . dol_sanitizeFileName($object->id);
+if ($id > 0 || ! empty($ref)) $upload_dir = $conf->mrp->multidir_output[$object->entity?$object->entity:$conf->entity] . "/mo/" . dol_sanitizeFileName($object->ref);
+
+
+/*
+ * Actions
+ */
+
+include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php';
+
+
+/*
+ * View
+ */
+
+$form = new Form($db);
+
+$title=$langs->trans("Mo").' - '.$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 = moPrepareHead($object);
+
+ dol_fiche_head($head, 'document', $langs->trans("Mo"), -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") . '';
+
+ dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
+
+ print '
';
+
+ print '';
+ print '
';
+
+ // Number of files
+ print '
'.$langs->trans("NbOfAttachedFiles").'
'.count($filearray).'
';
+
+ // Total size
+ print '
'.$langs->trans("TotalSizeOfAttachedFiles").'
'.$totalsize.' '.$langs->trans("bytes").'
';
+
+ print '
';
+
+ print '
';
+
+ dol_fiche_end();
+
+ $modulepart = 'mrp';
+ //$permission = $user->rights->mrp->create;
+ $permission = 1;
+ //$permtoedit = $user->rights->mrp->create;
+ $permtoedit = 1;
+ $param = '&id=' . $object->id;
+
+ //$relativepathwithnofile='mo/' . dol_sanitizeFileName($object->id).'/';
+ $relativepathwithnofile='mo/' . 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/mrp/mo_list.php b/htdocs/mrp/mo_list.php
new file mode 100644
index 00000000000..2f32058a41f
--- /dev/null
+++ b/htdocs/mrp/mo_list.php
@@ -0,0 +1,589 @@
+
+ * 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 mo_list.php
+ * \ingroup mrp
+ * \brief List page for mo
+ */
+
+//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('NOIPCHECK')) define('NOIPCHECK','1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
+//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)
+//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("XFRAMEOPTIONS_ALLOWALL")) define('XFRAMEOPTIONS_ALLOWALL',1); // Do not add the HTTP header 'X-Frame-Options: SAMEORIGIN' but 'X-Frame-Options: ALLOWALL'
+
+// Load Dolibarr environment
+require '../main.inc.php';
+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 mrp libraries
+require_once __DIR__ . '/class/mo.class.php';
+
+// for other modules
+//dol_include_once('/othermodule/class/otherobject.class.php');
+
+// Load translation files required by the page
+$langs->loadLangs(array("mrp","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'):'molist'; // 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', 'alpha');
+$sortorder = GETPOST('sortorder', 'alpha');
+$page = GETPOST('page', 'int');
+if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
+$offset = $limit * $page;
+$pageprev = $page - 1;
+$pagenext = $page + 1;
+//if (! $sortfield) $sortfield="p.date_fin";
+//if (! $sortorder) $sortorder="DESC";
+
+// Initialize technical objects
+$object = new Mo($db);
+$extrafields = new ExtraFields($db);
+$diroutputmassaction = $conf->mrp->dir_output . '/temp/massgeneration/'.$user->id;
+$hookmanager->initHooks(array('molist')); // 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_');
+
+// 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";
+
+// Security check
+if (empty($conf->mrp->enabled)) accessforbidden('Module not enabled');
+$socid=0;
+if ($user->societe_id > 0) // Protection if external user
+{
+ //$socid = $user->societe_id;
+ accessforbidden();
+}
+//$result = restrictedArea($user, 'mrp', $id, '');
+
+
+// Initialize array of search criterias
+$search_all=trim(GETPOST("search_all", 'alpha'));
+$search=array();
+foreach($object->fields as $key => $val)
+{
+ if (GETPOST('search_'.$key, 'alpha')) $search[$key]=GETPOST('search_'.$key, 'alpha');
+}
+
+// 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 fields for list
+$arrayfields=array();
+foreach($object->fields as $key => $val)
+{
+ // If $val['visible']==0, then we never show the field
+ if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']);
+}
+// Extra fields
+if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0)
+{
+ foreach($extrafields->attributes[$object->table_element]['label'] as $key => $val)
+ {
+ if (! empty($extrafields->attributes[$object->table_element]['list'][$key]))
+ $arrayfields["ef.".$key]=array('label'=>$extrafields->attributes[$object->table_element]['label'][$key], 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key]<0)?0:1), 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key])!=3 && $extrafields->attributes[$object->table_element]['perms'][$key]));
+ }
+}
+$object->fields = dol_sort_array($object->fields, 'position');
+$arrayfields = dol_sort_array($arrayfields, 'position');
+
+
+
+/*
+ * 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='Mo';
+ $objectlabel='Mo';
+ $permtoread = $user->rights->mrp->read;
+ $permtodelete = $user->rights->mrp->delete;
+ $uploaddir = $conf->mrp->dir_output;
+ include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+}
+
+
+
+/*
+ * View
+ */
+
+$form=new Form($db);
+
+$now=dol_now();
+
+//$help_url="EN:Module_Mo|FR:Module_Mo_FR|ES:Módulo_Mo";
+$help_url='';
+$title = $langs->trans('ListOfManufacturingOrders');
+
+
+// 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.=$hookmanager->resPrint;
+$sql=preg_replace('/, $/', '', $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)";
+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 ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:$mode_search));
+}
+if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all);
+// 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); // Note that $action and $object may have been modified by hook
+$sql.=$hookmanager->resPrint;
+$sql=preg_replace('/, $/','', $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)
+{
+ $num = $nbtotalofrecords;
+}
+else
+{
+ $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)
+{
+ $obj = $db->fetch_object($resql);
+ $id = $obj->rowid;
+ header("Location: ".dol_buildpath('/mrp/mo_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';
+
+// 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 ($user->rights->mrp->delete) $arrayofmassactions['predelete']=''.$langs->trans("Delete");
+if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
+$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
+
+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=$user->rights->mrp->read;
+ $delallowed=$user->rights->mrp->write;
+
+ print $formfile->showdocuments('massfilesarea_mrp', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/mrp/mo_note.php b/htdocs/mrp/mo_note.php
new file mode 100644
index 00000000000..a006f79a609
--- /dev/null
+++ b/htdocs/mrp/mo_note.php
@@ -0,0 +1,165 @@
+
+ * 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 mo_note.php
+ * \ingroup mrp
+ * \brief Car with notes on Mo
+ */
+
+// 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('/mrp/class/mo.class.php');
+dol_include_once('/mrp/lib/mrp_mo.lib.php');
+
+// Load translation files required by the page
+$langs->loadLangs(array("mrp","companies"));
+
+// Get parameters
+$id = GETPOST('id', 'int');
+$ref = GETPOST('ref', 'alpha');
+$action = GETPOST('action', 'alpha');
+$cancel = GETPOST('cancel', 'aZ09');
+$backtopage = GETPOST('backtopage', 'alpha');
+
+// Initialize technical objects
+$object=new Mo($db);
+$extrafields = new ExtraFields($db);
+$diroutputmassaction=$conf->mrp->dir_output . '/temp/massgeneration/'.$user->id;
+$hookmanager->initHooks(array('monote','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->societe_id > 0) access_forbidden();
+//if ($user->societe_id > 0) $socid = $user->societe_id;
+//$result = restrictedArea($user, 'mrp', $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->mrp->multidir_output[$object->entity] . "/" . $object->id;
+
+$permissionnote=1;
+//$permissionnote=$user->rights->mrp->creer; // Used by the include of actions_setnotes.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('Mo'), $help_url);
+
+if ($id > 0 || ! empty($ref))
+{
+ $object->fetch_thirdparty();
+
+ $head = moPrepareHead($object);
+
+ dol_fiche_head($head, 'note', $langs->trans("Mo"), -1, $object->picto);
+
+ // Object card
+ // ------------------------------------------------------------
+ $linkback = '' . $langs->trans("BackToList") . '';
+
+ $morehtmlref='
';
+
+ dol_fiche_end();
+}
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/mrp/modulebuilder.txt b/htdocs/mrp/modulebuilder.txt
new file mode 100644
index 00000000000..24ea0d6eac5
--- /dev/null
+++ b/htdocs/mrp/modulebuilder.txt
@@ -0,0 +1,3 @@
+# DO NOT DELETE THIS FILE MANUALLY
+# File to flag module built using official module template.
+# When this file is present into a module directory, you can edit it with the module builder tool. Use ModuleBuilder if you want to delete module.
\ No newline at end of file
diff --git a/htdocs/mrp/sql/llx_mrp_mo.key.sql b/htdocs/mrp/sql/llx_mrp_mo.key.sql
new file mode 100644
index 00000000000..071a663dd56
--- /dev/null
+++ b/htdocs/mrp/sql/llx_mrp_mo.key.sql
@@ -0,0 +1,35 @@
+-- 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 http://www.gnu.org/licenses/.
+
+
+-- BEGIN MODULEBUILDER INDEXES
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_rowid (rowid);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_ref (ref);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_entity (entity);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_qty (qty);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_soc (fk_soc);
+ALTER TABLE llx_mrp_mo ADD CONSTRAINT llx_mrp_mo_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES user(rowid);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_status (status);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_product (fk_product);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_date_start_planned (date_start_planned);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_date_end_planned (date_end_planned);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_bom (fk_bom);
+ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_project (fk_project);
+-- END MODULEBUILDER INDEXES
+
+--ALTER TABLE llx_mrp_mo ADD UNIQUE INDEX uk_mrp_mo_fieldxy(fieldx, fieldy);
+
+--ALTER TABLE llx_mrp_mo ADD CONSTRAINT llx_mrp_mo_fk_field FOREIGN KEY (fk_field) REFERENCES llx_mrp_myotherobject(rowid);
+
diff --git a/htdocs/mrp/sql/llx_mrp_mo.sql b/htdocs/mrp/sql/llx_mrp_mo.sql
new file mode 100644
index 00000000000..dbb8b0faa01
--- /dev/null
+++ b/htdocs/mrp/sql/llx_mrp_mo.sql
@@ -0,0 +1,39 @@
+-- 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 http://www.gnu.org/licenses/.
+
+
+CREATE TABLE llx_mrp_mo(
+ -- BEGIN MODULEBUILDER FIELDS
+ rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL,
+ ref varchar(128) DEFAULT '(PROV)' NOT NULL,
+ entity integer DEFAULT 1 NOT NULL,
+ label varchar(255),
+ qty real NOT NULL,
+ fk_soc integer,
+ note_public text,
+ 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 integer NOT NULL,
+ fk_product integer NOT NULL,
+ date_start_planned datetime,
+ date_end_planned datetime,
+ fk_bom integer,
+ fk_project integer
+ -- END MODULEBUILDER FIELDS
+) ENGINE=innodb;
\ No newline at end of file
diff --git a/htdocs/mrp/sql/llx_mrp_mo_extrafields.key.sql b/htdocs/mrp/sql/llx_mrp_mo_extrafields.key.sql
new file mode 100644
index 00000000000..5b280acc41f
--- /dev/null
+++ b/htdocs/mrp/sql/llx_mrp_mo_extrafields.key.sql
@@ -0,0 +1,19 @@
+-- Copyright (C) 2019 Alicealalalamdskfldmjgdfgdfhfghgfh Adminson
+--
+-- 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 http://www.gnu.org/licenses/.
+
+
+-- BEGIN MODULEBUILDER INDEXES
+ALTER TABLE llx_mrp_myobject_extrafields ADD INDEX idx_fk_object(fk_object);
+-- END MODULEBUILDER INDEXES
diff --git a/htdocs/mrp/sql/llx_mrp_mo_extrafields.sql b/htdocs/mrp/sql/llx_mrp_mo_extrafields.sql
new file mode 100644
index 00000000000..9245ac1c341
--- /dev/null
+++ b/htdocs/mrp/sql/llx_mrp_mo_extrafields.sql
@@ -0,0 +1,23 @@
+-- Copyright (C) 2019 Alicealalalamdskfldmjgdfgdfhfghgfh Adminson
+--
+-- 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 http://www.gnu.org/licenses/.
+
+create table llx_mrp_myobject_extrafields
+(
+ rowid integer AUTO_INCREMENT PRIMARY KEY,
+ tms timestamp,
+ fk_object integer NOT NULL,
+ import_key varchar(14) -- import key
+) ENGINE=innodb;
+
diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php
index b81e989cbb9..59c81c83e29 100644
--- a/htdocs/product/inventory/list.php
+++ b/htdocs/product/inventory/list.php
@@ -21,6 +21,7 @@
* \brief List page for inventory
*/
+// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
@@ -30,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php';
// Load translation files required by the page
$langs->loadLangs(array("stocks","other"));
-$action = GETPOST('action', 'alpha')?GETPOST('action', 'alpha'):'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
+$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
@@ -47,7 +48,7 @@ $limit = GETPOST('limit', 'int')?GETPOST('limit', 'int'):$conf->liste_limit;
$sortfield = GETPOST('sortfield', 'alpha');
$sortorder = GETPOST('sortorder', 'alpha');
$page = GETPOST('page', 'int');
-if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
+if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
$offset = $limit * $page;
$pageprev = $page - 1;
$pagenext = $page + 1;
@@ -67,7 +68,7 @@ if (! $sortorder) $sortorder="ASC";
// Security check
$socid=0;
-if ($user->societe_id > 0)
+if ($user->societe_id > 0) // Protection if external user
{
//$socid = $user->societe_id;
accessforbidden();
@@ -101,10 +102,10 @@ $arrayfields=array();
foreach($object->fields as $key => $val)
{
// If $val['visible']==0, then we never show the field
- if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled'], 'position'=>$val['position']);
+ if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']);
}
// Extra fields
-if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']))
+if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0)
{
foreach($extrafields->attributes[$object->table_element]['label'] as $key => $val)
{
@@ -119,8 +120,6 @@ $arrayfields = dol_sort_array($arrayfields, 'position');
/*
* Actions
- *
- * Put here all code to do according to value of "$action" parameter
*/
if (GETPOST('cancel', 'alpha')) { $action='list'; $massaction=''; }
@@ -164,8 +163,6 @@ if (empty($reshook))
/*
* View
- *
- * Put here all code to render page
*/
$form=new Form($db);
@@ -192,10 +189,10 @@ if (! empty($extrafields->attributes[$object->table_element]['label'])) {
$parameters=array();
$reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
$sql.=$hookmanager->resPrint;
-$sql=preg_replace('/, $/', '', $sql);
+$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."myobject_extrafields as ef on (t.rowid = ef.fk_object)";
-if ($object->ismultientitymanaged == 1) $sql.= " WHERE t.entity IN (".getEntity('myobject').")";
+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)";
+if ($object->ismultientitymanaged == 1) $sql.= " WHERE t.entity IN (".getEntity($object->element).")";
else $sql.=" WHERE 1 = 1";
foreach($search as $key => $val)
{
@@ -218,11 +215,14 @@ foreach($object->fields as $key => $val)
$sql.='t.'.$key.', ';
}
// Add fields from extrafields
-foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
+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); // Note that $action and $object may have been modified by hook
$sql.=$hookmanager->resPrint;
+$sql=preg_replace('/, $/','', $sql);
*/
$sql.=$db->order($sortfield, $sortorder);
@@ -231,18 +231,17 @@ $sql.=$db->order($sortfield, $sortorder);
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
- $result = $db->query($sql);
- $nbtotalofrecords = $db->num_rows($result);
- if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0
+ $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 resultset is smaller the limit, no need to do paging.
+// 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)
{
- $resql = $result;
$num = $nbtotalofrecords;
}
else
@@ -274,21 +273,6 @@ if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) &&
llxHeader('', $title, $help_url);
-// Example : Adding jquery code
-print '';
-
$arrayofselected=is_array($toselect)?$toselect:array();
$param='';
@@ -296,7 +280,8 @@ if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&con
if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit);
foreach($search as $key => $val)
{
- $param.= '&search_'.$key.'='.urlencode($search[$key]);
+ 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
@@ -308,7 +293,7 @@ $arrayofmassactions = array(
//'builddoc'=>$langs->trans("PDFMerge"),
);
if ($user->rights->stock->supprimer) $arrayofmassactions['predelete']=''.$langs->trans("Delete");
-if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
+if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
print '
'."\n";
// Detect if we need a fetch on each output line
$needToFetchEachLine=0;
-if (! empty($extrafields->attributes[$object->table_element]['computed'])) {
+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
@@ -448,16 +437,21 @@ while ($i < min($num, $limit))
print '
';
foreach($object->fields as $key => $val)
{
- $align='';
- if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center';
- if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap';
- if ($key == 'status') $align.=($align?' ':'').'center';
+ $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')) && $key != 'status') $cssforfield.=($cssforfield?' ':'').'right';
+
if (! empty($arrayfields['t.'.$key]['checked']))
{
- print '
';
if (! $i) $totalarray['nbfield']++;
if (! empty($val['isameasure']))
@@ -474,7 +468,7 @@ while ($i < min($num, $limit))
$reshook=$hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint;
// Action column
- print '
';
+ 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;
@@ -484,7 +478,7 @@ while ($i < min($num, $limit))
print '
';
if (! $i) $totalarray['nbfield']++;
- print '
';
+ print '
'."\n";
$i++;
}
diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php
index 824934992bf..004ad49ce46 100644
--- a/htdocs/product/stock/class/entrepot.class.php
+++ b/htdocs/product/stock/class/entrepot.class.php
@@ -95,6 +95,30 @@ class Entrepot extends CommonObject
// List of short language codes for status
public $statuts = array();
+ /**
+ * @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'=>'ID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>10),
+ 'ref' =>array('type'=>'varchar(255)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-2, 'showoncombobox'=>1, 'position'=>25),
+ 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'position'=>30),
+ 'description' =>array('type'=>'text', 'label'=>'Description', 'enabled'=>1, 'visible'=>-2, 'position'=>35),
+ 'lieu' =>array('type'=>'varchar(64)', 'label'=>'LocationSummary', 'enabled'=>1, 'visible'=>-2, 'position'=>40),
+ 'fk_parent' =>array('type'=>'integer', 'label'=>'ParentWarehouse', 'enabled'=>1, 'visible'=>-2, 'position'=>41),
+ 'address' =>array('type'=>'varchar(255)', 'label'=>'Address', 'enabled'=>1, 'visible'=>-2, 'position'=>45),
+ 'zip' =>array('type'=>'varchar(10)', 'label'=>'Zip', 'enabled'=>1, 'visible'=>-2, 'position'=>50),
+ 'town' =>array('type'=>'varchar(50)', 'label'=>'Town', 'enabled'=>1, 'visible'=>-2, 'position'=>55),
+ 'fk_departement' =>array('type'=>'integer', 'label'=>'State', 'enabled'=>1, 'visible'=>0, 'position'=>60),
+ 'fk_pays' =>array('type'=>'integer', 'label'=>'Country', 'enabled'=>1, 'visible'=>-2, 'position'=>65),
+ //'fk_user_author' =>array('type'=>'integer', 'label'=>'Fk user author', 'enabled'=>1, 'visible'=>-2, 'position'=>82),
+ //'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'ModelPDF', 'enabled'=>1, 'visible'=>-2, 'position'=>84),
+ //'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportKey', 'enabled'=>1, 'visible'=>-2, 'position'=>85),
+ 'statut' =>array('type'=>'tinyint(4)', 'label'=>'Status', 'enabled'=>1, 'visible'=>-2, 'position'=>200),
+ 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>500),
+ 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501),
+ );
+
+
/**
* Constructor
*
diff --git a/htdocs/product/stock/class/productlot.class.php b/htdocs/product/stock/class/productlot.class.php
index f08b290f0b9..3848a592f21 100644
--- a/htdocs/product/stock/class/productlot.class.php
+++ b/htdocs/product/stock/class/productlot.class.php
@@ -53,6 +53,19 @@ class Productlot extends CommonObject
*/
public $ismultientitymanaged = 1;
+ /**
+ * @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, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'),
+ 'batch' =>array('type'=>'varchar(30)', 'label'=>'Batch', 'enabled'=>1, 'visible'=>1, 'notnull'=>0, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'comment'=>'Batch'),
+ 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20),
+ 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500),
+ 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501),
+ 'fk_user_author'=>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510, 'foreignkey'=>'llx_user.rowid'),
+ 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>511)
+ );
+
/**
* @var int Entity
*/
diff --git a/htdocs/product/stock/list.php b/htdocs/product/stock/list.php
index ae39ba63f3b..b38888be9bb 100644
--- a/htdocs/product/stock/list.php
+++ b/htdocs/product/stock/list.php
@@ -28,34 +28,50 @@ require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
// Load translation files required by the page
-$langs->load("stocks");
+$langs->loadLangs(array("stocks","other"));
-// Security check
-$result=restrictedArea($user, 'stock');
+$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'):'stocklist'; // 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')
-$sall=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml'));
+$search_all=trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml'));
$search_ref=GETPOST("sref", "alpha")?GETPOST("sref", "alpha"):GETPOST("search_ref", "alpha");
$search_label=GETPOST("snom", "alpha")?GETPOST("snom", "alpha"):GETPOST("search_label", "alpha");
$search_status=GETPOST("search_status", "int");
+// Load variable for pagination
$limit = GETPOST('limit', 'int')?GETPOST('limit', 'int'):$conf->liste_limit;
-$sortfield = GETPOST("sortfield");
-$sortorder = GETPOST("sortorder");
+$sortfield = GETPOST('sortfield', 'alpha');
+$sortorder = GETPOST('sortorder', 'alpha');
+$page = GETPOST('page', 'int');
+if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
+$offset = $limit * $page;
+$pageprev = $page - 1;
+$pagenext = $page + 1;
if (! $sortfield) $sortfield="e.ref";
if (! $sortorder) $sortorder="ASC";
-$page = GETPOST("page");
-if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
-$offset = $limit * $page;
+
+// Security check
+$result=restrictedArea($user, 'stock');
+
$year = strftime("%Y", time());
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$object = new Entrepot($db);
-$hookmanager->initHooks(array('stocklist'));
$extrafields = new ExtraFields($db);
+$diroutputmassaction=$conf->inventory->dir_output . '/temp/massgeneration/'.$user->id;
+$hookmanager->initHooks(array('stocklist'));
-// fetch optionals attributes and labels
+// Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);
+
$search_array_options=$extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
@@ -69,30 +85,69 @@ $fieldstosearchall = array(
'e.town'=>'Town',
);
-
-// Extra fields
-if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
+// Definition of fields for list
+$arrayfields=array(
+ 'stockqty'=>array('type'=>'float', 'label'=>'PhysicalStock', 'enabled'=>1, 'visible'=>-2, 'position'=>70),
+ 'estimatedvalue'=>array('type'=>'float', 'label'=>'EstimatedStockValue', 'enabled'=>1, 'visible'=>-2, 'position'=>71),
+ 'sellvalue'=>array('type'=>'float', 'label'=>'EstimatedStockValueSell', 'enabled'=>1, 'visible'=>-2, 'position'=>72),
+);
+foreach($object->fields as $key => $val)
{
- foreach($extrafields->attribute_label as $key => $val)
- {
- if (! empty($extrafields->attribute_list[$key])) $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>(($extrafields->attribute_list[$key]<0)?0:1), 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>(abs($extrafields->attribute_list[$key])!=3 && $extrafields->attribute_perms[$key]));
- }
+ // If $val['visible']==0, then we never show the field
+ if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']);
}
+// Extra fields
+if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0)
+{
+ foreach($extrafields->attributes[$object->table_element]['label'] as $key => $val)
+ {
+ if (! empty($extrafields->attributes[$object->table_element]['list'][$key]))
+ $arrayfields["ef.".$key]=array('label'=>$extrafields->attributes[$object->table_element]['label'][$key], 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key]<0)?0:1), 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key])!=3 && $extrafields->attributes[$object->table_element]['perms'][$key]));
+ }
+}
+$object->fields = dol_sort_array($object->fields, 'position');
+$arrayfields = dol_sort_array($arrayfields, 'position');
/*
* Actions
*/
-include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
+if (GETPOST('cancel', 'alpha')) { $action='list'; $massaction=''; }
+if (! GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; }
-if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // Both test are required to be compatible with all browsers
+$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))
{
- $search_ref="";
- $sall="";
- $search_label="";
- $search_status="";
- $search_array_options=array();
+ // 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
+ {
+ $search_ref="";
+ $sall="";
+ $search_label="";
+ $search_status="";
+ $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='Entrepot';
+ $objectlabel='Warehouse';
+ $permtoread = $user->rights->stock->lire;
+ $permtodelete = $user->rights->stock->supprimer;
+ $uploaddir = $conf->stock->dir_output;
+ include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
@@ -103,6 +158,14 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
$form=new Form($db);
$warehouse=new Entrepot($db);
+$now=dol_now();
+
+$help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks';
+$title = $langs->trans("ListOfWarehouses");
+
+
+// Build and execute select
+// --------------------------------------------------------------------
$sql = "SELECT e.rowid, e.ref, e.statut, e.lieu, e.address, e.zip, e.town, e.fk_pays, e.fk_parent,";
$sql.= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue, SUM(ps.reel) as stockqty";
// Add fields from extrafields
@@ -115,16 +178,16 @@ if (! empty($extrafields->attributes[$object->table_element]['label'])) {
$parameters=array();
$reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
$sql.=$hookmanager->resPrint;
-//$sql=preg_replace('/, $/', '', $sql);
-$sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e";
+$sql=preg_replace('/,\s*$/', '', $sql);
+$sql.= " FROM ".MAIN_DB_PREFIX.$object->table_element." as e";
+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 (e.rowid = ef.fk_object)";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON e.rowid = ps.fk_entrepot";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON ps.fk_product = p.rowid";
-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 (e.rowid = ef.fk_object)";
$sql.= " WHERE e.entity IN (".getEntity('stock').")";
if ($search_ref) $sql.= natural_search("e.ref", $search_ref); // ref
if ($search_label) $sql.= natural_search("e.lieu", $search_label); // label
if ($search_status != '' && $search_status >= 0) $sql.= " AND e.statut = ".$search_status;
-if ($sall) $sql .= natural_search(array_keys($fieldstosearchall), $sall);
+if ($search_all) $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
// Add where from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
// Add where from hooks
@@ -149,189 +212,308 @@ if ($result)
}
}
$sql.= $db->order($sortfield, $sortorder);
-$sql.= $db->plimit($limit+1, $offset);
-$result = $db->query($sql);
-if ($result)
+// Count total nb of records
+$nbtotalofrecords = '';
+if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
{
- $num = $db->num_rows($result);
-
- $i = 0;
-
- $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks';
- llxHeader("", $langs->trans("ListOfWarehouses"), $help_url);
-
- $param='';
- if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage;
- if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit;
- if ($search_ref) $param.="&search_ref=".urlencode($search_ref);
- if ($search_label) $param.="&search_label=".urlencode($search_label);
- if ($search_status) $param.="&search_status=".urlencode($search_status);
- if ($sall) $param.="&sall=".urlencode($sall);
-
- // Add $param from extra fields
- include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
-
- $newcardbutton='';
- if ($user->rights->stock->creer)
+ $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
{
- $newcardbutton=''.$langs->trans('MenuNewWarehouse').'';
- $newcardbutton.= '';
- $newcardbutton.= '';
+ $page = 0;
+ $offset = 0;
}
-
- print '
";
-
- print '';
+}
+// 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)
+{
+ $num = $nbtotalofrecords;
}
else
{
- dol_print_error($db);
+ $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)
+{
+ $obj = $db->fetch_object($resql);
+ $id = $obj->rowid;
+ header("Location: ".DOL_URL_ROOT.'/product/stock/card.php?id='.$id);
+ exit;
+}
+
+
+// Output page
+// --------------------------------------------------------------------
+
+llxHeader('', $title, $help_url);
+
+$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);
+if ($search_ref) $param.="&search_ref=".urlencode($search_ref);
+if ($search_label) $param.="&search_label=".urlencode($search_label);
+if ($search_status) $param.="&search_status=".urlencode($search_status);
+if ($search_all) $param.="&search_all=".urlencode($search_all);
+if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
+// Add $param from extra fields
+include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
+
+// List of mass actions available
+$arrayofmassactions = array(
+ //'presend'=>$langs->trans("SendByMail"),
+ //'builddoc'=>$langs->trans("PDFMerge"),
+);
+//if ($user->rights->stock->supprimer) $arrayofmassactions['predelete']=''.$langs->trans("Delete");
+if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
+$massactionbutton=$form->selectMassAction('', $arrayofmassactions);
+
+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=$user->rights->mymodule->read;
+ $delallowed=$user->rights->mymodule->create;
+
+ print $formfile->showdocuments('massfilesarea_mymodule', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
}
// End of page
diff --git a/htdocs/product/stock/movement_card.php b/htdocs/product/stock/movement_card.php
index 0278e1572e6..c08fc8078a8 100644
--- a/htdocs/product/stock/movement_card.php
+++ b/htdocs/product/stock/movement_card.php
@@ -451,7 +451,9 @@ $sql.= " m.type_mouvement,";
$sql.= " pl.rowid as lotid, pl.eatby, pl.sellby,";
$sql.= " u.login, u.photo, u.lastname, u.firstname";
// Add fields from extrafields
-foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+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); // Note that $action and $object may have been modified by hook
diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php
index 73b783e09b9..a4831d46844 100644
--- a/htdocs/product/stock/movement_list.php
+++ b/htdocs/product/stock/movement_list.php
@@ -429,7 +429,9 @@ $sql.= " m.fk_projet,";
$sql.= " pl.rowid as lotid, pl.eatby, pl.sellby,";
$sql.= " u.login, u.photo, u.lastname, u.firstname";
// Add fields from extrafields
-foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$key : '');
+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); // Note that $action and $object may have been modified by hook
diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php
index b91c5d9c5ec..328847c6473 100644
--- a/htdocs/product/stock/product.php
+++ b/htdocs/product/stock/product.php
@@ -764,7 +764,7 @@ if (empty($reshook))
if ($user->rights->stock->mouvement->creer)
{
- if (! $variants) {
+ if (! $variants || ! empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) {
print 'id . '&action=correction">' . $langs->trans("CorrectStock") . '';
}
else
@@ -780,7 +780,7 @@ if (empty($reshook))
//if (($user->rights->stock->mouvement->creer) && ! $object->hasbatch())
if ($user->rights->stock->mouvement->creer)
{
- if (! $variants) {
+ if (! $variants || ! empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) {
print 'id . '&action=transfert">' . $langs->trans("TransferStock") . '';
}
else
@@ -804,8 +804,8 @@ if (! $variants) {
*/
print '