diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index d5b0f864be6..de9d1677932 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -21,7 +21,9 @@ * \brief Page to activate/disable all modules */ -if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Disabled because this page is into a popup on module search page and we want to avoid to have an Anti CSRF token error (done if MAIN_SECURITY_CSRF_WITH_TOKEN is on) when we make a second search after closing popup. + require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 44370b40720..73e26de8aea 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -94,6 +94,7 @@ class BOM extends CommonObject 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'help'=>'ProductBOMHelp'), 'qty' => array('type'=>'real', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>1, 'default'=>1, 'position'=>55, 'notnull'=>1, 'isameasure'=>'1', 'css'=>'maxwidth75imp'), 'efficiency' => array('type'=>'real', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>-1, 'default'=>1, 'position'=>100, 'notnull'=>0, 'css'=>'maxwidth50imp', 'help'=>'ValueOfMeansLoss'), + 'duration' => array('type'=>'real', 'label'=>'EstimatedDuration', 'enabled'=>1, 'visible'=>-1, 'position'=>101, 'notnull'=>-1, 'css'=>'maxwidth50imp', 'help'=>'EstimatedDurationDesc'), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>-1, 'position'=>161, 'notnull'=>-1,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>-1, 'position'=>162, 'notnull'=>-1,), 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>300, 'notnull'=>1,), @@ -202,7 +203,7 @@ class BOM extends CommonObject */ public function create(User $user, $notrigger = false) { - if ($this->efficiency < 0 || $this->efficiency > 1) $this->efficiency = 1; + if ($this->efficiency <= 0 || $this->efficiency > 1) $this->efficiency = 1; return $this->createCommon($user, $notrigger); } @@ -412,7 +413,7 @@ class BOM extends CommonObject */ public function update(User $user, $notrigger = false) { - if ($this->efficiency < 0 || $this->efficiency > 1) $this->efficiency = 1; + if ($this->efficiency <= 0 || $this->efficiency > 1) $this->efficiency = 1; return $this->updateCommon($user, $notrigger); } diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index 4ca8b75af31..998f4a6c202 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -126,7 +126,7 @@ if (GETPOST('clearlist', 'int')) if (GETPOST('exportcsv', 'int')) { - $completefilename = 'targets_emailing'.$object->id.'_'.dol_print_date(dol_now(), 'dayhourlog').'csv'; + $completefilename = 'targets_emailing'.$object->id.'_'.dol_print_date(dol_now(), 'dayhourlog').'.csv'; header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=' . $completefilename); diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index a71860c01c1..18d153dc597 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2004-2019 Laurent Destailleur * Copyright (C) 2009-2012 Regis Houssin * Copyright (C) 2010-2011 Juanjo Menent * Copyright (C) 2012 Cedric Salvador @@ -1241,14 +1241,17 @@ class FactureRec extends CommonInvoice $result=''; $label = '' . $langs->trans("ShowInvoice") . ''; - if (! empty($this->ref)) + if (! empty($this->ref)) { $label .= '
'.$langs->trans('Ref') . ': ' . $this->ref; - if (! empty($this->date_last_gen)) + } + if ($this->frequency > 0) { + $label .= '
'.$langs->trans('Frequency') . ': ' . $langs->trans('FrequencyPer_'.$this->unit_frequency, $this->frequency); + } + if (! empty($this->date_last_gen)) { $label .= '
'.$langs->trans('DateLastGeneration') . ': ' . dol_print_date($this->date_last_gen, 'dayhour'); - if ($this->frequency > 0) - { - if (! empty($this->date_when)) - { + } + if ($this->frequency > 0) { + if (! empty($this->date_when)) { $label .= '
'.$langs->trans('NextDateToExecution') . ': '; $label .= (empty($this->suspended)?'':''). dol_print_date($this->date_when, 'day').(empty($this->suspended)?'':''); // No hour for this property if (! empty($this->suspended)) $label .= ' ('.$langs->trans("Disabled").')'; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index baaed787023..713c68c8e8a 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1233,7 +1233,7 @@ class Facture extends CommonInvoice */ public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $addlinktonotes = 0, $save_lastsearch_value = -1, $target = '') { - global $langs, $conf, $user; + global $langs, $conf, $user, $mysoc; if (! empty($conf->dol_no_mouse_hover)) $notooltip=1; // Force disable tooltips @@ -1276,11 +1276,11 @@ class Facture extends CommonInvoice if (! empty($this->total_ht)) $label.= '
' . $langs->trans('AmountHT') . ': ' . price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency); if (! empty($this->total_tva)) - $label.= '
' . $langs->trans('VAT') . ': ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency); + $label.= '
' . $langs->trans('AmountVAT') . ': ' . price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency); if (! empty($this->total_localtax1) && $this->total_localtax1 != 0) // We keep test != 0 because $this->total_localtax1 can be '0.00000000' - $label.= '
' . $langs->trans('LT1') . ': ' . price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency); + $label.= '
' . $langs->transcountry('AmountLT1', $mysoc->country_code) . ': ' . price($this->total_localtax1, 0, $langs, 0, -1, -1, $conf->currency); if (! empty($this->total_localtax2) && $this->total_localtax2 != 0) - $label.= '
' . $langs->trans('LT2') . ': ' . price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency); + $label.= '
' . $langs->transcountry('AmountLT2', $mysoc->country_code) . ': ' . price($this->total_localtax2, 0, $langs, 0, -1, -1, $conf->currency); if (! empty($this->total_ttc)) $label.= '
' . $langs->trans('AmountTTC') . ': ' . price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency); if ($moretitle) $label.=' - '.$moretitle; @@ -2136,7 +2136,7 @@ class Facture extends CommonInvoice if ($this->paye != 1) { $this->db->begin(); - + $now=dol_now(); dol_syslog(get_class($this)."::set_paid rowid=".$this->id, LOG_DEBUG); @@ -3557,7 +3557,7 @@ class Facture extends CommonInvoice $cluser->fetch($obj->fk_user_closing); $this->user_closing = $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); diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index 713d5e9554d..fb56ccb916f 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -154,7 +154,7 @@ if (empty($reshook)) // Create predefined invoice if ($action == 'add') { - if (! GETPOST('titre')) + if (! GETPOST('titre', 'nohtml')) { setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Title")), null, 'errors'); $action = "create"; @@ -162,15 +162,15 @@ if (empty($reshook)) } $frequency=GETPOST('frequency', 'int'); - $reyear=GETPOST('reyear'); - $remonth=GETPOST('remonth'); - $reday=GETPOST('reday'); - $rehour=GETPOST('rehour'); - $remin=GETPOST('remin'); + $reyear=GETPOST('reyear', 'int'); + $remonth=GETPOST('remonth', 'int'); + $reday=GETPOST('reday', 'int'); + $rehour=GETPOST('rehour', 'int'); + $remin=GETPOST('remin', 'int'); $nb_gen_max=GETPOST('nb_gen_max', 'int'); //if (empty($nb_gen_max)) $nb_gen_max =0; - if (GETPOST('frequency')) + if (GETPOST('frequency', 'int')) { if (empty($reyear) || empty($remonth) || empty($reday)) { @@ -188,12 +188,12 @@ if (empty($reshook)) if (! $error) { - $object->titre = GETPOST('titre', 'alpha'); // deprecated - $object->title = GETPOST('titre', 'alpha'); + $object->titre = GETPOST('titre', 'nohtml'); // deprecated + $object->title = GETPOST('titre', 'nohtml'); $object->note_private = GETPOST('note_private', 'none'); $object->note_public = GETPOST('note_public', 'none'); $object->modelpdf = GETPOST('modelpdf', 'alpha'); - $object->usenewprice = GETPOST('usenewprice'); + $object->usenewprice = GETPOST('usenewprice', 'alpha'); $object->frequency = $frequency; $object->unit_frequency = GETPOST('unit_frequency', 'alpha'); diff --git a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php index f9e3d4336f0..f6f854d9635 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php @@ -48,7 +48,7 @@ foreach($linkedObjectBlock as $key => $objectlink) ?> trans("RepeatableInvoice"); ?> - getNomUrl(1); ?> + getNomUrl(1); ?> date_when, 'day'); ?> error); } -print ''; +print '
'; print ''; print ''; print ''; print ''; - if (!empty($conf->multicurrency->enabled)) { - print ''; - } + //if (!empty($conf->multicurrency->enabled)) { + // print ''; + //} print ''; if ($conf->global->PRODUCT_USE_UNITS) print ''; print ''; @@ -1571,8 +1571,7 @@ else $objp = $db->fetch_object($result); - // - + // Line in view mode if ($action != 'editline' || GETPOST('rowid') != $objp->rowid) { print ''; @@ -1608,21 +1607,21 @@ else { print '\n"; } - // TVA + // VAT print ''; // Price print '\n"; // Price multicurrency - if (!empty($conf->multicurrency->enabled)) { + /*if (!empty($conf->multicurrency->enabled)) { print ''; - } - // Quantite + }*/ + // Quantity print ''; // Unit if($conf->global->PRODUCT_USE_UNITS) print ''; - // Remise + // Discount if ($objp->remise_percent > 0) { print '\n"; @@ -1711,7 +1710,7 @@ else print $line->showOptionals($extrafields, 'view', array('style'=>'class="oddeven"', 'colspan'=>$colspan), '', '', empty($conf->global->MAIN_EXTRAFIELDS_IN_ONE_TD)?0:1); } } - // Ligne en mode update + // Line in mode update else { // Ligne carac @@ -1741,18 +1740,34 @@ else $doleditor->Create(); print ''; + + // VAT print ''; + + // Price print ''; + + // Price multicurrency + /*if (!empty($conf->multicurrency->enabled)) { + print ''; + }*/ + + // Quantity print ''; + + // Unit if ($conf->global->PRODUCT_USE_UNITS) { print ''; } + + // Discount print ''; + if (! empty($usemargins)) { print ''; } // Duration - if ((string) $type == '1' && ! empty($arrayfields['p.duration']['checked'])) + if (! empty($arrayfields['p.duration']['checked'])) { print ''; @@ -748,7 +748,7 @@ if ($resql) if (! empty($arrayfields['p.barcode']['checked'])) { print_liste_field_titre($arrayfields['p.barcode']['label'], $_SERVER["PHP_SELF"], "p.barcode", "", $param, "", $sortfield, $sortorder); } - if ((string) $type == '1' && ! empty($arrayfields['p.duration']['checked'])) { + if (! empty($arrayfields['p.duration']['checked'])) { print_liste_field_titre($arrayfields['p.duration']['label'], $_SERVER["PHP_SELF"], "p.duration", "", $param, '', $sortfield, $sortorder, 'center '); } if (! empty($arrayfields['p.weight']['checked'])) print_liste_field_titre($arrayfields['p.weight']['label'], $_SERVER["PHP_SELF"], "p.weight", "", $param, '', $sortfield, $sortorder, 'center '); @@ -921,7 +921,7 @@ if ($resql) } // Duration - if ((string) $type == '1' && ! empty($arrayfields['p.duration']['checked'])) + if (! empty($arrayfields['p.duration']['checked'])) { print '
'.$langs->trans("NbOfInvoiceToWithdraw").''; @@ -161,6 +161,7 @@ print ''; if ($mesg) print $mesg; print "
\n"; + print '
'; print ''; if ($nb) { @@ -193,6 +194,7 @@ else } print "
\n"; + print "
\n"; print '
'; @@ -245,7 +247,7 @@ if ($resql) print_barre_liste($langs->trans("InvoiceWaitingWithdraw"), $page, $_SERVER['PHP_SELF'], $param, '', '', '', $num, $nbtotalofrecords, 'invoicing', 0, '', '', $limit); - print ''; + print '
'; print ''; print ''; print ''; @@ -299,7 +301,10 @@ if ($resql) $i++; } } - else print ''; + else + { + print ''; + } print "
'.$langs->trans("Invoice").''.$langs->trans("ThirdParty").'
'.$langs->trans("None").'
'.$langs->trans("None").'
"; print ""; print "
\n"; diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index bbefeb7eb4f..51f5e7382f6 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1559,9 +1559,9 @@ else print '
'.$langs->trans("ServiceNb", $cursorline).''.$langs->trans("VAT").''.$langs->trans("PriceUHT").''.$langs->trans("PriceUHTCurrency").''.$langs->trans("PriceUHTCurrency").''.$langs->trans("Qty").''.$langs->trans("Unit").''.$langs->trans("ReductionShort").'
'.img_object($langs->trans("ShowProductOrService"), ($objp->product_type ? 'service' : 'product')).' '.dol_htmlentitiesbr($objp->description)."'; print vatrate($objp->tva_tx.($objp->vat_src_code?(' ('.$objp->vat_src_code.')'):''), '%', $objp->info_bits); print ''.($objp->subprice != '' ? price($objp->subprice) : '')."'.price($objp->multicurrency_subprice).''.$objp->qty.''.$langs->trans($object->lines[$cursorline-1]->getLabelOfUnit()).''.$objp->remise_percent."%'; print $form->load_tva("eltva_tx", $objp->tva_tx.($objp->vat_src_code?(' ('.$objp->vat_src_code.')'):''), $mysoc, $object->thirdparty, $objp->fk_product, $objp->info_bits, $objp->product_type, 0, 1); print ''.price($objp->multicurrency_subprice).''; print $form->selectUnits($objp->fk_unit, "unit"); print '%'; @@ -2063,6 +2078,7 @@ else if ($action != 'editline') { $forcetoshowtitlelines=1; + if (empty($object->multicurrency_code)) $object->multicurrency_code = $conf->currency; // TODO Remove this when multicurrency supported on contracts // Add free products/services $object->formAddObjectLine(1, $mysoc, $soc); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 54fbb374b09..b9a4479367e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2579,8 +2579,7 @@ abstract class CommonObject public function updateRangOfLine($rowid, $rang) { $fieldposition = 'rang'; // @TODO Rename 'rang' into 'position' - if (in_array($this->table_element_line, array('ecm_files', 'emailcollector_emailcollectoraction'))) $fieldposition = 'position'; - if (in_array($this->table_element_line, array('bom_bomline'))) $fieldposition = 'position'; + if (in_array($this->table_element_line, array('bom_bomline', 'ecm_files', 'emailcollector_emailcollectoraction'))) $fieldposition = 'position'; $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.$rang; $sql.= ' WHERE rowid = '.$rowid; @@ -2886,11 +2885,11 @@ abstract class CommonObject $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_PROPOSAL"; elseif ($this->element == 'commande' || $this->element == 'order') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_ORDER"; - elseif ($this->element == 'facture') + elseif ($this->element == 'facture' || $this->element == 'invoice') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_INVOICE"; - elseif ($this->element == 'facture_fourn') + elseif ($this->element == 'facture_fourn' || $this->element == 'supplier_invoice') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_INVOICE"; - elseif ($this->element == 'order_supplier') + elseif ($this->element == 'order_supplier' || $this->element == 'supplier_order') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_ORDER"; elseif ($this->element == 'supplier_proposal') $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_PROPOSAL"; @@ -6278,18 +6277,12 @@ abstract class CommonObject $value=''; } } - elseif ($type == 'double') + elseif ($type == 'double' || $type == 'real') { if (!empty($value)) { $value=price($value); } } - elseif ($type == 'real') - { - if (!empty($value)) { - $value=price($value); - } - } elseif ($type == 'boolean') { $checked=''; @@ -7122,7 +7115,7 @@ abstract class CommonObject * Function test if type is array * * @param array $info content informations of field - * @return bool + * @return bool true if array */ protected function isArray($info) { @@ -7131,42 +7124,26 @@ abstract class CommonObject if(isset($info['type']) && $info['type']=='array') return true; else return false; } - else return false; - } - - /** - * Function test if type is null - * - * @param array $info content informations of field - * @return bool - */ - protected function isNull($info) - { - if(is_array($info)) - { - if(isset($info['type']) && $info['type']=='null') return true; - else return false; - } - else return false; + return false; } /** * Function test if type is date * * @param array $info content informations of field - * @return bool + * @return bool true if date */ public function isDate($info) { if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; - else return false; + return false; } /** * Function test if type is integer * * @param array $info content informations of field - * @return bool + * @return bool true if integer */ public function isInt($info) { @@ -7182,7 +7159,7 @@ abstract class CommonObject * Function test if type is float * * @param array $info content informations of field - * @return bool + * @return bool true if float */ public function isFloat($info) { @@ -7191,14 +7168,14 @@ abstract class CommonObject if (isset($info['type']) && (preg_match('/^(double|real|price)/i', $info['type']))) return true; else return false; } - else return false; + return false; } /** * Function test if type is text * * @param array $info content informations of field - * @return bool + * @return bool true if type text */ public function isText($info) { @@ -7207,7 +7184,39 @@ abstract class CommonObject if(isset($info['type']) && $info['type']=='text') return true; else return false; } - else return false; + return false; + } + + /** + * Function test if field can be null + * + * @param array $info content informations of field + * @return bool true if it can be null + */ + protected function canBeNull($info) + { + if(is_array($info)) + { + if(isset($info['notnull']) && $info['notnull']!='1') return true; + else return false; + } + return true; + } + + /** + * Function test if field is forced to null if zero or empty + * + * @param array $info content informations of field + * @return bool true if forced to null + */ + protected function isForcedToNullIfZero($info) + { + if(is_array($info)) + { + if(isset($info['notnull']) && $info['notnull']=='-1') return true; + else return false; + } + return false; } /** @@ -7223,7 +7232,7 @@ abstract class CommonObject if(isset($info['index']) && $info['index']==true) return true; else return false; } - else return false; + return false; } /** @@ -7316,17 +7325,30 @@ abstract class CommonObject elseif($this->isInt($info)) { if ($field == 'rowid') $this->id = (int) $obj->{$field}; - else $this->{$field} = (int) $obj->{$field}; + else + { + if ($this->isForcedToNullIfZero($info)) + { + if (empty($obj->{$field})) $this->{$field} = null; + else $this->{$field} = (double) $obj->{$field}; + } + else + { + $this->{$field} = (int) $obj->{$field}; + } + } } elseif($this->isFloat($info)) { - $this->{$field} = (double) $obj->{$field}; - } - elseif($this->isNull($info)) - { - $val = $obj->{$field}; - // zero is not null - $this->{$field} = (is_null($val) || (empty($val) && $val!==0 && $val!=='0') ? null : $val); + if ($this->isForcedToNullIfZero($info)) + { + if (empty($obj->{$field})) $this->{$field} = null; + else $this->{$field} = (double) $obj->{$field}; + } + else + { + $this->{$field} = (double) $obj->{$field}; + } } else { @@ -7383,7 +7405,8 @@ abstract class CommonObject if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now); 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) { diff --git a/htdocs/core/modules/modBom.class.php b/htdocs/core/modules/modBom.class.php index 9502c4c0af8..92cd956a260 100644 --- a/htdocs/core/modules/modBom.class.php +++ b/htdocs/core/modules/modBom.class.php @@ -54,14 +54,14 @@ class modBom extends DolibarrModules // 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 = '90'; + $this->module_position = '60'; // 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 'ModuleBomName' not found (Bom is name of module). $this->name = preg_replace('/^mod/i', '', get_class($this)); // Module description, used if translation string 'ModuleBomDesc' not found (Bom is name of module). - $this->description = "Bill of Materials (BOM) definitions for Manufacturing Resource Planning"; + $this->description = "Module to define your Bills Of Materials (BOM). Can be used for Manufacturing Resource Planning by the module Manufacturing Orders (MO)"; // Used only if file README.md and README-LL.md not found. $this->descriptionlong = "Bill of Materials definitions. They can be used to make Manufacturing Resource Planning"; @@ -75,7 +75,7 @@ class modBom extends DolibarrModules // 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='generic'; + $this->picto='bom'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( diff --git a/htdocs/core/modules/modVariants.class.php b/htdocs/core/modules/modVariants.class.php index 31e008b2870..728107ea08f 100644 --- a/htdocs/core/modules/modVariants.class.php +++ b/htdocs/core/modules/modVariants.class.php @@ -53,6 +53,8 @@ class modVariants extends DolibarrModules // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' // It is used to group modules in module setup page $this->family = "products"; + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '50'; // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) $this->name = preg_replace('/^mod/i', '', get_class($this)); // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) 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 73d283969a8..e631a3a1f71 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 @@ -49,6 +49,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; + create table llx_categorie_warehouse ( fk_categorie integer NOT NULL, diff --git a/htdocs/install/mysql/tables/llx_bom_bom.sql b/htdocs/install/mysql/tables/llx_bom_bom.sql index d66c3f9ffbf..d195dc4ec5d 100644 --- a/htdocs/install/mysql/tables/llx_bom_bom.sql +++ b/htdocs/install/mysql/tables/llx_bom_bom.sql @@ -26,6 +26,7 @@ CREATE TABLE llx_bom_bom( fk_product integer, qty double(24,8), efficiency double(8,4) DEFAULT 1, + duration double(8,4) DEFAULT NULL, date_creation datetime NOT NULL, date_valid datetime, tms timestamp, diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 29bb88a80a4..9d8e85f889d 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -1,6 +1,10 @@ +Mrp=Manufacturing Orders +MRPDescription=Module to manage Manufacturing Orders (MO). MRPArea=MRP Area +MrpSetupPage=Setup of module MO MenuBOM=Bills of material LatestBOMModified=Latest %s Bills of materials modified +Bom=Bills of Material BillOfMaterials=Bill of Material BOMsSetup=Setup of module BOM ListOfBOMs=List of bills of material - BOM @@ -21,4 +25,6 @@ NewMO=New Manufacturing Order QtyToProduce=Qty to produce DateStartPlannedMo=Date start planned DateEndPlannedMo=Date end planned -KeepEmptyForAsap=Empty means 'As Soon As Possible' \ No newline at end of file +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 diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 50b1347da6b..2b36582025f 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -171,7 +171,7 @@ $arrayfields=array( 'p.label'=>array('label'=>$langs->trans("Label"), 'checked'=>1), 'p.fk_product_type'=>array('label'=>$langs->trans("Type"), 'checked'=>0, 'enabled'=>(! empty($conf->product->enabled) && ! empty($conf->service->enabled))), 'p.barcode'=>array('label'=>$langs->trans("Gencod"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))), - 'p.duration'=>array('label'=>$langs->trans("Duration"), 'checked'=>($contextpage != 'productlist'), 'enabled'=>(! empty($conf->service->enabled))), + 'p.duration'=>array('label'=>$langs->trans("Duration"), 'checked'=>($contextpage != 'productlist'), 'enabled'=>(! empty($conf->service->enabled) && (string) $type == '1')), 'p.weight'=>array('label'=>$langs->trans("Weight"), 'checked'=>0, 'enabled'=>(! empty($conf->product->enabled))), 'p.length'=>array('label'=>$langs->trans("Length"), 'checked'=>0, 'enabled'=>(! empty($conf->product->enabled) && ! empty($conf->global->PRODUCT_DISABLE_SIZE))), 'p.surface'=>array('label'=>$langs->trans("Surface"), 'checked'=>0, 'enabled'=>(! empty($conf->product->enabled) && ! empty($conf->global->PRODUCT_DISABLE_SURFACE))), @@ -604,7 +604,7 @@ if ($resql) print ''; print ''; @@ -939,9 +939,9 @@ if ($resql) $dur=array("i"=>$langs->trans("Minute"),"h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year")); } print $duration_value; - print (! empty($duration_unit) && isset($dur[$duration_unit]) ? ' '.$langs->trans($dur[$duration_unit]) : ''); + print ((! empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); } - else + elseif (! preg_match('/^[a-z]$/i', $obj->duration)) // If duration is a simple char (like 's' of 'm'), we do not show value { print $obj->duration; } diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index ddbea5cd43b..2eb5a4d17e9 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -785,6 +785,9 @@ table[summary="list_of_modules"] .fa-cog { font-size: 1.5em; } +.linkedcol-element { + min-width: 100px; +} /* ============================================================================== */ /* Styles to hide objects */ @@ -865,6 +868,10 @@ table[summary="list_of_modules"] .fa-cog { .minwidth300imp { min-width: 300px !important; } .minwidth400imp { min-width: 300px !important; } .minwidth500imp { min-width: 300px !important; } + + .linkedcol-element { + min-width: unset; + } } /* Force values for small screen 1000 */ @@ -1101,8 +1108,8 @@ div.blockvmenulogo } .menulogocontainer { margin: px; - margin-left: 8px; - margin-right: 8px; + margin-left: 12px; + margin-right: 4px; padding: 0; height: px; /* width: 100px; */ diff --git a/htdocs/theme/eldy/img/object_mrp.png b/htdocs/theme/eldy/img/object_mrp.png new file mode 100644 index 00000000000..38b59646d71 Binary files /dev/null and b/htdocs/theme/eldy/img/object_mrp.png differ diff --git a/htdocs/theme/eldy/theme_vars.inc.php b/htdocs/theme/eldy/theme_vars.inc.php index 91b50b2a249..f0f74cc1e44 100644 --- a/htdocs/theme/eldy/theme_vars.inc.php +++ b/htdocs/theme/eldy/theme_vars.inc.php @@ -70,7 +70,7 @@ $colorbackbody='255,255,255'; $colortexttitlenotab='110,80,20'; $colortexttitle='0,0,0'; $colortext='0,0,0'; -$colortextlink='10, 20, 120'; +$colortextlink='10, 20, 110'; $fontsize='0.86em'; $fontsizesmaller='0.75em'; $topMenuFontSize='1.2em'; diff --git a/htdocs/theme/md/img/object_movement.png b/htdocs/theme/md/img/object_movement.png new file mode 100644 index 00000000000..aec344a3f8d Binary files /dev/null and b/htdocs/theme/md/img/object_movement.png differ diff --git a/htdocs/theme/md/img/object_mrp.png b/htdocs/theme/md/img/object_mrp.png new file mode 100644 index 00000000000..38b59646d71 Binary files /dev/null and b/htdocs/theme/md/img/object_mrp.png differ