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 '
'; // hideobject is to start hidden print "
\n"; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 787f3ded291..f26e657679a 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -190,7 +190,7 @@ if ($action=='install') //var_dump($modulenamedir); if (! dol_is_dir($modulenamedir)) { - setEventMessages($langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat").'
Dir not found: '.$conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulename.'
'.$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulename, null, 'errors'); + setEventMessages($langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat").'
'.$langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat2", $modulename, 'htdocs/'.$modulename), null, 'errors'); $error++; } } diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 1320c20ffbb..14366f46de7 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -1048,6 +1048,7 @@ class BlockedLog if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; $fingerprint = dol_hash(print_r($mysoc, true).getRandomPassword(1), '5'); diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 5e24724b6f7..8e6551e92ea 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -42,6 +42,11 @@ $contextpage= GETPOST('contextpage', 'aZ')?GETPOST('contextpage', 'aZ'):'bomcard $backtopage = GETPOST('backtopage', 'alpha'); $lineid = GETPOST('lineid', 'int'); +// PDF +$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0)); +$hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0)); +$hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0)); + // Initialize technical objects $object=new BOM($db); $extrafields = new ExtraFields($db); @@ -92,8 +97,8 @@ if (empty($reshook)) $permissiontodelete = $user->rights->bom->delete || ($permissiontoadd && $object->status == 0); $backurlforlist = DOL_URL_ROOT.'/bom/bom_list.php'; if (empty($backtopage)) { - if (empty($id)) $backtopage = $backurlforlist; - else $backtopage = DOL_URL_ROOT.'/bom/bom_card.php?id='.$id; + if (empty($id) && $action != 'add' && $action != 'create') $backtopage = $backurlforlist; + else $backtopage = DOL_URL_ROOT.'/bom/bom_card.php?id='.($id > 0 ? $id : '__ID__'); } $triggermodname = 'BOM_MODIFY'; // Name of trigger action code to execute when we modify record @@ -286,6 +291,112 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); } + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); + } + + // Confirmation of validation + if ($action == 'validate') + { + // We check that object has a temporary ref + $ref = substr($object->ref, 1, 4); + if ($ref == 'PROV') { + $object->fetch_product(); + $numref = $object->getNextNumRef($object->product); + } else { + $numref = $object->ref; + } + + $text = $langs->trans('ConfirmValidateBom', $numref); + /*if (! empty($conf->notification->enabled)) + { + require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; + $notify = new Notify($db); + $text .= '
'; + $text .= $notify->confirmMessage('BOM_VALIDATE', $object->socid, $object); + }*/ + + $formquestion=array(); + if (! empty($conf->bom->enabled)) + { + $langs->load("mrp"); + require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + $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), + ); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220); + } + + // Confirmation of closing + if ($action == 'close') + { + $text = $langs->trans('ConfirmCloseBom', $object->ref); + /*if (! empty($conf->notification->enabled)) + { + require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; + $notify = new Notify($db); + $text .= '
'; + $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object); + }*/ + + $formquestion=array(); + if (! empty($conf->bom->enabled)) + { + $langs->load("mrp"); + require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + $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), + ); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220); + } + + // Confirmation of reopen + if ($action == 'reopen') + { + $text = $langs->trans('ConfirmReopenBom', $object->ref); + /*if (! empty($conf->notification->enabled)) + { + require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; + $notify = new Notify($db); + $text .= '
'; + $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object); + }*/ + + $formquestion=array(); + if (! empty($conf->bom->enabled)) + { + $langs->load("mrp"); + require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + $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), + ); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ReOpen'), $text, 'confirm_reopen', $formquestion, 0, 1, 220); + } + // Clone confirmation if ($action == 'clone') { // Create an array for form @@ -467,10 +578,35 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''.$langs->trans('Modify').''."\n"; } + // Validate + if ($user->rights->bom->write && $object->status == BOM::STATUS_DRAFT) + { + if (is_array($object->lines) && count($object->lines) > 0) + { + print '' . $langs->trans("Validate") . ''; + } + else + { + print '' . $langs->trans("Validate") . ''; + } + } + + // Close / Cancel + if ($user->rights->bom->write && $object->status == BOM::STATUS_VALIDATED) + { + print '' . $langs->trans("Disable") . ''; + } + + // Re-open + if ($user->rights->bom->write && $object->status == BOM::STATUS_CANCELED) + { + print '' . $langs->trans("ReOpen") . ''; + } + // Clone if ($user->rights->bom->write) { - print '
' . $langs->trans("ToClone") . '
'; + print '' . $langs->trans("ToClone") . ''; } /* diff --git a/htdocs/bom/bom_list.php b/htdocs/bom/bom_list.php index 635f0f9db65..46473d52ddb 100644 --- a/htdocs/bom/bom_list.php +++ b/htdocs/bom/bom_list.php @@ -21,6 +21,7 @@ * \ingroup bom * \brief List page for bom */ + // Load Dolibarr environment require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; @@ -99,7 +100,7 @@ $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']) > 0) @@ -179,8 +180,9 @@ foreach($object->fields as $key => $val) $sql.='t.'.$key.', '; } // Add fields from extrafields -if (! empty($extrafields->attributes[$object->table_element]['label'])) +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 @@ -213,6 +215,7 @@ foreach($object->fields as $key => $val) // 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 @@ -258,7 +261,7 @@ if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && { $obj = $db->fetch_object($resql); $id = $obj->rowid; - header("Location: ".dol_buildpath('/bom/bom_card.php', 1).'?id='.$id); + header("Location: ".DOL_URL_ROOT.'/bom/bom_card.php?id='.$id); exit; } @@ -290,7 +293,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 @@ -315,19 +319,7 @@ print ''; print ''; print ''; -$newcardbutton=''; -//if ($user->rights->bom->creer) -//{ - $newcardbutton=''.$langs->trans('New').''; - $newcardbutton.= ''; - $newcardbutton.= ''; -//} -//else -//{ -// $newcardbutton=''.$langs->trans('New').''; -// $newcardbutton.= ''; -// $newcardbutton.= ''; -//} +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/bom/bom_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $user->rights->bom->write); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'cubes', 0, $newcardbutton, '', $limit); @@ -338,10 +330,10 @@ $objecttmp=new BOM($db); $trackid='xxxx'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; -if ($sall) +if ($search_all) { foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); - print '
'.$langs->trans("FilterOnInto", $sall) . join(', ', $fieldstosearchall).'
'; + print '
'.$langs->trans("FilterOnInto", $search_all) . join(', ', $fieldstosearchall).'
'; } $moreforfilter = ''; @@ -424,7 +416,7 @@ $parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sort $reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ')."\n"; +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; print ''."\n"; @@ -460,12 +452,14 @@ while ($i < min($num, $limit)) foreach($object->fields as $key => $val) { $cssforfield=(empty($val['css'])?'':$val['css']); - if ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center'; - elseif ($key == 'ref') $cssforfield.=($cssforfield?' ':'').'nowrap'; - elseif (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center'; - elseif (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap'; - elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real'))) $cssforfield.=($cssforfield?' ':'').'right'; - + 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 ''; @@ -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 $form->selectDate($dateend, 'dateend', 0, 0, 1, '', 1, 0); print ''; @@ -548,6 +550,7 @@ if ($resql) $actionstatic->type_label=$obj->type_label; $actionstatic->type_picto=$obj->type_picto; $actionstatic->label=$obj->label; + $actionstatic->location = $obj->location; $actionstatic->note=dol_htmlentitiesbr($obj->note); print ''; @@ -609,11 +612,11 @@ if ($resql) print $form->textwithtooltip(dol_trunc($text, 40), $actionstatic->note); print ''; } - + $formatToUse = $obj->fulldayevent?'day':'dayhour'; // Start date if (! empty($arrayfields['a.datep']['checked'])) { print ''; - print dol_print_date($db->jdate($obj->dp), "dayhour"); + print dol_print_date($db->jdate($obj->dp), $formatToUse); $late=0; if ($obj->percent == 0 && $obj->dp && $db->jdate($obj->dp) < ($now - $delay_warning)) $late=1; if ($obj->percent == 0 && ! $obj->dp && $obj->dp2 && $db->jdate($obj->dp) < ($now - $delay_warning)) $late=1; @@ -626,7 +629,7 @@ if ($resql) // End date if (! empty($arrayfields['a.datep2']['checked'])) { print ''; - print dol_print_date($db->jdate($obj->dp2), "dayhour"); + print dol_print_date($db->jdate($obj->dp2), $formatToUse); print ''; } diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index f688808d10e..6d815d63d8b 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -551,7 +551,7 @@ class Mailing extends CommonObject $result = ''; $companylink = ''; - $label = '' . $langs->trans("ShowEmailing") . ''; + $label = '' . $langs->trans("ShowEMailing") . ''; $label.= '
'; $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; @@ -570,7 +570,7 @@ class Mailing extends CommonObject { if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $label=$langs->trans("ShowEmailing"); + $label=$langs->trans("ShowEMailing"); $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; diff --git a/htdocs/comm/multiprix.php b/htdocs/comm/multiprix.php index a176f758d7a..429e7f3dacf 100644 --- a/htdocs/comm/multiprix.php +++ b/htdocs/comm/multiprix.php @@ -91,15 +91,13 @@ if ($_socid > 0) dol_fiche_head($head, $tabchoice, $langs->trans("ThirdParty"), 0, 'company'); - print ''; - print '\n"; - - - print ""; - print "
'; - print ''; + print '
'; - print '"; + print '"; - print '
'; - print $langs->trans("PriceLevel").''.$objsoc->price_level."
'; + print $langs->trans("PriceLevel").''.$objsoc->price_level."
'; - print $langs->trans("NewValue").''; + print '
'; + print $langs->trans("NewValue").''; print '
"; - print "
"; - dol_fiche_end(); print '
'; @@ -157,8 +149,8 @@ if ($_socid > 0) while ($i < $num ) { $obj = $db->fetch_object($resql); - $tag = !$tag; - print ''; + + print ''; print ''.dol_print_date($db->jdate($obj->dc), "dayhour").''; print ''.$obj->price_level.' '; $userstatic->id=$obj->uid; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 968607ed660..0d13537037c 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1924,7 +1924,7 @@ if ($action == 'create' && $usercancreate) // Confirmation of validation if ($action == 'validate') { - // on verifie si l'objet est en numerotation provisoire + // We check that object has a temporary ref $ref = substr($object->ref, 1, 4); if ($ref == 'PROV') { $numref = $object->getNextNumRef($soc); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 16d9dcdc3d8..66a15857a04 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -647,7 +647,7 @@ class Commande extends CommonOrder $now=dol_now(); - $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= ' SET fk_statut = '.self::STATUS_CLOSED.','; $sql.= ' fk_user_cloture = '.$user->id.','; $sql.= " date_cloture = '".$this->db->idate($now)."'"; diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index 1b0f7feffe4..7f43b24763a 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -473,7 +473,9 @@ $sql.= " ba.rowid as bankid, ba.ref as bankref,"; $sql.= " bu.url_id,"; $sql.= " s.nom, s.name_alias, s.client, s.fournisseur, s.email, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur"; // 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/compta/bank/card.php b/htdocs/compta/bank/card.php index fd5a2b42723..ac32ce98c30 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -627,7 +627,7 @@ else $conciliate=$object->canBeConciliated(); if ($conciliate == -2) print $langs->trans("No").' ('.$langs->trans("CashAccount").')'; elseif ($conciliate == -3) print $langs->trans("No").' ('.$langs->trans("Closed").')'; - else print ($object->rappro==1 ? $langs->trans("Yes") : ($langs->trans("No").' ('.$langs->trans("ConciliationDisabled").')')); + else print ($object->rappro==1 ? $langs->trans("Yes") : ($langs->trans("No").' ('.$langs->trans("ConciliationDisabled").')')); print ''; print ''.$langs->trans("BalanceMinimalAllowed").''; diff --git a/htdocs/compta/bank/list.php b/htdocs/compta/bank/list.php index 8f87d6f7151..6a143d4a8d1 100644 --- a/htdocs/compta/bank/list.php +++ b/htdocs/compta/bank/list.php @@ -73,7 +73,7 @@ $hookmanager->initHooks(array('bankaccountlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('bank_account'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options=$extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // List of fields to search into when doing a "search in all" @@ -144,7 +144,9 @@ $accounts = array(); $sql = "SELECT b.rowid, b.label, b.courant, b.rappro, b.account_number, b.fk_accountancy_journal, b.currency_code, b.datec as date_creation, b.tms as date_update"; // 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 @@ -514,7 +516,10 @@ foreach ($accounts as $key=>$type) } } } - else print $langs->trans("FeatureDisabled"); + else + { + print ''.$langs->trans("FeatureDisabled").''; + } print ''; if (! $i) $totalarray['nbfield']++; } diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 560a6e2bc0d..1d88ebc87aa 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1514,8 +1514,8 @@ class Contact extends CommonObject /** * Get Contact roles for a thirdparty * - * @param string $element element type - * @return array|int + * @param string $element Element type + * @return array|int Array of contact roles or -1 * @throws Exception */ public function getContactRoles($element = '') diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 1eed9497619..9f3dc206447 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -276,7 +276,9 @@ $sql.= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.zip, p.town, $sql.= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,"; $sql.= " co.code as country_code"; // 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/contrat/list.php b/htdocs/contrat/list.php index fc110d4a396..0fd27d29826 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -218,7 +218,9 @@ $sql.= ' SUM('.$db->ifsql("cd.statut=4 AND (cd.date_fin_validite IS NOT NULL AND $sql.= ' SUM('.$db->ifsql("cd.statut=4 AND (cd.date_fin_validite IS NOT NULL AND cd.date_fin_validite < '".$db->idate($now - $conf->contrat->services->expires->warning_delay)."')", 1, 0).') as nb_late,'; $sql.= ' SUM('.$db->ifsql("cd.statut=5", 1, 0).') as nb_closed'; // 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/contrat/services_list.php b/htdocs/contrat/services_list.php index 3e5b9f55c98..fac71516e99 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -219,7 +219,9 @@ $sql.= " cd.subprice,"; //$sql.= " cd.date_c as date_creation,"; $sql.= " cd.tms as date_update"; // 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/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 66428eea974..7082bc5e882 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -18,7 +18,7 @@ /** * \file htdocs/core/actions_addupdatedelete.inc.php - * \brief Code for common actions cancel / add / update / delete / clone + * \brief Code for common actions cancel / add / update / update_extras / delete / deleteline / validate / cancel / reopen / clone */ @@ -231,6 +231,92 @@ if ($action == 'confirm_deleteline' && $confirm == 'yes' && ! empty($permissiont } } +// Action validate object +if ($action == 'confirm_validate' && $confirm == 'yes' && $permissionedit) +{ + $result = $object->validate($user); + if ($result >= 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +// Action close object +if ($action == 'confirm_close' && $confirm == 'yes' && $permissionedit) +{ + $result = $object->cancel($user); + if ($result >= 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +// Action reopen object +if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissionedit) +{ + $result = $object->reopen($user); + if ($result >= 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} // Action clone object if ($action == 'confirm_clone' && $confirm == 'yes' && ! empty($permissiontoadd)) diff --git a/htdocs/core/boxes/box_accountancy_suspense_account.php b/htdocs/core/boxes/box_accountancy_suspense_account.php index 03c0f0ab7ae..86971e1e042 100644 --- a/htdocs/core/boxes/box_accountancy_suspense_account.php +++ b/htdocs/core/boxes/box_accountancy_suspense_account.php @@ -74,7 +74,7 @@ class box_accountancy_suspense_account extends ModeleBoxes include_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; - $bookkeepingstatic = new BookKeeping($this->db); + //$bookkeepingstatic = new BookKeeping($this->db); $this->info_box_head = array('text' => $langs->trans("BoxTitleSuspenseAccount")); @@ -103,7 +103,7 @@ class box_accountancy_suspense_account extends ModeleBoxes $this->info_box_contents[0][1] = array( 'td' => 'class="right"', - 'text' => '' . $nbSuspenseAccount . '', + 'text' => '' . $nbSuspenseAccount . '', 'asis' => 1 ); } else { diff --git a/htdocs/core/boxes/box_last_modified_ticket.php b/htdocs/core/boxes/box_last_modified_ticket.php index 8f86be5a115..56299c60429 100644 --- a/htdocs/core/boxes/box_last_modified_ticket.php +++ b/htdocs/core/boxes/box_last_modified_ticket.php @@ -166,7 +166,7 @@ class box_last_modified_ticket extends ModeleBoxes // Date creation $this->info_box_contents[$i][$r] = array( 'td' => 'class="right"', - 'text' => dol_print_date($this->db->idate($objp->datec), 'dayhour') + 'text' => dol_print_date($datec, 'dayhour') ); $r++; diff --git a/htdocs/core/boxes/box_last_ticket.php b/htdocs/core/boxes/box_last_ticket.php index 18990cd8bb6..cf4b7f305f7 100644 --- a/htdocs/core/boxes/box_last_ticket.php +++ b/htdocs/core/boxes/box_last_ticket.php @@ -166,7 +166,7 @@ class box_last_ticket extends ModeleBoxes // Date creation $this->info_box_contents[$i][$r] = array( 'td' => 'class="right"', - 'text' => dol_print_date($this->db->idate($objp->datec), 'dayhour'), + 'text' => dol_print_date($datec, 'dayhour'), ); $r++; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 484bb5fa4d4..d17d49e326e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7399,7 +7399,7 @@ abstract class CommonObject if (array_key_exists('fk_user_creat', $fieldvalues) && ! ($fieldvalues['fk_user_creat'] > 0)) $fieldvalues['fk_user_creat']=$user->id; unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into insert. if (array_key_exists('ref', $fieldvalues)) $fieldvalues['ref']=dol_string_nospecial($fieldvalues['ref']); // If field is a ref,we sanitize data - + $keys=array(); $values = array(); foreach ($fieldvalues as $k => $v) { @@ -7857,6 +7857,57 @@ abstract class CommonObject } } + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $status New status to set (often a constant like self::STATUS_XXX) + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @param string $triggercode Trigger code to use + * @return int <0 if KO, >0 if OK + */ + public function setStatusCommon($user, $status, $notrigger = 0, $triggercode = '') + { + $error=0; + + $this->db->begin(); + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET status = ".$status; + $sql.= " WHERE rowid = ".$this->id; + + if ($this->db->query($sql)) + { + if (! $error) + { + $this->oldcopy= clone $this; + } + + if (! $error && ! $notrigger) { + // Call trigger + $result=$this->call_trigger($triggercode, $user); + if ($result < 0) $error++; + } + + if (!$error) { + $this->status = $status; + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + else + { + $this->error=$this->db->error(); + $this->db->rollback(); + return -1; + } + } + + /** * Initialise object with example values * Id must be 0 if object instance is a specimen diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 535db40e0e4..287d8121213 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -227,10 +227,7 @@ class Conf $filesList = explode(":", $this->global->LOCAL_CONSTS_FILES); foreach ($filesList as $file) { $file=dol_sanitizeFileName($file); - include_once DOL_DOCUMENT_ROOT . "/".$file."/".$file."_consts.php"; - foreach ($file2bddconsts as $key=>$value) { - $this->global->$key=$value; - } + include_once DOL_DOCUMENT_ROOT . "/".$file."/".$file."_consts.php"; // This file must set $this->global->XXX vars. } } @@ -442,7 +439,6 @@ class Conf // Set some default values //$this->global->MAIN_LIST_FILTER_ON_DAY=1; // On filter that show date, we must show input field for day before or after month - $this->global->MAIN_ACTIVATE_HTML5=1; $this->global->MAIN_MAIL_USE_MULTI_PART=1; // societe @@ -669,6 +665,8 @@ class Conf if (! isset($this->global->MAIN_EXTRAFIELDS_IN_ONE_TD)) $this->global->MAIN_EXTRAFIELDS_IN_ONE_TD = 1; + if (! isset($this->global->MAIN_USE_OLD_TITLE_BUTTON)) $this->global->MAIN_USE_OLD_TITLE_BUTTON = 0; + if (empty($this->global->MAIN_MODULE_DOLISTORE_API_SRV)) $this->global->MAIN_MODULE_DOLISTORE_API_SRV='https://www.dolistore.com'; if (empty($this->global->MAIN_MODULE_DOLISTORE_API_KEY)) $this->global->MAIN_MODULE_DOLISTORE_API_KEY='dolistorecatalogpublickey1234567'; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d9442e43457..2130a7d7e38 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5607,10 +5607,10 @@ class Form $reset_scripts = ""; // Generate the date part, depending on the use or not of the javascript calendar - $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day').'\');'; - $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d').'\');'; - $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m').'\');'; - $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day', 'tzuser').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d', 'tzuser').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m', 'tzuser').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y', 'tzuser').'\');'; /*if ($usecalendar == "eldy") { $base=DOL_URL_ROOT.'/core/'; @@ -5627,7 +5627,7 @@ class Form { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); '; - $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H', 'tzuser').'\');'; if ($fullday) $reset_scripts .= ' } '; } // Update the minute part @@ -5635,7 +5635,7 @@ class Form { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); '; - $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M').'\');'; + $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M', 'tzuser').'\');'; if ($fullday) $reset_scripts .= ' } '; } // If reset_scripts is not empty, print the link with the reset_scripts in the onClick diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 1aee5e67cd5..b3140c7e051 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2220,7 +2220,7 @@ function dol_print_socialnetworks($value, $cid, $socid, $type) if (! empty($type)) { $newskype ='
'; - $newskype.=img_picto($langs->trans(strtoupper($type)), $type.'.png', '', false, 0, 0, '', 'paddingright'); + $newskype.=img_picto($langs->trans(strtoupper($type)), $type.'.png', '', false, 0, 0, '', 'paddingright', 0); $newskype.=$value; if ($type == 'skype') { @@ -4125,9 +4125,9 @@ function load_fiche_titre($titre, $morehtmlright = '', $picto = 'generic', $pict if ($picto == 'setup') $picto='generic'; $return.= "\n"; - $return.= ''; // maring bottom must be same than into print_barre_list - if ($picto) $return.= ''; - $return.= ''; print '
'.img_picto('', $picto, 'class="valignmiddle widthpictotitle pictotitle"', $pictoisfullpath).''; + $return.= ''; // maring bottom must be same than into print_barre_list + if ($picto) $return.= ''; + $return.= ''; if (dol_strlen($morehtmlcenter)) @@ -4187,11 +4187,10 @@ function print_barre_liste($titre, $page, $file, $options = '', $sortfield = '', print "\n"; print "\n"; - print '
'.img_picto('', $picto, 'class="valignmiddle widthpictotitle pictotitle"', $pictoisfullpath).''; $return.= '
'.$titre.'
'; $return.= '
'; // maring bottom must be same than into load_fiche_tire + print '
'; // maring bottom must be same than into load_fiche_tire // Left - //if ($picto && $titre) print ''; - print ''; print ''; - print ''; + print ''; print ''; $starthalfday=($obj->halfday == -1 || $obj->halfday == 2)?'afternoon':'morning'; @@ -304,7 +304,7 @@ if (! empty($conf->deplacement->enabled) && $user->rights->deplacement->lire) print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -376,7 +376,7 @@ if (! empty($conf->expensereport->enabled) && $user->rights->expensereport->lire print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; diff --git a/htdocs/index.php b/htdocs/index.php index c1c6d4a1f63..b0b04075da4 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -212,7 +212,7 @@ if (empty($user->societe_id) && empty($conf->global->MAIN_DISABLE_GLOBAL_BOXSTAT 'askprice', 'projects', 'expensereports', - 'holidays', + 'holiday', 'donations' ); // Dashboard Icon lines diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 42097685f6f..1a8379d857a 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -50,6 +50,8 @@ UPDATE llx_c_units SET label = 'SurfaceUnitm2' WHERE code IN ('M2'); -- For v11 ALTER TABLE llx_bom_bom ADD COLUMN duration double(8,4) DEFAULT NULL; +ALTER TABLE llx_bom_bomline ADD COLUMN position integer NOT NULL DEFAULT 0; +ALTER TABLE llx_bom_bomline DROP COLUMN rank; create table llx_categorie_warehouse ( diff --git a/htdocs/install/mysql/tables/llx_bom_bomline.sql b/htdocs/install/mysql/tables/llx_bom_bomline.sql index cb7079cf16a..330f1bb18d6 100644 --- a/htdocs/install/mysql/tables/llx_bom_bomline.sql +++ b/htdocs/install/mysql/tables/llx_bom_bomline.sql @@ -23,6 +23,6 @@ CREATE TABLE llx_bom_bomline( import_key varchar(14), qty double(24,8) NOT NULL, efficiency double(8,4) NOT NULL DEFAULT 1, - position integer NOT NULL + position integer NOT NULL DEFAULT 0 -- END MODULEBUILDER FIELDS ) ENGINE=innodb; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 0546b472225..c82dd17343a 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1069,6 +1069,7 @@ CompanyTown=Town CompanyCountry=Country CompanyCurrency=Main currency CompanyObject=Object of the company +IDCountry=ID country Logo=Logo LogoDesc=Main logo of company. Will be used into generated documents (PDF, ...) LogoSquarred=Logo (squarred) diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 8ad19e06695..465846a43db 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -76,6 +76,7 @@ ContractSentByEMail=Contract %s sent by email OrderSentByEMail=Sales order %s sent by email InvoiceSentByEMail=Customer invoice %s sent by email SupplierOrderSentByEMail=Purchase order %s sent by email +ORDER_SUPPLIER_DELETEInDolibarr=Purchase order %s deleted SupplierInvoiceSentByEMail=Vendor invoice %s sent by email ShippingSentByEMail=Shipment %s sent by email ShippingValidated= Shipment %s validated diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index f8c3c1a1aee..0b4b9b61746 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -196,6 +196,7 @@ ErrorPhpMailDelivery=Check that you don't use a too high number of recipients an ErrorUserNotAssignedToTask=User must be assigned to task to be able to enter time consumed. ErrorTaskAlreadyAssigned=Task already assigned to user ErrorModuleFileSeemsToHaveAWrongFormat=The module package seems to have a wrong format. +ErrorModuleFileSeemsToHaveAWrongFormat2=At least one mandatory directory must exists into zip of module: %s or %s ErrorFilenameDosNotMatchDolibarrPackageRules=The name of the module package (%s) does not match expected name syntax: %s ErrorDuplicateTrigger=Error, duplicate trigger name %s. Already loaded from %s. ErrorNoWarehouseDefined=Error, no warehouses defined. diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 9d8e85f889d..9fbbe6a7161 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -27,4 +27,7 @@ DateStartPlannedMo=Date start planned DateEndPlannedMo=Date end planned KeepEmptyForAsap=Empty means 'As Soon As Possible' EstimatedDuration=Estimated duration -EstimatedDurationDesc=Estimated duration to manufacture this product using this BOM \ No newline at end of file +EstimatedDurationDesc=Estimated duration to manufacture this product using this BOM +ConfirmValidateBom=Are you sure you want to validate the BOM with the reference %s (you will be able to use it to build new Manufacturing Orders) +ConfirmCloseBom=Are you sure you want to cancel this BOM (you won't be able to use it to build new Manufacturing Orders anymore) ? +ConfirmReopenBom=Are you sure you want to re-open this BOM (you will be able to use it to build new Manufacturing Orders) \ No newline at end of file diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 9919767db0f..480a2aa91e5 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -213,8 +213,8 @@ UseMultipriceRules=Use price segment rules (defined into product module setup) t PercentVariationOver=%% variation over %s PercentDiscountOver=%% discount over %s KeepEmptyForAutoCalculation=Keep empty to have this calculated automatically from weight or volume of products -VariantRefExample=Example: COL -VariantLabelExample=Example: Color +VariantRefExample=Examples: COL, SIZE +VariantLabelExample=Examples: Color, Size ### composition fabrication Build=Produce ProductsMultiPrice=Products and prices for each price segment diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 5cd32512713..2e22e9fb23e 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -537,6 +537,26 @@ if ($dirins && $action == 'initobject' && $module && GETPOST('createtablearray', } else { + /** + * 'type' if the field format ('integer', 'integer:Class:pathtoclass', 'varchar(x)', 'double(24,8)', 'text', 'html', 'datetime', 'timestamp', 'float') + * 'label' the translation key. + * 'enabled' is a condition when the field must be managed. + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'default' is a default value for creation (can still be replaced by the global setup of default values) + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'position' is the sort order of field. + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' is the CSS style to use on field. For example: 'maxwidth200' + * 'help' is a string visible as a tooltip on field + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + */ + /*public $fields=array( 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), @@ -562,14 +582,31 @@ if ($dirins && $action == 'initobject' && $module && GETPOST('createtablearray', $i=10; while ($obj = $db->fetch_object($_results)) { + // fieldname $fieldname = $obj->Field; + // type $type = $obj->Type; if ($type == 'int(11)') $type='integer'; + // notnull $notnull = ($obj->Null == 'YES'?0:1); + // label $label = preg_replace('/_/', ' ', ucfirst($fieldname)); if ($fieldname == 'rowid') $label='ID'; + if ($fieldname == 'import_key') $label='ImportKey'; + // visible + $visible = -1; + if ($fieldname == 'entity') $visible = -2; + if ($fieldname == 'model_pdf') $visible = 0; + // enabled + $enabled = 1; + // default + $default = ''; + if ($fieldname == 'entity') $default=1; - $string.= "'".$obj->Field."' =>array('type'=>'".$type."', 'label'=>'".$label."', 'enabled'=>1, 'visible'=>-2"; + $string.= "'".$obj->Field."' =>array('type'=>'".$type."', 'label'=>'".$label."',"; + if ($default != '') $string.= " 'default'=>".$default.","; + $string.= " 'enabled'=>".$enabled.","; + $string.= " 'visible'=>".$visible; if ($notnull) $string.= ", 'notnull'=>".$notnull; if ($fieldname == 'ref') $string.= ", 'showoncombobox'=>1"; $string.= ", 'position'=>".$i."),\n"; @@ -1578,7 +1615,7 @@ elseif (! empty($module)) print '
'.img_picto('', $picto, 'id="pictotitle"', $pictoisfullpath).''; + print ''; if ($picto && $titre) print img_picto('', $picto, 'class="hideonsmartphone valignmiddle opacityhigh pictotitle widthpictotitle"', $pictoisfullpath); print '
'.$titre; if (!empty($titre) && $savtotalnboflines >= 0 && (string) $savtotalnboflines != '') print ' ('.$totalnboflines.')'; @@ -8283,7 +8282,7 @@ function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $u $class = 'btnTitle'; // hidden conf keep during button transition TODO: remove this block - if (empty($conf->global->MAIN_USE_NEW_TITLE_BUTTON)) { + if (!empty($conf->global->MAIN_USE_OLD_TITLE_BUTTON)) { $class = 'butActionNew'; } if (! empty($params['morecss'])) $class.=' '.$params['morecss']; @@ -8301,7 +8300,7 @@ function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $u $attr['class'] .= ' refused'; // hidden conf keep during button transition TODO: remove this block - if(empty($conf->global->MAIN_USE_NEW_TITLE_BUTTON)){ + if(!empty($conf->global->MAIN_USE_OLD_TITLE_BUTTON)){ $attr['class'] = 'butActionNewRefused'; } @@ -8363,7 +8362,7 @@ function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $u $button.= ''; // hidden conf keep during button transition TODO: remove this block - if(empty($conf->global->MAIN_USE_NEW_TITLE_BUTTON)){ + if(!empty($conf->global->MAIN_USE_OLD_TITLE_BUTTON)){ $button='<'.$tag.' '.$compiledAttributes.' >'.$label.''; $button.= ''; $button.= ''; diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index d16fc569961..b233b937be7 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -240,14 +240,18 @@ function pdf_getPDFFont($outputlangs) */ function pdf_getPDFFontSize($outputlangs) { + global $conf; + $size=10; // By default, for FPDI or ISO language on TCPDF - if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower) + if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower) { - if ($outputlangs->trans('FONTSIZEFORPDF')!='FONTSIZEFORPDF') + if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') { $size = (int) $outputlangs->trans('FONTSIZEFORPDF'); } } + if (! empty($conf->global->MAIN_PDF_FORCE_FONT_SIZE)) $size = $conf->global->MAIN_PDF_FORCE_FONT_SIZE; + return $size; } diff --git a/htdocs/core/lib/ticket.lib.php b/htdocs/core/lib/ticket.lib.php index 53afbe50dce..543bdb025fa 100644 --- a/htdocs/core/lib/ticket.lib.php +++ b/htdocs/core/lib/ticket.lib.php @@ -151,6 +151,7 @@ function showDirectPublicLink($object) require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; $email = CMailFile::getValidAddress($object->origin_email, 2); + $url = ''; if ($email) { $url = dol_buildpath('/public/ticket/view.php', 3).'?track_id='.$object->track_id.'&email='.$email; diff --git a/htdocs/core/menus/standard/auguria.lib.php b/htdocs/core/menus/standard/auguria.lib.php index 39e2150280e..5f27a68d63a 100644 --- a/htdocs/core/menus/standard/auguria.lib.php +++ b/htdocs/core/menus/standard/auguria.lib.php @@ -137,7 +137,7 @@ function print_auguria_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout } else { - $urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo_squarred.png'; + $urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo_squarred_alpha.png'; } $title=$langs->trans("GoIntoSetupToChangeLogo"); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 5d6bf501d82..cf95da29568 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -482,7 +482,7 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = $mysoc->logo_squarred_mini=(empty($conf->global->MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI)?'':$conf->global->MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI); $logoContainerAdditionalClass = 'backgroundforcompanylogo'; - if(!empty($conf->global->MAIN_INFO_SOCIETE_LOGO_NO_BACKGROUND)){ + if(! empty($conf->global->MAIN_INFO_SOCIETE_LOGO_NO_BACKGROUND)){ $logoContainerAdditionalClass = ''; } @@ -496,7 +496,8 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = }*/ else { - $urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo_squarred.png'; + $urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo_squarred_alpha.png'; + $logoContainerAdditionalClass = ''; } $title=$langs->trans("GoIntoSetupToChangeLogo"); diff --git a/htdocs/core/modules/bom/mod_bom_advanced.php b/htdocs/core/modules/bom/mod_bom_advanced.php index be6bd9f095d..eed79c037fd 100644 --- a/htdocs/core/modules/bom/mod_bom_advanced.php +++ b/htdocs/core/modules/bom/mod_bom_advanced.php @@ -118,11 +118,11 @@ class mod_bom_advanced extends ModeleNumRefboms /** * Return next free value * - * @param Societe $objsoc Object thirdparty + * @param Product $objprod Object product * @param Object $object Object we need next value for * @return string Value if KO, <0 if KO */ - public function getNextValue($objsoc, $object) + public function getNextValue($objprod, $object) { global $db,$conf; @@ -139,7 +139,7 @@ class mod_bom_advanced extends ModeleNumRefboms $date = ($object->date_bom ? $object->date_bom : $object->date); - $numFinal=get_next_value($db, $mask, 'bom_bom', 'ref', '', $objsoc, $date); + $numFinal=get_next_value($db, $mask, 'bom_bom', 'ref', '', null, $date); return $numFinal; } diff --git a/htdocs/core/modules/bom/mod_bom_standard.php b/htdocs/core/modules/bom/mod_bom_standard.php index af7e173bbae..eefbc7570c0 100644 --- a/htdocs/core/modules/bom/mod_bom_standard.php +++ b/htdocs/core/modules/bom/mod_bom_standard.php @@ -108,16 +108,16 @@ class mod_bom_standard extends ModeleNumRefboms /** * Return next free value * - * @param Societe $objsoc Object thirdparty + * @param Product $objprod Object product * @param Object $object Object we need next value for * @return string Value if KO, <0 if KO */ - public function getNextValue($objsoc, $object) + public function getNextValue($objprod, $object) { global $db,$conf; // D'abord on recupere la valeur max - $posindice=8; + $posindice=9; $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql.= " FROM ".MAIN_DB_PREFIX."bom_bom"; $sql.= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; @@ -137,7 +137,7 @@ class mod_bom_standard extends ModeleNumRefboms } //$date=time(); - $date=$object->date; + $date=$object->date_creation; $yymm = strftime("%y%m", $date); if ($max >= (pow(10, 4) - 1)) $num=$max+1; // If counter > 9999, we do not format on 4 chars, we take number as it is diff --git a/htdocs/core/modules/contract/doc/pdf_strato.modules.php b/htdocs/core/modules/contract/doc/pdf_strato.modules.php index d2dd1f56218..badf7343295 100644 --- a/htdocs/core/modules/contract/doc/pdf_strato.modules.php +++ b/htdocs/core/modules/contract/doc/pdf_strato.modules.php @@ -269,7 +269,7 @@ class pdf_strato extends ModelePDFContract $tab_top = 90; $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42:10); - // Affiche notes + // Display notes if (! empty($object->note_public)) { $tab_top -= 2; @@ -411,7 +411,7 @@ class pdf_strato extends ModelePDFContract $pdf->setPage($pageposafter); $curY = $tab_top_newpage; } - $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut + $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font // Detect if some page were added automatically and output _tableau for past pages while ($pagenb < $pageposafter) @@ -613,7 +613,7 @@ class pdf_strato extends ModelePDFContract pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->CONTRACT_DRAFT_WATERMARK); } - //Prepare la suite + //Prepare next $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size + 3); @@ -727,7 +727,7 @@ class pdf_strato extends ModelePDFContract $this->recipient = $object->thirdparty; //Recipient name - // On peut utiliser le nom de la societe du contact + // You can use the name of the contact company if ($usecontact && !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)) { $thirdparty = $object->contact; } else { diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index 8d29edec7d8..ddc07db0380 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -218,7 +218,7 @@ class pdf_espadon extends ModelePdfExpedition if ($conf->expedition->dir_output) { - // Definition de $dir et $file + // Definition of $dir and $file if ($object->specimen) { $dir = $conf->expedition->dir_output."/sending"; @@ -390,10 +390,10 @@ class pdf_espadon extends ModelePdfExpedition } - // Use new auto collum system + // Use new auto column system $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); - // Simulation de tableau pour connaitre la hauteur de la ligne de titre + // Table simulation to know the height of the title line $pdf->startTransaction(); $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); $pdf->rollbackTransaction(true); @@ -606,10 +606,10 @@ class pdf_espadon extends ModelePdfExpedition $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; } - // Affiche zone totaux + // Display total area $posy=$this->_tableau_tot($pdf, $object, 0, $bottomlasttab, $outputlangs); - // Pied de page + // Pagefoot $this->_pagefoot($pdf, $object, $outputlangs); if (method_exists($pdf, 'AliasNbPages')) $pdf->AliasNbPages(); @@ -653,12 +653,12 @@ class pdf_espadon extends ModelePdfExpedition /** * Show total to pay * - * @param PDF $pdf Object PDF + * @param PDF $pdf Object PDF * @param Facture $object Object invoice - * @param int $deja_regle Montant deja regle - * @param int $posy Position depart + * @param int $deja_regle Amount already paid + * @param int $posy Start Position * @param Translate $outputlangs Objet langs - * @return int Position pour suite + * @return int Position for suite */ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs) { @@ -673,7 +673,7 @@ class pdf_espadon extends ModelePdfExpedition $tab2_hl = 4; $pdf->SetFont('', 'B', $default_font_size - 1); - // Tableau total + // Total table $col1x = $this->posxweightvol-50; $col2x = $this->posxweightvol; /*if ($this->page_largeur < 210) // To work with US executive format { @@ -824,7 +824,7 @@ class pdf_espadon extends ModelePdfExpedition pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->SHIPPING_DRAFT_WATERMARK); } - //Prepare la suite + //Prepare next $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size + 3); @@ -1006,7 +1006,7 @@ class pdf_espadon extends ModelePdfExpedition } //Recipient name - // On peut utiliser le nom de la societe du contact + // You can use the name of the contact company if ($usecontact && !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)) { $thirdparty = $object->contact; } else { diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index da2ac06dcea..a3e3e539468 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -85,6 +85,13 @@ class modProduct extends DolibarrModules $this->const[$r][3] = 'Module to control product codes'; $this->const[$r][4] = 0; $r++; + + $this->const[$r][0] = "PRODUCT_PRICE_UNIQ"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "1"; + $this->const[$r][3] = 'pricing rule by default'; + $this->const[$r][4] = 0; + $r++; /*$this->const[$r][0] = "PRODUCT_ADDON_PDF"; $this->const[$r][1] = "chaine"; diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 3c98cd7709d..a225fe47005 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -270,6 +270,7 @@ class modSociete extends DolibarrModules 'st.code'=>'ProspectStatus','payterm.libelle'=>'PaymentConditions','paymode.libelle'=>'PaymentMode' ); if (! empty($conf->global->SOCIETE_USEPREFIX)) $this->export_fields_array[$r]['s.prefix']='Prefix'; + if (! empty($conf->global->PRODUIT_MULTIPRICES)) $this->export_fields_array[$r]['s.price_level']='PriceLevel'; // Add multicompany field if (! empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) { @@ -295,7 +296,8 @@ class modSociete extends DolibarrModules 's.tva_intra'=>"Text",'s.capital'=>"Numeric",'s.note_private'=>"Text",'s.note_public'=>"Text",'t.libelle'=>"Text", 'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code', 'st.code'=>'List:c_stcomm:libelle:code','d.nom'=>'Text','u.login'=>'Text','u.firstname'=>'Text','u.lastname'=>'Text','payterm.libelle'=>'Text', - 'paymode.libelle'=>'Text','s.entity'=>'Numeric' + 'paymode.libelle'=>'Text','s.entity'=>'Numeric', + 's.price_level'=>'Numeric' ); $this->export_entities_array[$r]=array('u.login'=>'user','u.firstname'=>'user','u.lastname'=>'user'); // We define here only fields that use another picto diff --git a/htdocs/core/modules/stock/doc/pdf_stdmovement.modules.php b/htdocs/core/modules/stock/doc/pdf_stdmovement.modules.php index 2a5f797147e..3ed4ff7e813 100644 --- a/htdocs/core/modules/stock/doc/pdf_stdmovement.modules.php +++ b/htdocs/core/modules/stock/doc/pdf_stdmovement.modules.php @@ -253,6 +253,7 @@ class pdf_stdmovement extends ModelePDFMovement $warehousestatic=new Entrepot($db); $movement=new MouvementStock($db); $userstatic=new User($db); + $element = 'movement'; $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.entity,"; $sql.= " e.ref as stock, e.rowid as entrepot_id, e.lieu,"; @@ -262,7 +263,9 @@ class pdf_stdmovement extends ModelePDFMovement $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[$element]['label'])) { + foreach ($extrafields->attributes[$element]['label'] as $key => $val) $sql.=($extrafields->attributes[$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/core/triggers/interface_90_modSociete_ContactRoles.class.php b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php index 13eb44d4eee..79b99e59a8f 100644 --- a/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php +++ b/htdocs/core/triggers/interface_90_modSociete_ContactRoles.class.php @@ -90,20 +90,23 @@ class InterfaceContactRoles extends DolibarrTriggers if (!empty($cloneFrom->id)) $TContactAlreadyLinked = array_merge($cloneFrom->liste_contact(-1, 'external'), $cloneFrom->liste_contact(-1, 'internal')); } - foreach($TContact as $i => $infos) { - foreach ($TContactAlreadyLinked as $contactData) { - if($contactData['id'] == $infos['fk_socpeople'] && $contactData['fk_c_type_contact'] == $infos['type_contact']) unset($TContact[$i]); + if (is_array($TContact)) + { + foreach($TContact as $i => $infos) { + foreach ($TContactAlreadyLinked as $contactData) { + if ($contactData['id'] == $infos['fk_socpeople'] && $contactData['fk_c_type_contact'] == $infos['type_contact']) unset($TContact[$i]); + } } - } - $nb = 0; - foreach($TContact as $infos) { - $res = $object->add_contact($infos['fk_socpeople'], $infos['type_contact']); - if($res > 0) $nb++; - } + $nb = 0; + foreach($TContact as $infos) { + $res = $object->add_contact($infos['fk_socpeople'], $infos['type_contact']); + if ($res > 0) $nb++; + } - if($nb > 0) { - setEventMessages($langs->trans('ContactAddedAutomatically', $nb), null, 'mesgs'); + if($nb > 0) { + setEventMessages($langs->trans('ContactAddedAutomatically', $nb), null, 'mesgs'); + } } } } diff --git a/htdocs/expedition/list.php b/htdocs/expedition/list.php index ebe0bcfd8df..1840569fd0e 100644 --- a/htdocs/expedition/list.php +++ b/htdocs/expedition/list.php @@ -192,7 +192,9 @@ $sql.= " typent.code as typent_code,"; $sql.= " state.code_departement as state_code, state.nom as state_name,"; $sql.= ' e.date_creation as date_creation, e.tms as date_update'; // 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/exports/class/export.class.php b/htdocs/exports/class/export.class.php index cd4d70c2518..d6b6a8676ae 100644 --- a/htdocs/exports/class/export.class.php +++ b/htdocs/exports/class/export.class.php @@ -399,8 +399,7 @@ class Export $szFilterField=''; break; case 'Status': - if (! empty($conf->global->MAIN_ACTIVATE_HTML5)) $szFilterField=''; - else $szFilterField=''; + $szFilterField=''; break; case 'Boolean': $szFilterField='
'.$holidaystatic->getNomUrl(1).''.$userstatic->getNomUrl(-1, 'leave').''.$userstatic->getNomUrl(-1, 'leave').''.$typeleaves[$obj->fk_type]['label'].'
'.$deplacementstatic->getNomUrl(1).''.$userstatic->getNomUrl(-1).''.$userstatic->getNomUrl(-1).''.$obj->km.''.dol_print_date($db->jdate($obj->dm), 'day').''.$deplacementstatic->LibStatut($obj->fk_statut, 3).'
'.$expensereportstatic->getNomUrl(1).''.$userstatic->getNomUrl(-1).''.$userstatic->getNomUrl(-1).''.price($obj->total_ttc).''.dol_print_date($db->jdate($obj->dm), 'day').''.$expensereportstatic->LibStatut($obj->status, 3).'
'; print '
'; - print load_fiche_titre($langs->trans("DescriptorFile")); + print load_fiche_titre($langs->trans("DescriptorFile"), '', ''); if (! empty($moduleobj)) { @@ -1638,35 +1675,33 @@ elseif (! empty($module)) print '
'; - - print '

'; - - // Readme file - print load_fiche_titre($langs->trans("ReadmeFile")); - - print '
'; - print '
'; - if (dol_is_file($dirread.'/'.$pathtofilereadme)) print $moduleobj->getDescLong(); - else print $langs->trans("ErrorFileNotFound", $pathtofilereadme); - - print '

'; - - // ChangeLog - print load_fiche_titre($langs->trans("ChangeLog")); - - print '
'; - print '
'; - - if (dol_is_file($dirread.'/'.$pathtochangelog)) print $moduleobj->getChangeLog(); - else print $langs->trans("ErrorFileNotFound", $pathtochangelog); - - print '
'; } else { print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'
'; } + if (! empty($moduleobj)) + { + print '

'; + + // Readme file + print load_fiche_titre($langs->trans("ReadmeFile"), '', ''); + + print ''; + if (dol_is_file($dirread.'/'.$pathtofilereadme)) print '
'.$moduleobj->getDescLong().'
'; + else print ''.$langs->trans("ErrorFileNotFound", $pathtofilereadme).''; + + print '

'; + + // ChangeLog + print load_fiche_titre($langs->trans("ChangeLog"), '', ''); + + print ''; + if (dol_is_file($dirread.'/'.$pathtochangelog)) print '
'.$moduleobj->getChangeLog().'
'; + else print ''.$langs->trans("ErrorFileNotFound", $pathtochangelog).''; + } + dol_fiche_end(); } else diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 371c4498da8..5c17723e4dd 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -489,6 +489,82 @@ class MyObject extends CommonObject return $this->deleteLineCommon($user, $idline, $notrigger); } + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->mymodule->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->mymodule->mymodule_advance->validate)))) + { + $this->error='Permission denied'; + 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->mymodule->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->mymodule->mymodule_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'BOM_CLOSE'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->mymodule->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->mymodule->mymodule_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) * diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 6af2312938b..c443641ffd6 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -129,7 +129,7 @@ if (empty($reshook)) $permissiontodelete = $user->rights->mymodule->delete || ($permissiontoadd && $object->status == 0); $backurlforlist = dol_buildpath('/mymodule/myobject_list.php', 1); if (empty($backtopage)) { - if (empty($id)) $backtopage = $backurlforlist; + if (empty($id) && $action != 'add' && $action != 'create') $backtopage = $backurlforlist; else $backtopage = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); } $triggermodname = 'MYMODULE_MYOBJECT_MODIFY'; // Name of trigger action code to execute when we modify record @@ -450,7 +450,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Clone if (! empty($user->rights->mymodule->write)) { - 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 ($action == 'edit') +{ + print '
'; + print ''; + print ''; + + print ''; + print ''; + + foreach($arrayofparameters as $key => $val) + { + print ''; + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print '
'; + + print '
'; + print ''; + print '
'; + + print '
'; + print '
'; +} +else +{ + if (! empty($arrayofparameters)) + { + print ''; + print ''; + + foreach($arrayofparameters as $key => $val) + { + print ''; + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print '' . $conf->global->$key . '
'; + + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + } + else + { + print '
'.$langs->trans("NothingToSetup"); + } +} + + +// Page end +dol_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php new file mode 100644 index 00000000000..a459a582bba --- /dev/null +++ b/htdocs/mrp/class/mo.class.php @@ -0,0 +1,746 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/mo.class.php + * \ingroup mrp + * \brief This file is a CRUD class file for Mo (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Mo + */ +class Mo extends CommonObject +{ + /** + * @var string ID to identify managed object + */ + public $element = 'mo'; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'mrp_mo'; + + /** + * @var int Does mo support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does mo support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for mo. Must be the part after the 'object_' into object_mo.png + */ + public $picto = 'mrp'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; // To produce + const STATUS_INPROGRESS = 2; + const STATUS_DONE = 3; + const STATUS_CANCELED = -1; + + + + /** + * 'type' if the field format ('integer', 'integer:Class:pathtoclass', 'varchar(x)', 'double(24,8)', 'text', 'html', 'datetime', 'timestamp', 'float') + * 'label' the translation key. + * 'enabled' is a condition when the field must be managed. + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'default' is a default value for creation (can still be replaced by the global setup of default values) + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'position' is the sort order of field. + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' is the CSS style to use on field. For example: 'maxwidth200' + * 'help' is a string visible as a tooltip on field + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id",), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>'1',), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>-1, 'position'=>20, 'notnull'=>1, 'default'=>'1', 'index'=>1,), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'showoncombobox'=>'1',), + 'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'index'=>1, 'comment'=>"Qty to produce",), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>1, 'visible'=>-1, 'position'=>50, 'notnull'=>-1, 'index'=>1), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>-1, 'position'=>61, 'notnull'=>-1,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>-1, 'position'=>62, 'notnull'=>-1,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>500, 'notnull'=>1,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'position'=>501, 'notnull'=>-1,), + 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'comment'=>"Product to produce",), + 'date_start_planned' => array('type'=>'datetime', 'label'=>'DateStartPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>55, 'notnull'=>-1, 'index'=>1, 'help'=>'KeepEmptyForAsap'), + 'date_end_planned' => array('type'=>'datetime', 'label'=>'DateEndPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>56, 'notnull'=>-1, 'index'=>1,), + 'fk_bom' => array('type'=>'integer:Bom:bom/class/bom.class.php', 'label'=>'BOM', 'enabled'=>1, 'visible'=>1, 'position'=>33, 'notnull'=>-1, 'index'=>1, 'comment'=>"Original BOM",), + 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php', 'label'=>'Project', 'enabled'=>1, 'visible'=>-1, 'position'=>52, 'notnull'=>-1, 'index'=>1,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>4, 'position'=>1000, 'default'=>0, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validated', '2'=>'InProgress', '3'=>'Done', '-1'=>'Canceled')), + ); + public $rowid; + public $ref; + public $entity; + public $label; + public $qty; + public $fk_soc; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + public $status; + public $fk_product; + public $date_start_planned; + public $date_end_planned; + public $fk_bom; + public $fk_project; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'mrp_moline'; + + /** + * @var int Field with ID of parent key if this field has a parent + */ + //public $fk_element = 'fk_mo'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Moline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables=array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + */ + //protected $childtablesoncascade=array('mrp_modet'); + + /** + * @var MoLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible']=0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled']=0; + + // Unset fields that are disabled + foreach($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + foreach($this->fields as $key => $val) + { + if (is_array($val['arrayofkeyval'])) + { + foreach($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2]=$langs->trans($val2); + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + return $this->createCommon($user, $notrigger); + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && ! empty($object->table_element_line)) $object->fetchLines(); + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + + // Clear fields + $object->ref = "copy_of_".$object->ref; + $object->title = $langs->trans("CopyOf")." ".$object->title; + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) + { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach($object->array_options as $key => $option) + { + $shortkey = preg_replace('/options_/', '', $key); + if (! empty($extrafields->attributes[$this->element]['unique'][$shortkey])) + { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (! $error) + { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) + { + $error++; + } + } + + if (! $error) + { + // copy external contacts if same company + if (property_exists($this, 'socid') && $this->socid == $object->socid) + { + if ($this->copy_linked_contact($object, 'external') < 0) + $error++; + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines=array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records=array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key=='t.rowid') { + $sqlwhere[] = $key . '='. $value; + } + elseif (strpos($key, 'date') !== false) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } + elseif ($key=='customsql') { + $sqlwhere[] = $value; + } + else { + $sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND (' . implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' ' . $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < min($limit, $num)) + { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) + { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (! empty($conf->dol_no_mouse_hover)) $notooltip=1; // Force disable tooltips + + $result = ''; + + $label = '' . $langs->trans("Mo") . ''; + $label.= '
'; + $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; + + $url = dol_buildpath('/mrp/mo_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1; + if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1'; + } + + $linkclose=''; + if (empty($notooltip)) + { + if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label=$langs->trans("ShowMo"); + $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose.=' class="classfortooltip'.($morecss?' '.$morecss:'').'"'; + } + else $linkclose = ($morecss?' class="'.$morecss.'"':''); + + $linkstart = ''; + $linkend=''; + + $result .= $linkstart; + if ($withpicto) $result.=img_object(($notooltip?'':$label), ($this->picto?$this->picto:'generic'), ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1); + if ($withpicto != 2) $result.= $this->ref; + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action,$hookmanager; + $hookmanager->initHooks(array('modao')); + $parameters=array('id'=>$this->id, 'getnomurl'=>$result); + $reshook=$hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $result = $hookmanager->resPrint; + else $result .= $hookmanager->resPrint; + + return $result; + } + + /** + * Return label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelstatus)) + { + global $langs; + //$langs->load("mrp"); + $this->labelstatus[self::STATUS_DRAFT] = $langs->trans('Draft'); + $this->labelstatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); + $this->labelstatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); + } + + if ($mode == 0) + { + return $this->labelstatus[$status]; + } + elseif ($mode == 1) + { + return $this->labelstatus[$status]; + } + elseif ($mode == 2) + { + return img_picto($this->labelstatus[$status], 'statut'.$status, '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; + } + elseif ($mode == 3) + { + return img_picto($this->labelstatus[$status], 'statut'.$status, '', false, 0, 0, '', 'valignmiddle'); + } + elseif ($mode == 4) + { + return img_picto($this->labelstatus[$status], 'statut'.$status, '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; + } + elseif ($mode == 5) + { + return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut'.$status, '', false, 0, 0, '', 'valignmiddle'); + } + elseif ($mode == 6) + { + return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut'.$status, '', false, 0, 0, '', 'valignmiddle'); + } + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql.= ' fk_user_creat, fk_user_modif'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql.= ' WHERE t.rowid = '.$id; + $result=$this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } + else + { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines=array(); + + $objectline = new MoLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_mo = '.$this->id)); + + if (is_numeric($result)) + { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } + else + { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf,$langs; + + $langs->load("mrp"); + + if (! dol_strlen($modele)) { + + $modele = 'standard'; + + if ($this->modelpdf) { + $modele = $this->modelpdf; + } elseif (! empty($conf->global->MO_ADDON_PDF)) { + $modele = $conf->global->MO_ADDON_PDF; + } + } + + $modelpath = "core/modules/mrp/doc/"; + + return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + //public function doScheduledJob($param1, $param2, ...) + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error=''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} + +/** + * Class MoLine. You can also remove this and generate a CRUD class for lines objects. + */ +class MoLine +{ + // To complete with content of an object MoLine + // We should have a field rowid, fk_mo and position +} diff --git a/htdocs/mrp/core/modules/modMrp.class.php b/htdocs/mrp/core/modules/modMrp.class.php new file mode 100644 index 00000000000..7e57f70c6c8 --- /dev/null +++ b/htdocs/mrp/core/modules/modMrp.class.php @@ -0,0 +1,349 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019 Frédéric France + * 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 . + */ + +/** + * \defgroup mrp Module Mrp + * \brief Mrp module descriptor. + * + * \file htdocs/mrp/core/modules/modMrp.class.php + * \ingroup mrp + * \brief Description and activation file for module Mrp + */ +include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php'; + +/** + * Description and activation class for module Mrp + */ +class modMrp extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs,$conf; + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 660; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'mrp'; + // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' + // It is used to group modules by family in module setup page + $this->family = "products"; + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '62'; + // Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); + // Module label (no space allowed), used if translation string 'ModuleMrpName' not found (Mrp is name of module). + $this->name = preg_replace('/^mod/i', '', get_class($this)); + // Module description, used if translation string 'ModuleMrpDesc' not found (Mrp is name of module). + $this->description = "MRPDescription"; + // Used only if file README.md and README-LL.md not found. + $this->descriptionlong = "Module to Manage Manufacturing Orders (MO)"; + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' + $this->version = 'dolibarr'; + // Url to the file with your last numberversion of this module + //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; + + // Key used in llx_const table to save module status enabled/disabled (where MRP is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + $this->picto='mrp'; + // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + // Set this to 1 if module has its own trigger directory (core/triggers) + 'triggers' => 0, + // Set this to 1 if module has its own login method file (core/login) + 'login' => 0, + // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 0, + // Set this to 1 if module has its own menus handler directory (core/menus) + 'menus' => 0, + // Set this to 1 if module overwrite template dir (core/tpl) + 'tpl' => 0, + // Set this to 1 if module has its own barcode directory (core/modules/barcode) + 'barcode' => 0, + // Set this to 1 if module has its own models directory (core/modules/xxx) + 'models' => 0, + // Set this to 1 if module has its own theme directory (theme) + 'theme' => 0, + // Set this to relative path of css file if module has its own css file + 'css' => array( + // '/mrp/css/mrp.css.php', + ), + // Set this to relative path of js file if module must load a js on all pages + 'js' => array( + // '/mrp/js/mrp.js.php', + ), + // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all' + 'hooks' => array( + // 'data' => array( + // 'hookcontext1', + // 'hookcontext2', + // ), + // 'entity' => '0', + ), + // Set this to 1 if features of module are opened to external users + 'moduleforexternal' => 0, + ); + // Data directories to create when module is enabled. + // Example: this->dirs = array("/mrp/temp","/mrp/subdir"); + $this->dirs = array("/mrp/temp"); + // Config pages. Put here list of php page, stored into mrp/admin directory, to use to setup module. + $this->config_page_url = array("setup.php@mrp"); + // Dependencies + // A condition to hide module + $this->hidden = false; + // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) + $this->depends = array('modBom'); + $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) + $this->langfiles = array("mrp"); + $this->phpmin = array(5,5); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(8,0); // Minimum version of Dolibarr required by module + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + //$this->automatic_activation = array('FR'=>'MrpWasAutomaticallyActivatedBecauseOfYourCountryChoice'); + //$this->always_enabled = true; // If true, can't be disabled + + // Constants + // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) + // Example: $this->const=array(1 => array('MRP_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1), + // 2 => array('MRP_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1) + // ); + $this->const = array( + // 1 => array('MRP_MYCONSTANT', 'chaine', 'avalue', 'This is a constant to add', 1, 'allentities', 1) + ); + + // Some keys to add into the overwriting translation tables + /*$this->overwrite_translation = array( + 'en_US:ParentCompany'=>'Parent company or reseller', + 'fr_FR:ParentCompany'=>'Maison mère ou revendeur' + )*/ + + if (! isset($conf->mrp) || ! isset($conf->mrp->enabled)) { + $conf->mrp=new stdClass(); + $conf->mrp->enabled=0; + } + + // Array to add new pages in new tabs + $this->tabs = array(); + // Example: + // $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@mrp:$user->rights->mrp->read:/mrp/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1 + // $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@mrp:$user->rights->othermodule->read:/mrp/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // $this->tabs[] = array('data'=>'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // + // Where objecttype can be + // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) + // 'contact' to add a tab in contact view + // 'contract' to add a tab in contract view + // 'group' to add a tab in group view + // 'intervention' to add a tab in intervention view + // 'invoice' to add a tab in customer invoice view + // 'invoice_supplier' to add a tab in supplier invoice view + // 'member' to add a tab in fundation member view + // 'opensurveypoll' to add a tab in opensurvey poll view + // 'order' to add a tab in customer order view + // 'order_supplier' to add a tab in supplier order view + // 'payment' to add a tab in payment view + // 'payment_supplier' to add a tab in supplier payment view + // 'product' to add a tab in product view + // 'propal' to add a tab in propal view + // 'project' to add a tab in project view + // 'stock' to add a tab in stock view + // 'thirdparty' to add a tab in third party view + // 'user' to add a tab in user view + + // Dictionaries + $this->dictionaries=array(); + /* Example: + $this->dictionaries=array( + 'langs'=>'mylangfile@mrp', + // List of tables we want to see into dictonnary editor + 'tabname'=>array(MAIN_DB_PREFIX."table1",MAIN_DB_PREFIX."table2",MAIN_DB_PREFIX."table3"), + // Label of tables + 'tablib'=>array("Table1","Table2","Table3"), + // Request to select fields + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), + // Sort order + 'tabsqlsort'=>array("label ASC","label ASC","label ASC"), + // List of fields (result of select to show dictionary) + 'tabfield'=>array("code,label","code,label","code,label"), + // List of fields (list of fields to edit a record) + 'tabfieldvalue'=>array("code,label","code,label","code,label"), + // List of fields (list of fields for insert) + 'tabfieldinsert'=>array("code,label","code,label","code,label"), + // Name of columns with primary key (try to always name it 'rowid') + 'tabrowid'=>array("rowid","rowid","rowid"), + // Condition to show each dictionary + 'tabcond'=>array($conf->mrp->enabled,$conf->mrp->enabled,$conf->mrp->enabled) + ); + */ + + // Boxes/Widgets + // Add here list of php file(s) stored in mrp/core/boxes that contains a class to show a widget. + $this->boxes = array( + // 0 => array( + // 'file' => 'mrpwidget1.php@mrp', + // 'note' => 'Widget provided by Mrp', + // 'enabledbydefaulton' => 'Home', + // ), + // ... + ); + + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week + $this->cronjobs = array( + // 0 => array( + // 'label' => 'MyJob label', + // 'jobtype' => 'method', + // 'class' => '/mrp/class/mo.class.php', + // 'objectname' => 'Mo', + // 'method' => 'doScheduledJob', + // 'parameters' => '', + // 'comment' => 'Comment', + // 'frequency' => 2, + // 'unitfrequency' => 3600, + // 'status' => 0, + // 'test' => '$conf->mrp->enabled', + // 'priority' => 50, + // ), + ); + // Example: $this->cronjobs=array( + // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->mrp->enabled', 'priority'=>50), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->mrp->enabled', 'priority'=>50) + // ); + + // Permissions provided by this module + $this->rights = array(); + $r=0; + // Add here entries to declare new permissions + /* BEGIN MODULEBUILDER PERMISSIONS */ + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Read objects of Mrp'; // Permission label + $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Create/Update objects of Mrp'; // Permission label + $this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Delete objects of Mrp'; // Permission label + $this->rights[$r][4] = 'delete'; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mrp->level1->level2) + $r++; + /* END MODULEBUILDER PERMISSIONS */ + + // Main menu entries to add + $this->menu = array(); + $r=0; + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + /* END MODULEBUILDER LEFTMENU MO */ + + // Exports profiles provided by this module + $r=1; + /* BEGIN MODULEBUILDER EXPORT MO */ + /* + $langs->load("mrp"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MoLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='mo@mrp'; + $keyforclass = 'Mo'; $keyforclassfile='/mymobule/class/mo.class.php'; $keyforelement='mo'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='mo'; $keyforaliasextra='extra'; $keyforelement='mo'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'mo as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('mo').')'; + $r++; */ + /* END MODULEBUILDER EXPORT MO */ + + // Imports profiles provided by this module + $r=1; + /* BEGIN MODULEBUILDER IMPORT MO */ + /* + $langs->load("mrp"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MoLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='mo@mrp'; + $keyforclass = 'Mo'; $keyforclassfile='/mymobule/class/mo.class.php'; $keyforelement='mo'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='mo'; $keyforaliasextra='extra'; $keyforelement='mo'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'mo as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('mo').')'; + $r++; */ + /* END MODULEBUILDER IMPORT MO */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + $result=$this->_load_tables('/mrp/sql/'); + if ($result < 0) return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + + // Create extrafields during init + //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + //$extrafields = new ExtraFields($this->db); + //$result1=$extrafields->addExtraField('myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'mrp', '$conf->mrp->enabled'); + //$result2=$extrafields->addExtraField('myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'mrp', '$conf->mrp->enabled'); + //$result3=$extrafields->addExtraField('myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'mrp', '$conf->mrp->enabled'); + //$result4=$extrafields->addExtraField('myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'mrp', '$conf->mrp->enabled'); + //$result5=$extrafields->addExtraField('myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'mrp', '$conf->mrp->enabled'); + + $sql = array(); + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/htdocs/mrp/index.php b/htdocs/mrp/index.php index f5f723a8fac..b6c20cde620 100644 --- a/htdocs/mrp/index.php +++ b/htdocs/mrp/index.php @@ -175,7 +175,7 @@ print '
'; */ $max=5; -$sql = "SELECT a.rowid, a.status, a.ref, a.tms as datem"; +$sql = "SELECT a.rowid, a.status, a.ref, a.tms as datem, a.status"; $sql.= " FROM ".MAIN_DB_PREFIX."bom_bom as a"; $sql.= " WHERE a.entity IN (".getEntity('bom').")"; $sql.= $db->order("a.tms", "DESC"); @@ -200,6 +200,7 @@ if ($resql) $staticbom->id=$obj->rowid; $staticbom->ref=$obj->ref; $staticbom->date_modification=$obj->datem; + $staticbom->status=$obj->status; print ''; print ''.$staticbom->getNomUrl(1, 32).''; diff --git a/htdocs/mrp/lib/mrp.lib.php b/htdocs/mrp/lib/mrp.lib.php new file mode 100644 index 00000000000..7ee1fcd04c7 --- /dev/null +++ b/htdocs/mrp/lib/mrp.lib.php @@ -0,0 +1,54 @@ + + * + * 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/lib/mrp.lib.php + * \ingroup mrp + * \brief Library files with common functions for Mrp + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function mrpAdminPrepareHead() +{ + global $langs, $conf; + + $langs->load("mrp"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/mrp/admin/setup.php", 1); + $head[$h][1] = $langs->trans("Settings"); + $head[$h][2] = 'settings'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@mrp:/mrp/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@mrp:/mrp/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'mrp'); + + return $head; +} diff --git a/htdocs/mrp/lib/mrp_mo.lib.php b/htdocs/mrp/lib/mrp_mo.lib.php new file mode 100644 index 00000000000..6189761269e --- /dev/null +++ b/htdocs/mrp/lib/mrp_mo.lib.php @@ -0,0 +1,83 @@ +. + */ + +/** + * \file lib/mrp_mo.lib.php + * \ingroup mrp + * \brief Library files with common functions for Mo + */ + +/** + * Prepare array of tabs for Mo + * + * @param Mo $object Mo + * @return array Array of tabs + */ +function moPrepareHead($object) +{ + global $db, $langs, $conf; + + $langs->load("mrp"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/mrp/mo_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) + { + $nbNote = 0; + if (!empty($object->note_private)) $nbNote++; + if (!empty($object->note_public)) $nbNote++; + $head[$h][0] = dol_buildpath('/mrp/mo_note.php', 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) $head[$h][1].= ' '.$nbNote.''; + $head[$h][2] = 'note'; + $h++; + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; + $upload_dir = $conf->mrp->dir_output . "/mo/" . dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); + $nbLinks=Link::count($db, $object->element, $object->id); + $head[$h][0] = dol_buildpath("/mrp/mo_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ' '.($nbFiles+$nbLinks).''; + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = dol_buildpath("/mrp/mo_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@mrp:/mrp/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@mrp:/mrp/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'mo@mrp'); + + return $head; +} diff --git a/htdocs/mrp/mo_agenda.php b/htdocs/mrp/mo_agenda.php new file mode 100644 index 00000000000..aab1ff10581 --- /dev/null +++ b/htdocs/mrp/mo_agenda.php @@ -0,0 +1,262 @@ + + * 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_agenda.php + * \ingroup mrp + * \brief Page of Mo events + */ + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include substr($tmp, 0, ($i+1))."/main.inc.php"; +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include "../main.inc.php"; +if (! $res && file_exists("../../main.inc.php")) $res=@include "../../main.inc.php"; +if (! $res && file_exists("../../../main.inc.php")) $res=@include "../../../main.inc.php"; +if (! $res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/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', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) +{ + $actioncode=GETPOST('actioncode', 'array', 3); + if (! count($actioncode)) $actioncode='0'; +} +else +{ + $actioncode=GETPOST("actioncode", "alpha", 3)?GETPOST("actioncode", "alpha", 3):(GETPOST("actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label=GETPOST('search_agenda_label'); + +// 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); + +$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 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortfield) $sortfield='a.datep,a.id'; +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('moagenda','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->id; + + + +/* + * Actions + */ + +$parameters=array('id'=>$socid); +$reshook=$hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Cancel + if (GETPOST('cancel', 'alpha') && ! empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers + { + $actioncode=''; + $search_agenda_label=''; + } +} + + + +/* + * View + */ + +$contactstatic = new Contact($db); + +$form = new Form($db); + +if ($object->id > 0) +{ + $title=$langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = ''; + llxHeader('', $title, $help_url); + + if (! empty($conf->notification->enabled)) $langs->load("mails"); + $head = moPrepareHead($object); + + + dol_fiche_head($head, 'agenda', $langs->trans("Mo"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref='
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mrp->creer) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + }*/ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
'; + + dol_fiche_end(); + + + + // Actions buttons + + $objthirdparty=$object; + $objcon=new stdClass(); + + $out='&origin='.$object->element.'&originid='.$object->id; + $permok=$user->rights->agenda->myactions->create; + if ((! empty($objthirdparty->id) || ! empty($objcon->id)) && $permok) + { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
'; + + if (! empty($conf->agenda->enabled)) + { + if (! empty($user->rights->agenda->myactions->create) || ! empty($user->rights->agenda->allactions->create)) + { + print ''.$langs->trans("AddAction").''; + } + else + { + print ''.$langs->trans("AddAction").''; + } + } + + print '
'; + + if (! empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read) )) + { + $param='&id='.$object->id.'&socid='.$socid; + if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); + if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit); + + + //print load_fiche_titre($langs->trans("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 '
'; + print ''; + print ''; + print ''; + + dol_fiche_head(array(), ''); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_add.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_add.tpl.php'; + + print '
'."\n"; + + dol_fiche_end(); + + print ' + + '; + + print '
'; + print ''; + print '  '; + print ''; // Cancel for create does not post form if we don't know the backtopage + print '
'; + + print '
'; +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') +{ + print load_fiche_titre($langs->trans("Mo"), '', 'cubes'); + + print '
'; + print ''; + print ''; + print ''; + print ''; + + dol_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_edit.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_edit.tpl.php'; + + print '
'; + + dol_fiche_end(); + + print '
'; + print '   '; + print '
'; + + print '
'; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals(); + + $head = 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='
'; + /* + // Ref bis + $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->mrp->creer, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->mrp->creer, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mrp->write) + { + if ($action != 'classify') + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=$proj->getNomUrl(); + } else { + $morehtmlref.=''; + } + } + } + */ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + print '
'; + print ''."\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + + print '
'; + print '
'; + print '
'; + + print '
'; + + dol_fiche_end(); + + + /* + * Lines + */ + + if (! empty($object->table_element_line)) + { + // Show object lines + $result = $object->getLinesArray(); + + print '
+ + + + + '; + + if (! empty($conf->use_javascript_ajax) && $object->status == 0) { + include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php'; + } + + print '
'; + if (! empty($object->lines) && $object->status == 0 && $permissiontoadd && $action != 'selectlines' && $action != 'editline') + { + print ''; + } + + if (! empty($object->lines)) + { + $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1); + } + + // Form to add new line + if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') + { + if ($action != 'editline') + { + // Add products/services form + $object->formAddObjectLine(1, $mysoc, $soc); + + $parameters = array(); + $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + } + } + + if (! empty($object->lines) && $object->status == 0 && $permissiontoadd && $action != 'selectlines' && $action != 'editline') + { + print '
'; + } + print '
'; + + print "
\n"; + } + + + // Buttons for actions + + if ($action != 'presend' && $action != 'editline') { + print '
'."\n"; + $parameters=array(); + $reshook=$hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + // Send + print '' . $langs->trans('SendMail') . ''."\n"; + + // Modify + if (! empty($user->rights->mrp->write)) + { + print ''.$langs->trans("Modify").''."\n"; + } + else + { + print ''.$langs->trans('Modify').''."\n"; + } + + // Clone + if (! empty($user->rights->mrp->write)) + { + print ''; + } + + /* + if ($user->rights->mrp->write) + { + if ($object->status == 1) + { + print ''.$langs->trans("Disable").''."\n"; + } + else + { + print ''.$langs->trans("Enable").''."\n"; + } + } + */ + + // Delete (need delete permission, or if draft, just need create/modify permission) + if (! empty($user->rights->mrp->delete) || (! empty($object->fields['status']) && $object->status == $object::STATUS_DRAFT && ! empty($user->rights->mrp->write))) + { + print ''.$langs->trans('Delete').''."\n"; + } + else + { + print ''.$langs->trans('Delete').''."\n"; + } + } + print '
'."\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 ''; + + // Total size + print ''; + + print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; + + 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 '
'; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/mrp/mo_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $user->rights->mrp->write); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'cubes', 0, $newcardbutton, '', $limit); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail="SendMoRef"; +$modelmail="mo"; +$objecttmp=new Mo($db); +$trackid='xxxx'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) +{ + foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); + print '
'.$langs->trans("FilterOnInto", $search_all) . join(', ', $fieldstosearchall).'
'; +} + +$moreforfilter = ''; +/*$moreforfilter.='
'; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
';*/ + +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; +else $moreforfilter = $hookmanager->resPrint; + +if (! empty($moreforfilter)) +{ + print '
'; + print $moreforfilter; + print '
'; +} + +$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; +$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields.=(count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + $cssforfield=(empty($val['css'])?'':$val['css']); + if ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center'; + elseif (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield.=($cssforfield?' ':'').'right'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + $cssforfield=(empty($val['css'])?'':$val['css']); + if ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center'; + elseif (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield.=($cssforfield?' ':'').'right'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield?'class="'.$cssforfield.'"':''), $sortfield, $sortorder, ($cssforfield?$cssforfield.' ':''))."\n"; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); +$reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine=0; +if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) +{ + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) + { + if (preg_match('/\$object/', $val)) $needToFetchEachLine++; // There is at least one compute field that use $object + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i=0; +$totalarray=array(); +while ($i < min($num, $limit)) +{ + $obj = $db->fetch_object($resql); + if (empty($obj)) break; // Should not happen + + // Store properties in $object + $object->id = $obj->rowid; + foreach($object->fields as $key => $val) + { + if (property_exists($obj, $key)) $object->$key = $obj->$key; + } + + // Show here line of result + print ''; + foreach($object->fields as $key => $val) + { + $cssforfield=(empty($val['css'])?'':$val['css']); + if (in_array($val['type'], array('date','datetime','timestamp'))) $cssforfield.=($cssforfield?' ':'').'center'; + elseif ($key == 'status') $cssforfield.=($cssforfield?' ':'').'center'; + + if (in_array($val['type'], array('timestamp'))) $cssforfield.=($cssforfield?' ':'').'nowrap'; + elseif ($key == 'ref') $cssforfield.=($cssforfield?' ':'').'nowrap'; + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'status') $cssforfield.=($cssforfield?' ':'').'right'; + + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if ($key == 'status') print $object->getLibStatut(5); + elseif (in_array($val['type'], array('date','datetime','timestamp'))) print $object->showOutputField($val, $key, $db->jdate($obj->$key), ''); + else print $object->showOutputField($val, $key, $obj->$key, ''); + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj); + $reshook=$hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print ''; + if (! $i) $totalarray['nbfield']++; + + print ''; + + $i++; +} + +// Show total line +if (isset($totalarray['pos'])) +{ + print ''; + $i=0; + while ($i < $totalarray['nbfield']) + { + $i++; + if (! empty($totalarray['pos'][$i])) print ''; + else + { + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + else print ''; + } + } + print ''; +} + +// If no record found +if ($num == 0) +{ + $colspan=1; + foreach($arrayfields as $key => $val) { if (! empty($val['checked'])) $colspan++; } + print ''; +} + + +$db->free($resql); + +$parameters=array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook=$hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; + if (is_array($val['arrayofkeyval'])) print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth75'); + else print ''; + print ''; +$searchpicto=$form->showFilterButtons(); +print $searchpicto; +print '
'; + if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + { + $selected=0; + if (in_array($obj->rowid, $arrayofselected)) $selected=1; + print ''; + } + print '
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").'
'.$langs->trans("NoRecordFound").'
'."\n"; +print '
'."\n"; + +print '
'."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) +{ + $hidegeneratedfilelistifempty=1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty=0; + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource=$_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource.=str_replace('&', '&', $param); + + $filedir=$diroutputmassaction; + $genallowed=$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='
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mrp->creer) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + }*/ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + + + $cssclass="titlefield"; + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
'; + + 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 '
'; @@ -321,7 +306,9 @@ print ''; print ''; print ''; -print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'products', 0, '', '', $limit); +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/bom/bom_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $user->rights->bom->write); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'products', 0, $newcardbutton, '', $limit); // Add code for pre mass action (confirmation or email presend form) $topicmail="Information"; @@ -330,7 +317,7 @@ $objecttmp=new Inventory($db); $trackid='inve'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; -if ($sall) +if ($search_all) { foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); print '
'.$langs->trans("FilterOnInto", $sall) . join(', ', $fieldstosearchall).'
'; @@ -415,13 +402,15 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; $parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); $reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch ')."\n"; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; print ''."\n"; // Detect if we need a fetch on each output line $needToFetchEachLine=0; -if (! 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 ''; - print $object->showOutputField($val, $key, $obj->$key, ''); + print ''; + if ($key == 'status') print $object->getLibStatut(5); + elseif (in_array($val['type'], array('date','datetime','timestamp'))) print $object->showOutputField($val, $key, $db->jdate($obj->$key), ''); + else print $object->showOutputField($val, $key, $obj->$key, ''); 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 ''; - print ''; - print ''; - print ''; - print ''; - - print_barre_liste($langs->trans("ListOfWarehouses"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $totalnboflines, 'generic', 0, $newcardbutton, '', $limit); - - if ($sall) - { - foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); - print '
'.$langs->trans("FilterOnInto", $sall) . join(', ', $fieldstosearchall).'
'; - } - - $moreforfilter=''; - - print '
'; - print ''."\n"; - - // Fields title search - print ''; - - print ''; - - print ''; - - print ''; - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; - - print ''; - - print ''; - - print ''; - - print ''; - print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "e.ref", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("LocationSummary", $_SERVER["PHP_SELF"], "e.lieu", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stockqty", '', $param, '', $sortfield, $sortorder, 'right '); - print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right '); - print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right '); - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; - print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "e.statut", '', $param, '', $sortfield, $sortorder, 'right '); - print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch '); - print "\n"; - - if ($num) - { - $warehouse=new Entrepot($db); - $var=false; - $totalarray=array(); - while ($i < min($num, $limit)) - { - $obj = $db->fetch_object($result); - - $warehouse->id = $obj->rowid; - $warehouse->ref = $obj->ref; - $warehouse->label = $obj->ref; - $warehouse->lieu = $obj->lieu; - $warehouse->fk_parent = $obj->fk_parent; - $warehouse->statut = $obj->statut; - - print ''; - print ''; - if (! $i) $totalarray['nbfield']++; - // Location - print ''; - if (! $i) $totalarray['nbfield']++; - - // Stock qty - print ''; - if (! $i) $totalarray['nbfield']++; - - // PMP value - print ''; - if (! $i) $totalarray['nbfield']++; - - // Selling value - print ''; - if (! $i) $totalarray['nbfield']++; - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - - // Status - print ''; - if (! $i) $totalarray['nbfield']++; - - print ''; - if (! $i) $totalarray['nbfield']++; - - print "\n"; - - - $i++; - } - - if ($totalnboflines-$offset <= $limit) - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - } - } - - $db->free($result); - - print "
'; - print ''; - print ''; - print ''; - print ''; - print ''; - print $form->selectarray('search_status', $warehouse->statuts, $search_status, 1, 0, 0, '', 1); - print ''; - $searchpicto=$form->showFilterAndCheckAddButtons(0); - print $searchpicto; - print '
' . $warehouse->getNomUrl(1) . ''.$obj->lieu.''.price2num($obj->stockqty, 5).''; - if (price2num($obj->estimatedvalue, 'MT')) print price(price2num($obj->estimatedvalue, 'MT'), 1); - else print ''; - print ''; - if (empty($conf->global->PRODUIT_MULTIPRICES)) print price(price2num($obj->sellvalue, 'MT'), 1); - else - { - $htmltext=$langs->trans("OptionMULTIPRICESIsOn"); - print $form->textwithtooltip($langs->trans("Variable"), $htmltext); - } - print ''.$warehouse->LibStatut($obj->statut, 5).'
'.$langs->trans("Total").''.price2num($totalStock, 5).''.price(price2num($total, 'MT'), 1, $langs, 0, 0, -1, $conf->currency).''; - if (empty($conf->global->PRODUIT_MULTIPRICES)) print price(price2num($totalsell, 'MT'), 1, $langs, 0, 0, -1, $conf->currency); - else - { - $htmltext=$langs->trans("OptionMULTIPRICESIsOn"); - print $form->textwithtooltip($langs->trans("Variable"), $htmltext); - } - print '
"; - 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 '
'; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('MenuNewWarehouse'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/stock/card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $user->rights->stock->creer); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'generic', 0, $newcardbutton, '', $limit); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail="Information"; +$modelmail="warehouse"; +$objecttmp=new Entrepot($db); +$trackid='ware'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + + +if ($search_all) +{ + foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); + print '
'.$langs->trans("FilterOnInto", $sall) . join(', ', $fieldstosearchall).'
'; +} + +$moreforfilter = ''; +/*$moreforfilter.='
'; + $moreforfilter.= $langs->trans('MyFilter') . ': '; + $moreforfilter.= '
';*/ + +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; +else $moreforfilter = $hookmanager->resPrint; + +if (! empty($moreforfilter)) +{ + print '
'; + print $moreforfilter; + print '
'; +} + +$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; +$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields.=(count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + +// Fields title search +// -------------------------------------------------------------------- +print ''; + +print ''; + +print ''; + +print ''; +print ''; +print ''; + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; +// Fields from hook +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +// Status +print ''; + +// Action column +print ''; +print ''."\n"; + +// Fields title label +// -------------------------------------------------------------------- +print ''; +print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "e.ref", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("LocationSummary", $_SERVER["PHP_SELF"], "e.lieu", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stockqty", '', $param, '', $sortfield, $sortorder, 'right '); +print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right '); +print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right '); +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters=array('arrayfields'=>$arrayfields,'param'=>$param,'sortfield'=>$sortfield,'sortorder'=>$sortorder); +$reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "e.statut", '', $param, '', $sortfield, $sortorder, 'right '); +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + +// Loop on record +// -------------------------------------------------------------------- +$i=0; +$totalarray=array(); +if ($num) +{ + $warehouse=new Entrepot($db); + + $totalarray=array(); + while ($i < min($num, $limit)) + { + $obj = $db->fetch_object($resql); + if (empty($obj)) break; // Should not happen + + $warehouse->id = $obj->rowid; + $warehouse->ref = $obj->ref; + $warehouse->label = $obj->ref; + $warehouse->lieu = $obj->lieu; + $warehouse->fk_parent = $obj->fk_parent; + $warehouse->statut = $obj->statut; + + // Show here line of result + print ''; + print ''; + if (! $i) $totalarray['nbfield']++; + // Location + print ''; + if (! $i) $totalarray['nbfield']++; + + // Stock qty + print ''; + if (! $i) $totalarray['nbfield']++; + + // PMP value + print ''; + if (! $i) $totalarray['nbfield']++; + + // Selling value + print ''; + if (! $i) $totalarray['nbfield']++; + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj); + $reshook=$hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Status + print ''; + if (! $i) $totalarray['nbfield']++; + + // Action column + print ''; + if (! $i) $totalarray['nbfield']++; + + print ''."\n"; + + + $i++; + } + + if ($totalnboflines-$offset <= $limit) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + } +} + +$db->free($resql); + +$parameters=array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook=$hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print $form->selectarray('search_status', $warehouse->statuts, $search_status, 1, 0, 0, '', 1); +print ''; +$searchpicto=$form->showFilterButtons(); +print $searchpicto; +print '
' . $warehouse->getNomUrl(1) . ''.$obj->lieu.''.price2num($obj->stockqty, 5).''; + if (price2num($obj->estimatedvalue, 'MT')) print price(price2num($obj->estimatedvalue, 'MT'), 1); + else print ''; + print ''; + if (empty($conf->global->PRODUIT_MULTIPRICES)) print price(price2num($obj->sellvalue, 'MT'), 1); + else + { + $htmltext=$langs->trans("OptionMULTIPRICESIsOn"); + print $form->textwithtooltip($langs->trans("Variable"), $htmltext); + } + print ''.$warehouse->LibStatut($obj->statut, 5).''; + if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + { + $selected=0; + if (in_array($obj->rowid, $arrayofselected)) $selected=1; + print ''; + } + print '
'.$langs->trans("Total").''.price2num($totalStock, 5).''.price(price2num($total, 'MT'), 1, $langs, 0, 0, -1, $conf->currency).''; + if (empty($conf->global->PRODUIT_MULTIPRICES)) print price(price2num($totalsell, 'MT'), 1, $langs, 0, 0, -1, $conf->currency); + else + { + $htmltext=$langs->trans("OptionMULTIPRICESIsOn"); + print $form->textwithtooltip($langs->trans("Variable"), $htmltext); + } + print '
'."\n"; +print '
'."\n"; + +print '
'."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) +{ + $hidegeneratedfilelistifempty=1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty=0; + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource=$_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource.=str_replace('&', '&', $param); + + $filedir=$diroutputmassaction; + $genallowed=$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 '' . $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 '' . $langs->trans("TransferStock") . ''; } else @@ -804,8 +804,8 @@ if (! $variants) { */ print '
'; + print ''; - print '
'; print ''; print ''; print ''; @@ -924,7 +924,8 @@ if (! $variants) { print ''; print ''; print ''; - print ''; + print ''; + print ''; } } } @@ -932,12 +933,13 @@ if (! $variants) { } } else dol_print_error($db); + // Total line print ''; print ''; print ''; -// Value purchase + // Value purchase print ''; @@ -945,12 +947,13 @@ if (! $variants) { if (empty($conf->global->PRODUIT_MULTIPRICES)) print ($total ? price($totalvaluesell / $total, 1) : ' '); else print $langs->trans("Variable"); print ''; -// Value to sell + // Value to sell print ''; print ""; + print "
' . $langs->trans("Warehouse") . '' . $langs->trans("NumberOfUnit") . '' . dol_print_date($pdluo->eatby, 'day') . '' . dol_print_date($pdluo->sellby, 'day') . '' . $pdluo->qty . ($pdluo->qty < 0 ? ' ' . img_warning() : '') . '
' . $langs->trans("Total") . ':' . price2num($total, 'MS') . ''; print ($totalwithpmp ? price(price2num($totalvalue / $totalwithpmp, 'MU')) : ' '); // This value may have rounding errors print ''; print $totalvalue ? price(price2num($totalvalue, 'MT'), 1) : ' '; print ''; if (empty($conf->global->PRODUIT_MULTIPRICES)) print price(price2num($totalvaluesell, 'MT'), 1); else print $langs->trans("Variable"); print '
"; print '
'; @@ -1073,6 +1076,7 @@ if (! $variants) { print ''; print ''.$langs->trans("Total").''; print ''.$stock_total.''; + print ''; print ''; } else diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 59d727c5027..9a5514ff1cc 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -293,8 +293,10 @@ $sql.= ", s.rowid as socid, s.nom as name, s.email"; $sql.= ", cls.code as opp_status_code"; // We'll need these fields in order to filter by categ if ($search_categ) $sql .= ", cs.fk_categorie, cs.fk_project"; -// Add fields for extrafields -foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ",ef.".$key.' as options_'.$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); // Note that $action and $object may have been modified by hook diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index 00ef201aa9f..e13b7092b26 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -271,7 +271,9 @@ if (! empty($arrayfields['t.tobill']['checked']) || ! empty($arrayfields['t.bill $sql.=" , SUM(tt.task_duration * ".$db->ifsql("invoice_id IS NULL", "1", "0").") as tobill, SUM(tt.task_duration * ".$db->ifsql("invoice_id IS NULL", "0", "1").") as billed"; } // 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/reception/list.php b/htdocs/reception/list.php index 65fdf153dd4..7978f7eaab3 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -427,7 +427,9 @@ $sql.= " typent.code as typent_code,"; $sql.= " state.code_departement as state_code, state.nom as state_name,"; $sql.= ' e.date_creation as date_creation, e.tms as date_update'; // 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/societe/card.php b/htdocs/societe/card.php index e2a8f731856..e855cb71b8c 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1293,9 +1293,9 @@ else } // Email / Web - print ''.$form->editfieldkey('EMail', 'email', '', $object, 0, 'string', '', $conf->global->SOCIETE_EMAIL_MANDATORY).''; + print ''.img_picto('', 'object_email').' '.$form->editfieldkey('EMail', 'email', '', $object, 0, 'string', '', $conf->global->SOCIETE_EMAIL_MANDATORY).''; print ''; - print ''.$form->editfieldkey('Web', 'url', '', $object, 0).''; + print ''.img_picto('', 'globe').' '.$form->editfieldkey('Web', 'url', '', $object, 0).''; print ''; if (! empty($conf->socialnetworks->enabled)) @@ -1335,9 +1335,9 @@ else } // Phone / Fax - print ''.$form->editfieldkey('Phone', 'phone', '', $object, 0).''; + print ''.img_picto('', 'object_phoning').' '.$form->editfieldkey('Phone', 'phone', '', $object, 0).''; print ''; - print ''.$form->editfieldkey('Fax', 'fax', '', $object, 0).''; + print ''.img_picto('', 'object_phoning_fax').' '.$form->editfieldkey('Fax', 'fax', '', $object, 0).''; print ''; // Prof ids @@ -1916,9 +1916,9 @@ else } // EMail / Web - print ''.$form->editfieldkey('EMail', 'email', '', $object, 0, 'string', '', (! empty($conf->global->SOCIETE_EMAIL_MANDATORY))).''; + print ''.img_picto('', 'object_email').' '.$form->editfieldkey('EMail', 'email', GETPOST('email', 'alpha'), $object, 0, 'string', '', (! empty($conf->global->SOCIETE_EMAIL_MANDATORY))).''; print ''; - print ''.$form->editfieldkey('Web', 'url', '', $object, 0).''; + print ''.img_picto('', 'globe').' '.$form->editfieldkey('Web', 'url', GETPOST('url', 'alpha'), $object, 0).''; print ''; if (! empty($conf->socialnetworks->enabled)) @@ -1950,9 +1950,9 @@ else } // Phone / Fax - print ''.$form->editfieldkey('Phone', 'phone', '', $object, 0).''; + print ''.img_picto('', 'object_phoning').' '.$form->editfieldkey('Phone', 'phone', GETPOST('phone', 'alpha'), $object, 0).''; print ''; - print ''.$form->editfieldkey('Fax', 'fax', '', $object, 0).''; + print ''.img_picto('', 'object_phoning_fax').' '.$form->editfieldkey('Fax', 'fax', GETPOST('fax', 'alpha'), $object, 0).''; print ''; // Prof ids @@ -2666,7 +2666,7 @@ else { print ''."\n"; } - + if (! empty($conf->adherent->enabled)) { $adh = new Adherent($db); diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index ed3b26e04ac..b5ae7d94c03 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -117,6 +117,7 @@ class Thirdparties extends DolibarrApi * @param int $mode Set to 1 to show only customers * Set to 2 to show only prospects * Set to 3 to show only those are not customer neither prospect + * Set to 4 to show only suppliers * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.nom:like:'TheCompany%') and (t.date_creation:<:'20160101')" * @return array Array of thirdparty objects */ @@ -143,6 +144,7 @@ class Thirdparties extends DolibarrApi if ($mode == 1) $sql.= " AND t.client IN (1, 3)"; if ($mode == 2) $sql.= " AND t.client IN (2, 3)"; if ($mode == 3) $sql.= " AND t.client IN (0)"; + if ($mode == 4) $sql.= " AND t.fournisseur IN (1)"; $sql.= ' AND t.entity IN ('.getEntity('societe').')'; if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; //if ($email != NULL) $sql.= " AND s.email = \"".$email."\""; diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index e29edb07717..7420c417aae 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -388,7 +388,9 @@ if ($search_sale) $sql .= ", sc.fk_soc, sc.fk_user"; if ($search_categ_cus) $sql .= ", cc.fk_categorie, cc.fk_soc"; if ($search_categ_sup) $sql .= ", cs.fk_categorie, cs.fk_soc"; // 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/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index f36013b289c..687d98911f2 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -250,7 +250,9 @@ $sql.= " p.rowid as project_id, p.ref as project_ref,"; if (! $user->rights->societe->client->voir && ! $socid) $sql .= " sc.fk_soc, sc.fk_user,"; $sql.= " u.firstname, u.lastname, u.photo, u.login"; // 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/theme/dolibarr_logo_squarred_alpha.png b/htdocs/theme/dolibarr_logo_squarred_alpha.png new file mode 100644 index 00000000000..06e69ad8b7b Binary files /dev/null and b/htdocs/theme/dolibarr_logo_squarred_alpha.png differ diff --git a/htdocs/theme/eldy/btn.inc.php b/htdocs/theme/eldy/btn.inc.php index c69ee57c17b..a3a952925e3 100644 --- a/htdocs/theme/eldy/btn.inc.php +++ b/htdocs/theme/eldy/btn.inc.php @@ -167,10 +167,9 @@ TITLE BUTTON .btnTitle, a.btnTitle { display: inline-block; - padding: 6px 12px; - font-size: 14px + padding: 4px 12px 4px 12px; font-weight: 400; - line-height: 1.4; + /* line-height: 1; */ text-align: center; white-space: nowrap; vertical-align: middle; @@ -192,6 +191,7 @@ TITLE BUTTON font-size: 12px; font-weight: 300; background-color: #fbfbfb; + border: 1px solid #fff; } .btnTitle > .btnTitle-icon{ @@ -203,12 +203,13 @@ TITLE BUTTON } .btnTitle:hover, a.btnTitle:hover { + border: 1px solid #bbb; border-radius: 3px; position: relative; margin: 0 0 0 10px; text-align: center; - color: #ffffff; - background-color: rgb(); + /* color: #ffffff; + background-color: rgb(); */ font-size: 12px; text-decoration: none; box-shadow: none; @@ -222,7 +223,7 @@ TITLE BUTTON } .btnTitle:hover .btnTitle-label{ - color: #ffffff; + /* color: #ffffff; */ } .btnTitle.refused .btnTitle-label, .btnTitle.refused:hover .btnTitle-label{ @@ -243,6 +244,15 @@ div.pagination li:first-child a.btnTitle{ color: #aaa; } +/* rule to reduce top menu - 2nd reduction: Reduce width of top menu icons again */ +@media only screen and (max-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2) ? round($nbtopmenuentries * 69, 0) + 130 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2; ?>px) /* reduction 2 */ +{ + .btnTitle, a.btnTitle { + display: inline-block; + padding: 4px 4px 4px 4px; + min-width: unset; + } +} global->MAIN_BUTTON_HIDE_UNAUTHORIZED) && (! $user->admin)) { ?> .butActionRefused, .butActionNewRefused, .btnTitle.refused { diff --git a/htdocs/theme/eldy/dropdown.inc.php b/htdocs/theme/eldy/dropdown.inc.php index 22ff1a87a22..30643b0076f 100644 --- a/htdocs/theme/eldy/dropdown.inc.php +++ b/htdocs/theme/eldy/dropdown.inc.php @@ -2,7 +2,7 @@ if (! defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> /*