diff --git a/ChangeLog b/ChangeLog index 76ec4faf452..00fbde60b91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,10 +24,10 @@ For users: --------------- NEW: Minimal PHP version is now PHP 7.0 instead of PHP 5.6 -NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link NEW: #20650 can move the checkbox column on left (experimental option MAIN_CHECKBOX_LEFT_COLUMN) NEW: #21000 Added columns 'alias_name' on project, supplier invoice, supplier order, supplier proposals and task list +NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #21395 Added option for dark theme mode in display - color and theme NEW: #21397 added option to auto define barcode numbers for third-parties in barcode module setup NEW: #21399 @@ -46,15 +46,11 @@ NEW: #22676 massaction for updating product prices NEW: #22735 Massaction to affect users on projects NEW: #25594 can chose if VAT ID is unique or not for third parties NEW: #4482 adding js to hide/show advanced option on the export data page + NEW: Add a constant to disallow modification of the product reference. -NEW: Add a method doAutoRenewContracts that can be used as a cron task. -NEW: Add " as enclosure by default for CSV export. Keep removing CR/LF. NEW: add attached file in presend email form of thirdparty card NEW: Add a way to enter LICENSE file content in property of website -NEW: add constant PROPAL_BYPASS_VALIDATED_STATUS NEW: Add employment anniversary in birthday box -NEW: Add fail2ban rules examples to limit access to /public pages -NEW: Add filter "Product subject to lot/Serial" in stock per lot/serial NEW: Add hidden option MAIN_EMAIL_SUPPORT_ACK to restore Email ack checkbox (feature abandonned by mailers) NEW: Add link to create an element from the category page NEW: Add max size send for "backup and link to mail" option @@ -63,43 +59,58 @@ NEW: Add more advices into the Setup security page NEW: Add new global variable for keeping the previous signature information on proposale (case of reopen a proposale) NEW: Add objectLink on expedition NEW: Add oldcopy to Ticket so triggers intercepting TICKET_MODIFY have access to old values of the updated properties -NEW: Add option FICHINTER_ALLOW_EXTERNAL_DOWNLOAD NEW: Add option --force on CLI cron_run_jobs.php NEW: Add option "Show price on the generated documents for receptions" -NEW: Add performance index (name for company and contact) and llx_bank_url(url_id) -NEW: Add picto property on sub-module for password generation +NEW: invoice export : add accounting affectation +NEW: label on products categories filter +NEW: manage no email with thirdparties (better for GDPR) +NEW: Manage VAT on all lines on purchases cycle +NEW: On a bank reconciled line, we can modify the bank receipt +NEW: parent company column and filter in invoice and order list +NEW: possibility to select scopes with checkbox for Oauth tokens +NEW: private and public note on user, thirdparty and contact list +NEW: Public counters feature +NEW: Saved token of OAUTH module are now encrypted into llx_oauth_token +NEW: Save one click to select on delivery ack, on emails. +NEW: scheduled job to send unpaid invoice reminder can now use the cc and bcc from email template +NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) +NEW: can substitue project title in mail template +NEW: The purge of files can purge only if older than a number of seconds +NEW: Update ActionComm type_code on email message ticket +NEW: Finance - VAT - Admin - Add information on deadline day for submission of VAT declaration +NEW: Add the target to select attendees of event for emailings NEW: add redirect on action confirm addconsumedline and addproduceline -NEW: Add a new advanced permission "read price" -NEW: Add substitution key __SENDEREMAIL_SIGNATURE__ NEW: Add the referrer-policy to "same-origin" by default on all public pages. -NEW: Add the SMTP header References on ticket email created by email NEW: Add trigger to record the event of sending an email from a project #20912 -NEW: Allow download link option in module configuration (propal,invoice,supplier proposal, order) -NEW: Can enter the unit price including the vat +NEW: Allow download link option in module configuration (propal, order, invoice, supplier proposal) +NEW: Can enter the unit price including the VAT NEW: Can invoice task time per different services -NEW: Can join several files by default on email form NEW: Can set a commercial discount by entering amount including VAT -NEW: Can set a monthly frequency (or multiple) in cron tasks. NEW: Can set start and end dates and comment on button "Activate all services" NEW: can sort and preselected best supplier price -NEW: Can use products categories to make inventory -NEW: Change filter type on tickets list into a multiselect combo NEW: show date delivery planned on orders linked to company and product -NEW: Encrypt all sensitive constants in llx_const NEW: filter on reception dates (from / to) in cheque paiement card + NEW: Accountancy - Add a graphic option to enable lettering function - FPC21 NEW: Accountancy - Add a way to clean some words when you generate thirdparty accounting account NEW: Accountancy - Added an option during export to export or not the lettering FPC21 NEW: Accountancy - Manage supplier deposit with specific account NEW: Accountancy - Model Digitaria - Add a way to clean some words when you generate thirdparty accounting account FPC22 +NEW: Agenda - start a simple support of recurrent events on agenda NEW: Bank - add salaries & VAT in tab planned entries -NEW: Contracts - Default template of contract is not mandatory +NEW: Contracts - add a method doAutoRenewContracts that can be used as a cron task +NEW: Contracts - default template of contract is not mandatory NEW: Contracts - Manage Position (Rank) on Contract Lines NEW: EMail - can copy/paste images into emails sent NEW: EMail - can edit label of an emailing even once sent +NEW: EMail - can join several files by default on email form NEW: EMail - can send an email on scheduled job error +NEW: EMail - on a form to send an email, we show all emails of all contacts of object +NEW: EMail - add the SMTP header References on ticket email created by email +NEW: EMail - add substitution key __SENDEREMAIL_SIGNATURE__ NEW: EMail-Collector - add IMAP port setting NEW: EMail-Collector - add a button "Test collect" +NEW: Export - Add " as enclosure by default for CSV export. Keep removing CR/LF. NEW: Event-Organization - add date event (!= date project) and location on event organization NEW: Extrafields - add badge in admin extrafields setup NEW: Extrafields - can edit property css, cssview, csslist on extrafields @@ -111,8 +122,10 @@ NEW: Invoice - Add french mention on pdf when vat debit option is on NEW: Members - default_lang for members NEW: Members - Table of membership types NEW: Members - add free membership amounts at the membership type level +NEW: Orders - resize parent company column in order list +NEW: Products supplier price - autofill default supplier VAT NEW: Projects - add author on list -NEW: Projects - add the thirdparty column to the time list (projet/tasks/time.php) +NEW: Projects - add thirdparty column to the time list (projet/tasks/time.php) NEW: Proposals - show delivery mode on PDF for proposals NEW: Proposals - skip accept/refuse process for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) NEW: Reception - add a from/to on search on date field @@ -120,64 +133,55 @@ NEW: Stock - page for mass stock transfer can be used with no source stock NEW: Stock - product categories filter on inventory list NEW: Stock - show product label on inventory NEW: Stock - manage virtual stock at a future date +NEW: Stock Inventory - add filter "Product subject to lot/Serial" in stock per lot/serial +NEW: Stock Inventory - can use products categories to make inventory +NEW: Supplier Order List - add column private and public note NEW: TakePOS - add margin infos to TakePOS invoice lines -NEW: TakePOS - display currency in TakePOS menu -NEW: TakePOS - Header Scroll in TakePOS NEW: TakePOS - add price to product box in TakePOS NEW: TakePOS - add setup parameters, can setup terminal name -NEW: TakePOS - support of Stripe Terminal with TakePOS -NEW: TakePOS - Receipt preview in TakePOS setup NEW: TakePOS - different product list on smartphone +NEW: TakePOS - display currency in TakePOS menu +NEW: TakePOS - Header Scroll in TakePOS +NEW: TakePOS - Receipt preview in TakePOS setup +NEW: TakePOS - support of Stripe Terminal with TakePOS NEW: Thirdparty - set thirdparty type with company modify trigger +NEW: Tickets - change filter type on tickets list into a multiselect combo NEW: Website - can delete a whole website if disabled NEW: Website - can remove a website template NEW: Website - can set header "Strict-Transport-Security" in web sites. NEW: Website - can switch status of website and page from the website toolbar NEW: Website - Templates of websites are now directories and not zip into core repo NEW: Website - add 4 other templates in website module -NEW: General - Bulk action to remove a category in list/search website pages -NEW: General - If we select another view list mode, we keep it -NEW: General - Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db -NEW: invoice export : add accounting affectation -NEW: label on products categories filter -NEW: The link "add to bookmark" is always on top in the bookmark popup -NEW: manage no email with thirdparties (better for GDPR) -NEW: Manage VAT on all lines on purchases cycle -NEW: On a bank reconciled line, we can modify the bank receipt -NEW: On a form to send an email, we show all emails of all contacts of object -NEW: parent company column and filter in invoice and order list -NEW: Add show "Sales rep" option for PDF -NEW: Picto for shared link is clickable -NEW: possibility to select scopes with checkbox for Oauth tokens -NEW: private and public note on user, thirdparty and contact list -NEW: Product supplier price: autofill default supplier VAT -NEW: Public counters feature -NEW: Start a simple support of recurrent events on agenda -NEW: Resize parent company column in order list -NEW: Saved token of OAUTH module are now encrypted into llx_oauth_token -NEW: Save one click to select on delivery ack, on emails. -NEW: scheduled job to send unpaid invoice reminder can now use the cc and bcc from email template -NEW: Show also scheduled task never finished in scheduled task widget -NEW: show badge with number of extrafields in setup -NEW: show category tree in sellist and chkbxlst for common object -NEW: Show picto and color into combo for selection of tags -NEW: show sell-by and eat-by dates only if not empty -NEW: show SellBy/EatBy dates for each batch product in shipment card -NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) -NEW: can substitue project title in mail template -NEW: Supplier order list - Add column private and public note -NEW: The purge of files can purge only if older than a number of seconds -NEW: Update ActionComm type_code on email message ticket -NEW: VAT - Admin - Add information on deadline day for submission of VAT declaration -NEW: expand/collapse permissions on user permission page -NEW: Add the target to select attendees of event for emailings + +General: +NEW: Actions: Bulk action to remove a category in list/search website pages +NEW: Cronjobs: can set a monthly frequency (or multiple) in cron tasks +NEW: Database: Encrypt all sensitive constants in llx_const +NEW: Database: Add performance index (name for company and contact) and llx_bank_url(url_id) +NEW: Database: Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db +NEW: GUI: If we select another view list mode, we keep it +NEW: GUI: the link "add to bookmark" is always on top in the bookmark popup +NEW: GUI: Picto for shared link is clickable +NEW: GUI: add picto property on sub-module for password generation +NEW: GUI: show also scheduled task never finished in scheduled task widget +NEW: GUI: show badge with number of extrafields in setup +NEW: GUI: show category tree in sellist and chkbxlst for common object +NEW: GUI: show picto and color into combo for selection of tags +NEW: GUI: show sell-by and eat-by dates only if not empty +NEW: GUI: show SellBy/EatBy dates for each batch product in shipment card +NEW: GUI/Permissions: expand/collapse permissions on user permission page +NEW: Permissions: add a new advanced permission "read price" +NEW: Print: add show "Sales rep" option for PDF +NEW: Security: add fail2ban rules examples to limit access to /public pages Option / Const for System: -NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS const to show category customer filter -NEW: PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing warehouse on PDF -NEW: PRODUIT_DESC_IN_FORM accept (desktop only or +smartphone) +NEW: FICHINTER_ALLOW_EXTERNAL_DOWNLOAD +NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS - const to show category customer filter +NEW: PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT - showing warehouse on PDF +NEW: PRODUIT_DESC_IN_FORM accept - desktop only or +smartphone +NEW: PROPAL_BYPASS_VALIDATED_STATUS NEW: PROPAL_NEW_AS_SIGNED -NEW: TIMESPENT_ALWAYS_UPDATE_THM, when it's on we always check current thm of user to update it in task time line +NEW: TIMESPENT_ALWAYS_UPDATE_THM - when it's on we always check current thm of user to update it in task time line Localisation: NEW: adding JAPAN Chart-of-Account and regions/departments @@ -207,7 +211,7 @@ NEW: support multilang in Civilities API Hooks: NEW: Actioncomm - add new hooks for actioncomm -NEW: Actioncomm - hook formConfirm on action comm card +NEW: Actioncomm - hook formConfirm on actioncomm card NEW: Agenda - hook on agenda pages NEW: Help - hook "changeHelpURL" to modify target of the help button NEW: Product - add hook to show virtual stock details on product stock card diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 217dfd63cc9..8c082d674db 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -48,6 +48,8 @@ $action = GETPOST('action', 'aZ09'); $provider = GETPOST('provider', 'aZ09'); $label = GETPOST('label', 'aZ09'); +$servicetoeditname = GETPOST('servicetoeditname', 'aZ09'); + $error = 0; @@ -72,15 +74,24 @@ if ($action == 'update') { foreach ($conf->global as $key => $val) { if (!empty($val) && preg_match('/^OAUTH_.+_ID$/', $key)) { $constvalue = str_replace('_ID', '', $key); - if (!dolibarr_set_const($db, $constvalue.'_ID', GETPOST($constvalue.'_ID'), 'chaine', 0, '', $conf->entity)) { - $error++; + $newconstvalue = $constvalue; + if (GETPOSTISSET($constvalue.'_NAME')) { + $newconstvalue = preg_replace('/-.*$/', '', $constvalue).'-'.GETPOST($constvalue.'_NAME'); + } + + if (GETPOSTISSET($constvalue.'_ID')) { + if (!dolibarr_set_const($db, $newconstvalue.'_ID', GETPOST($constvalue.'_ID'), 'chaine', 0, '', $conf->entity)) { + $error++; + } } // If we reset this provider, we also remove the secret - if (!dolibarr_set_const($db, $constvalue.'_SECRET', GETPOST($constvalue.'_ID') ? GETPOST($constvalue.'_SECRET') : '', 'chaine', 0, '', $conf->entity)) { - $error++; + if (GETPOSTISSET($constvalue.'_SECRET')) { + if (!dolibarr_set_const($db, $newconstvalue.'_SECRET', GETPOST($constvalue.'_ID') ? GETPOST($constvalue.'_SECRET') : '', 'chaine', 0, '', $conf->entity)) { + $error++; + } } if (GETPOSTISSET($constvalue.'_URLAUTHORIZE')) { - if (!dolibarr_set_const($db, $constvalue.'_URLAUTHORIZE', GETPOST($constvalue.'_URLAUTHORIZE'), 'chaine', 0, '', $conf->entity)) { + if (!dolibarr_set_const($db, $newconstvalue.'_URLAUTHORIZE', GETPOST($constvalue.'_URLAUTHORIZE'), 'chaine', 0, '', $conf->entity)) { $error++; } } @@ -90,14 +101,46 @@ if ($action == 'update') { } else { $scopestring = GETPOST($constvalue.'_SCOPE'); } - if (!dolibarr_set_const($db, $constvalue.'_SCOPE', $scopestring, 'chaine', 0, '', $conf->entity)) { + if (!dolibarr_set_const($db, $newconstvalue.'_SCOPE', $scopestring, 'chaine', 0, '', $conf->entity)) { $error++; } - } else { - if (!dolibarr_set_const($db, $constvalue.'_SCOPE', '', 'chaine', 0, '', $conf->entity)) { + } elseif ($newconstvalue !== $constvalue) { + if (!dolibarr_set_const($db, $newconstvalue.'_SCOPE', '', 'chaine', 0, '', $conf->entity)) { $error++; } } + + // If name changed, we have to delete old const and proceed few other changes + if ($constvalue !== $newconstvalue) { + dolibarr_del_const($db, $constvalue.'_ID', $conf->entity); + dolibarr_del_const($db, $constvalue.'_SECRET', $conf->entity); + dolibarr_del_const($db, $constvalue.'_URLAUTHORIZE', $conf->entity); + dolibarr_del_const($db, $constvalue.'_SCOPE', $conf->entity); + + // Update name of token + $oldname = preg_replace('/^OAUTH_/', '', $constvalue); + $oldprovider = ucfirst(strtolower(preg_replace('/-.*$/', '', $oldname))); + $oldlabel = preg_replace('/^.*-/', '', $oldname); + $newlabel = preg_replace('/^.*-/', '', $newconstvalue); + + + $sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token"; + $sql.= " SET service = '".$db->escape($oldprovider."-".$newlabel)."'"; + $sql.= " WHERE service = '".$db->escape($oldprovider."-".$oldlabel)."'"; + + + $resql = $db->query($sql); + if (!$resql) { + $error++; + } + + // Update const where the token was used, might not be exhaustive + if (getDolGlobalString('MAIN_MAIL_SMTPS_OAUTH_SERVICE') == $oldname) { + if (!dolibarr_set_const($db, 'MAIN_MAIL_SMTPS_OAUTH_SERVICE', strtoupper($oldprovider).'-'.$newlabel, 'chaine', 0, '', $conf->entity)) { + $error++; + } + } + } } } @@ -270,11 +313,16 @@ if (count($listinsetup) > 0) { } else { print $label; } - if ($keyforprovider) { + if ($servicetoeditname == $key[0]) { + print ' ()'; + } elseif ($keyforprovider) { print ' ('.$keyforprovider.')'; } else { print ' ('.$langs->trans("NoName").')'; } + if (!($servicetoeditname == $key[0])) { + print ''.img_edit($langs->transnoentitiesnoconv('Edit'), 1).''; + } print ''; print ''; if (!empty($supportedoauth2array[$keyforsupportedoauth2array]['urlforcredentials'])) { diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index e06cdeb0312..c79a3e63653 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -1682,6 +1682,68 @@ class Setup extends DolibarrApi return $list; } + /** + * Get the list of incoterms. + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Number of items per page + * @param int $page Page number (starting from zero) + * @param int $active Payment term is active or not {@min 0} {@max 1} + * @param string $lang Code of the language the label of the type must be translated to + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" + * @return array List of incoterm types + * + * @url GET dictionary/incoterms + * + * @throws RestException + */ + public function getListOfIncoterms($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '') + { + $list = array(); + + $sql = "SELECT rowid, code, active"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_incoterms as t"; + $sql .= " WHERE 1=1"; + + // Add sql filters + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + + $sql .= $this->db->order($sortfield, $sortorder); + + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit, $offset); + } + + $result = $this->db->query($sql); + + if ($result) { + $num = $this->db->num_rows($result); + $min = min($num, ($limit <= 0 ? $num : $limit)); + for ($i = 0; $i < $min; $i++) { + $type =$this->db->fetch_object($result); + $list[] = $type; + } + } else { + throw new RestException(503, 'Error when retrieving list of incoterm types : '.$this->db->lasterror()); + } + + return $list; + } + /** * Get properties of company * diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index 373effecbe8..56361b948f0 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -226,7 +226,7 @@ if ($action == 'builddoc') { 'code'=>$code, 'encoding'=>$encoding, 'is2d'=>$is2d, - 'photo'=>$barcodeimage // Photo must be a file that exists with format supported by TCPDF + 'photo'=>!empty($barcodeimage) ? $barcodeimage : '' // Photo must be a file that exists with format supported by TCPDF ); } } else { diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 333b6232f9f..fbced8e6773 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -358,11 +358,11 @@ if (empty($reshook)) { // Confirmation to delete if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), 'confirm_delete', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), '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); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); } // Confirmation of validation @@ -393,13 +393,13 @@ if (empty($reshook)) { $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), + // '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); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220); } // Confirmation of closing @@ -421,13 +421,13 @@ if (empty($reshook)) { $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), + // '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); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220); } // Confirmation of reopen @@ -444,26 +444,26 @@ if (empty($reshook)) { $formquestion = array(); if (isModEnabled('bom')) { $langs->load("mrp"); - require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; $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), + // '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); + $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 $formquestion = array(); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } // Confirmation of action xxxx @@ -471,7 +471,7 @@ if (empty($reshook)) { $text = $langs->trans('ConfirmSetToDraft', $object->ref); $formquestion = array(); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220); } // Call Hook formConfirm @@ -489,7 +489,7 @@ if (empty($reshook)) { // Object card // ------------------------------------------------------------ - $linkback = ''.$langs->trans("BackToList").''; + $linkback = '' . $langs->trans("BackToList") . ''; $morehtmlref = '
'; /* @@ -538,17 +538,17 @@ if (empty($reshook)) { print '
'; print '
'; print '
'; - print ''."\n"; + print '
' . "\n"; // Common attributes $keyforbreak = 'duration'; - include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; $object->calculateCosts(); - print ''; - print ''; + print ''; + print ''; // Other attributes - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; print '
'.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).''.price($object->total_cost).'
'.$langs->trans("UnitCost").''.price($object->unit_cost).'
' . $form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")) . '' . price($object->total_cost) . '
' . $langs->trans("UnitCost") . '' . price($object->unit_cost) . '
'; print '
'; @@ -559,7 +559,6 @@ if (empty($reshook)) { print dol_get_fiche_end(); - /* * Lines */ @@ -580,7 +579,7 @@ if (empty($reshook)) { '; if (!empty($conf->use_javascript_ajax) && $object->status == 0) { - include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php'; } print '
'; @@ -602,7 +601,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('formAddObjectLine', $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)) - $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); + $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); } } @@ -652,7 +651,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('formAddObjectServiceLine', $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)) - $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); + $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); } } } @@ -665,146 +664,146 @@ if (empty($reshook)) { print "\n"; mrpCollapseBomManagement(); - } - $res = $object->fetchLines(); + $res = $object->fetchLines(); - // Buttons for actions + // 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 - //if (empty($user->socid)) { - // print '' . $langs->trans('SendMail') . ''."\n"; - //} - - // Back to draft - if ($object->status == $object::STATUS_VALIDATED) { - if ($permissiontoadd) { - print ''.$langs->trans("SetToDraft").''."\n"; - } + 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'); } - // Modify - if ($object->status == $object::STATUS_DRAFT) { - if ($permissiontoadd) { - print ''.$langs->trans("Modify").''."\n"; - } else { - print ''.$langs->trans('Modify').''."\n"; - } - } + if (empty($reshook)) { + // Send + //if (empty($user->socid)) { + // print '' . $langs->trans('SendMail') . ''."\n"; + //} - // Validate - if ($object->status == $object::STATUS_DRAFT) { - if ($permissiontoadd) { - if (is_array($object->lines) && count($object->lines) > 0) { - print ''.$langs->trans("Validate").''."\n"; - } else { - $langs->load("errors"); - print ''.$langs->trans("Validate").''."\n"; + // Back to draft + if ($object->status == $object::STATUS_VALIDATED) { + if ($permissiontoadd) { + print '' . $langs->trans("SetToDraft") . '' . "\n"; } } - } - // Re-open - if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) { - print ''.$langs->trans("ReOpen").''."\n"; - } - - // Create MO - if (isModEnabled('mrp')) { - if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) { - print ''.$langs->trans("CreateMO").''."\n"; + // Modify + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { + print '' . $langs->trans("Modify") . '' . "\n"; + } else { + print '' . $langs->trans('Modify') . '' . "\n"; + } } - } - // Clone - if ($permissiontoadd) { - print dolGetButtonAction($langs->trans("ToClone"), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid) ? '&socid='.$object->socid : "").'&action=clone&object=bom', 'clone', $permissiontoadd); - } + // Validate + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { + if (is_array($object->lines) && count($object->lines) > 0) { + print '' . $langs->trans("Validate") . '' . "\n"; + } else { + $langs->load("errors"); + print '' . $langs->trans("Validate") . '' . "\n"; + } + } + } - // Close / Cancel - if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) { - print ''.$langs->trans("Disable").''."\n"; - } + // Re-open + if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) { + print '' . $langs->trans("ReOpen") . '' . "\n"; + } - /* - if ($user->rights->bom->write) - { - if ($object->status == 1) - { - print ''.$langs->trans("Disable").''."\n"; - } - else - { - print ''.$langs->trans("Enable").''."\n"; - } - } - */ + // Create MO + if (isModEnabled('mrp')) { + if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) { + print '' . $langs->trans("CreateMO") . '' . "\n"; + } + } - // Delete - print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete); + // Clone + if ($permissiontoadd) { + print dolGetButtonAction($langs->trans("ToClone"), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . (!empty($object->socid) ? '&socid=' . $object->socid : "") . '&action=clone&object=bom', 'clone', $permissiontoadd); + } + + // Close / Cancel + if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) { + print '' . $langs->trans("Disable") . '' . "\n"; + } + + /* + if ($user->rights->bom->write) + { + if ($object->status == 1) + { + print ''.$langs->trans("Disable").''."\n"; + } + else + { + print ''.$langs->trans("Enable").''."\n"; + } + } + */ + + // Delete + print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $permissiontodelete); + } + print '
' . "\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 = $objref . '/' . $objref . '.pdf'; + $filedir = $conf->bom->dir_output . '/' . $objref; + $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id; + $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content + $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card + print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); + + // Show links to link elements + $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + + + print '
'; + + $MAXEVENT = 10; + + $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT . '/bom/bom_agenda.php?id=' . $object->id); + + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlcenter); + + print '
'; + } + + //Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + // Presend form + $modelmail = 'bom'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->bom->dir_output; + $trackid = 'bom' . $object->id; + + include DOL_DOCUMENT_ROOT . '/core/tpl/card_presend.tpl.php'; } - - - // 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 = $objref.'/'.$objref.'.pdf'; - $filedir = $conf->bom->dir_output.'/'.$objref; - $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content - $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card - print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); - - // Show links to link elements - $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom')); - $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); - - - print '
'; - - $MAXEVENT = 10; - - $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/bom/bom_agenda.php?id='.$object->id); - - // List of actions on element - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; - $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlcenter); - - print '
'; - } - - //Select mail models is same action as presend - if (GETPOST('modelselected')) { - $action = 'presend'; - } - - // Presend form - $modelmail = 'bom'; - $defaulttopic = 'InformationMessage'; - $diroutput = $conf->bom->dir_output; - $trackid = 'bom'.$object->id; - - include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; } // End of page diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index e730243bfbf..9d84e205f2b 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -2048,7 +2048,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa } } if (!empty($contact_id) && $contact_id > 0) { - if (!is_object($cachecontacts[$contact_id])) { + if (empty($cachecontacts[$contact_id]) || !is_object($cachecontacts[$contact_id])) { $contact = new Contact($db); $contact->fetch($contact_id); $cachecontacts[$contact_id] = $contact; diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 67af97cfe12..b748cac3df4 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -65,7 +65,7 @@ $max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; $now = dol_now(); // Security check -$socid = GETPOST("socid", 'int'); +//$socid = GETPOST("socid", 'int'); if ($user->socid > 0) { $action = ''; $id = $user->socid; diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index dde6e3204d6..c39e4fbf834 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -675,7 +675,7 @@ if ($object->fetch($id) >= 0) { // Date last update print ''; - print dol_print_date($obj->tms, 'dayhour'); + print dol_print_date(dol_stringtotime($obj->tms), 'dayhour'); print ''; // Status of recipient sending email (Warning != status of emailing) diff --git a/htdocs/comm/mailing/index.php b/htdocs/comm/mailing/index.php index d3ebc379b55..cf3d18adbac 100644 --- a/htdocs/comm/mailing/index.php +++ b/htdocs/comm/mailing/index.php @@ -101,7 +101,7 @@ if (is_resource($handle)) { $qualified = 1; foreach ($mailmodule->require_module as $key) { - if (!$conf->$key->enabled || (!$user->admin && $mailmodule->require_admin)) { + if (empty($conf->$key->enabled) || (!$user->admin && $mailmodule->require_admin)) { $qualified = 0; //print "Les pr�requis d'activation du module mailing ne sont pas respect�s. Il ne sera pas actif"; break; @@ -176,7 +176,7 @@ if ($result) { print ''; print ''.$mailstatic->getNomUrl(1).''; - print ''.dol_trunc($obj->title, 38).''; + print ''.(!empty($obj->title) ? dol_trunc($obj->title, 38) : '').''; print ''.dol_print_date($db->jdate($obj->date_creat), 'day').''; print ''.($obj->nbemail ? $obj->nbemail : "0").''; print ''.$mailstatic->LibStatut($obj->statut, 5).''; diff --git a/htdocs/core/boxes/box_birthdays_members.php b/htdocs/core/boxes/box_birthdays_members.php index fc8dc4c6745..64a1f16e624 100644 --- a/htdocs/core/boxes/box_birthdays_members.php +++ b/htdocs/core/boxes/box_birthdays_members.php @@ -2,7 +2,7 @@ /* Copyright (C) 2003-2007 Rodolphe Quiedeville * Copyright (C) 2004-2010 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin - * Copyright (C) 2015-2019 Frederic France + * Copyright (C) 2015-2023 Frederic France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -115,7 +115,7 @@ class box_birthdays_members extends ModeleBoxes $this->info_box_contents[$line][] = array( 'td' => 'class="center nowraponall"', - 'text' => dol_print_date($dateb, "day", 'gmt').' - '.$age.' '.$langs->trans('DurationYears') + 'text' => dol_print_date($dateb, "day", 'tzserver').' - '.$age.' '.$langs->trans('DurationYears') ); /*$this->info_box_contents[$line][] = array( diff --git a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php index b75d0752334..5a6dbbedd37 100644 --- a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php +++ b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php @@ -120,7 +120,7 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes while ($i < $num) { $objp = $this->db->fetch_object($resql); while ($minimumdatecformated < $objp->datec) { - $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); + $dataseries[] = array('label' => dol_print_date($minimumdatec, 'day'), 'data' => 0); $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); } @@ -130,7 +130,7 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes $i++; } while (count($dataseries) < $days) { - $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); + $dataseries[] = array('label' => dol_print_date($minimumdatec, 'day'), 'data' => 0); $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); $i++; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index b998fcbd71a..88fefed035f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1397,6 +1397,7 @@ abstract class CommonObject $transkey = "TypeContact_".$obj->element."_".$obj->source."_".$obj->code; $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->libelle); $tab[$i] = array( + 'parentId' => $this->id, 'source' => $obj->source, 'socid' => $obj->socid, 'id' => $obj->id, diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index d55a398dbd6..1b7098d9cc5 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -288,6 +288,155 @@ class SupplierOrders extends DolibarrApi return false; } + /** + * Get contacts of given supplier order + * + * Return an array with contact informations + * + * @param int $id ID of supplier order + * @param string $source Source of the contact (internal, external, all). + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...) + * @return Object Object with cleaned properties + * + * @url GET {id}/contacts + * + * @throws RestException + */ + public function getContacts($id, $source, $type = '') + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->lire) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $contacts = array(); + + if ($source == 'all' || $source == 'external') { + $tmpContacts = $this->order->liste_contact(-1, 'external', 0, $type); + $contacts = array_merge($contacts, $tmpContacts); + } + + if ($source == 'all' || $source == 'internal') { + $tmpContacts = $this->order->liste_contact(-1, 'internal', 0, $type); + $contacts = array_merge($contacts, $tmpContacts); + } + + return $this->_cleanObjectDatas($contacts); + } + + /** + * Add a contact type of given supplier order + * + * @param int $id Id of supplier order to update + * @param int $contactid Id of contact/user to add + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...) + * @param string $source Source of the contact (external, internal) + * @return array + * + * @url POST {id}/contact/{contactid}/{type}/{source} + * + * @throws RestException 401 + * @throws RestException 404 + */ + public function postContact($id, $contactid, $type, $source) + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->creer) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->order->add_contact($contactid, $type, $source); + + if ($result < 0) { + throw new RestException(500, 'Error when added the contact'); + } + + if ($result == 0) { + throw new RestException(304, 'contact already added'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Contact linked to the order' + ) + ); + } + + /** + * Unlink a contact type of given supplier order + * + * @param int $id Id of supplier order to update + * @param int $contactid Id of contact/user to add + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...). + * @param string $source Source of the contact (internal, external). + * + * @url DELETE {id}/contact/{contactid}/{type}/{source} + * + * @return array + * + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function deleteContact($id, $contactid, $type, $source) + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->creer) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $contacts = $this->order->liste_contact(-1, $source, 0, $type); + + $contactToUnlink = 0; + foreach ($contacts as $contact) { + if ($contact['id'] == $contactid && $contact['code'] == $type) { + $contactToUnlink = $contact['rowid']; + break; + } + } + + if ($contactToUnlink == 0) { + throw new RestException(404, 'Linked contact not found'); + } + + $result = $this->order->delete_contact($contact['rowid']); + + if (!$result) { + throw new RestException(500, 'Error when deleted the contact'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Contact unlinked from supplier order' + ) + ); + } + /** * Delete supplier order * diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index c05ee005a0c..c8fc2814ad6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2008,15 +2008,93 @@ if ($action == 'create') { $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : ''); //$ref_client = (!empty($objectsrc->ref_client)?$object->ref_client:''); - $soc = $objectsrc->thirdparty; - $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_supplier_id) ? $soc->cond_reglement_supplier_id : 0)); // TODO maybe add default value option - $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_supplier_id) ? $soc->mode_reglement_supplier_id : 0)); - $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0)); - $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_supplier_percent) ? $soc->remise_supplier_percent : 0)); - $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0)); - $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : ''; - $transport_mode_id = (!empty($objectsrc->transport_mode_id) ? $objectsrc->transport_mode_id : (!empty($soc->transport_mode_id) ? $soc->transport_mode_id : 0)); + + $cond_reglement_id = 0; + $mode_reglement_id = 0; + $fk_account = 0; + $remise_percent = 0; + $remise_absolue = 0; + $transport_mode_id = 0; + + // set from object source + if (!empty($objectsrc->cond_reglement_id)) { + $cond_reglement_id = $objectsrc->cond_reglement_id; + } + if (!empty($objectsrc->mode_reglement_id)) { + $mode_reglement_id = $objectsrc->mode_reglement_id; + } + if (!empty($objectsrc->fk_account)) { + $fk_account = $objectsrc->fk_account; + } + if (!empty($objectsrc->remise_percent)) { + $remise_percent = $objectsrc->remise_percent; + } + if (!empty($objectsrc->remise_absolue)) { + $remise_absolue = $objectsrc->remise_absolue; + } + if (!empty($objectsrc->transport_mode_id)) { + $transport_mode_id = $objectsrc->transport_mode_id; + } + + if (empty($cond_reglement_id) + || empty($mode_reglement_id) + || empty($fk_account) + || empty($remise_percent) + || empty($remise_absolue) + || empty($transport_mode_id) + ) { + if ($origin == 'reception') { + // try to get from source of reception (supplier order) + if (!isset($objectsrc->supplier_order)) { + $objectsrc->fetch_origin(); + } + + if (!empty($objectsrc->commandeFournisseur)) { + $supplierOrder = $objectsrc->commandeFournisseur; + if (empty($cond_reglement_id) && !empty($supplierOrder->cond_reglement_id)) { + $cond_reglement_id = $supplierOrder->cond_reglement_id; + } + if (empty($mode_reglement_id) && !empty($supplierOrder->mode_reglement_id)) { + $mode_reglement_id = $supplierOrder->mode_reglement_id; + } + if (empty($fk_account) && !empty($supplierOrder->fk_account)) { + $fk_account = $supplierOrder->fk_account; + } + if (empty($remise_percent) && !empty($supplierOrder->remise_percent)) { + $remise_percent = $supplierOrder->remise_percent; + } + if (empty($remise_absolue) && !empty($supplierOrder->remise_absolue)) { + $remise_absolue = $supplierOrder->remise_absolue; + } + if (empty($transport_mode_id) && !empty($supplierOrder->transport_mode_id)) { + $transport_mode_id = $supplierOrder->transport_mode_id; + } + } + } + + // try to get from third-party of source object + if (!empty($soc)) { + if (empty($cond_reglement_id) && !empty($soc->cond_reglement_supplier_id)) { + $cond_reglement_id = $soc->cond_reglement_supplier_id; + } + if (empty($mode_reglement_id) && !empty($soc->mode_reglement_supplier_id)) { + $mode_reglement_id = $soc->mode_reglement_supplier_id; + } + if (empty($fk_account) && !empty($soc->fk_account)) { + $fk_account = $soc->fk_account; + } + if (empty($remise_percent) && !empty($soc->remise_supplier_percent)) { + $remise_percent = $soc->remise_supplier_percent; + } + if (empty($remise_absolue) && !empty($soc->remise_absolue)) { + $remise_absolue = $soc->remise_absolue; + } + if (empty($transport_mode_id) && !empty($soc->transport_mode_id)) { + $transport_mode_id = $soc->transport_mode_id; + } + } + } if (isModEnabled("multicurrency")) { if (!empty($objectsrc->multicurrency_code)) { @@ -2028,7 +2106,7 @@ if ($action == 'create') { } $datetmp = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : '') : $datetmp); + $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : '') : $datetmp); $datetmp = dol_mktime(12, 0, 0, GETPOST('echmonth', 'int'), GETPOST('echday', 'int'), GETPOST('echyear', 'int')); $datedue = ($datetmp == '' ?-1 : $datetmp); diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index b685147a9b9..caf2ff00b03 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -395,10 +395,10 @@ class Position extends CommonObject foreach ($filter as $key => $value) { if ($key == 't.rowid') { $sqlwhere[] = $key . '=' . $value; - } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; } elseif ($key == 'customsql') { $sqlwhere[] = $value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; } elseif (strpos($value, '%') === false) { $sqlwhere[] = $key . ' IN (' . $this->db->sanitize($this->db->escape($value)) . ')'; } else { diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index 6bc34977e4e..e03ea174ef7 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2009 Regis Houssin * Copyright (C) 2012 Marcos García - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2023 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -128,6 +128,7 @@ class MailmanSpip { global $conf; + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; //Patterns that are going to be replaced with their original value $patterns = array( '%LISTE%', @@ -139,7 +140,7 @@ class MailmanSpip $list, $object->email, $object->pass, - $conf->global->ADHERENT_MAILMAN_ADMIN_PASSWORD + getDolGlobalString('ADHERENT_MAILMAN_ADMIN_PASSWORD') ); $curl_url = str_replace($patterns, $replace, $url); diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index b8810a2696d..0d2137928ac 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -3739,7 +3739,7 @@ if ($module == 'initmodule') { print ''; print ''; - print dol_escape_htmltag($menu['leftmenu']); + print !empty($menu['leftmenu']) ? dol_escape_htmltag($menu['leftmenu']) : ''; print ''; print ''; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 9544e9c25ef..c988da72b3f 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -874,6 +874,7 @@ class MyObject extends CommonObject */ public function getKanbanView($option = '', $arraydata = null) { + global $conf, $langs; $return = '
'; $return .= '
'; $return .= ''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 82e3f096e5d..d464871941a 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6303,6 +6303,59 @@ class Product extends CommonObject return $prodDurationHours; } + + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs,$conf; + + $return = '
'; + $return .= '
'; + $return .= '
'; + $label = ''; + if ($this->is_photo_available($conf->product->multidir_output[$this->entity])) { + $label .= $this->show_photos('product', $conf->product->multidir_output[$this->entity]); + $return .= $label; + } else { + if ($this->type == Product::TYPE_PRODUCT) { + $label .= img_picto('', 'product'); + } elseif ($this->type == Product::TYPE_SERVICE) { + $label .= img_picto('', 'service'); + } + $return .= $label; + } + $return .= '
'; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'label')) { + $return .= '
'.$this->label.''; + } + if (property_exists($this, 'price') && property_exists($this, 'price_ttc')) { + if ($this->price_base_type == 'TTC') { + $return .= '
'.price($this->price_ttc).' '.$langs->trans("TTC").''; + } else { + if ($this->status) { + $return .= '
'.price($this->price).' '.$langs->trans("HT").''; + } + } + } + if (property_exists($this, 'stock_reel')) { + $return .= '
'.$langs->trans('PhysicalStock').' : '.$this->stock_reel.''; + } + if (method_exists($this, 'getLibStatut')) { + $return .='
'.$this->getLibStatut(5, 1).' '.$this->getLibStatut(5, 0).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } /** diff --git a/htdocs/product/list.php b/htdocs/product/list.php index f98f4da1ad5..f9a353b81b0 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -97,6 +97,8 @@ $search_accountancy_code_buy_export = GETPOST("search_accountancy_code_buy_expor $search_finished = GETPOST("search_finished", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); $type = GETPOST("type", "int"); +$mode = GETPOST('mode', 'alpha'); + //Show/hide child products if (isModEnabled('variants') && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { @@ -672,6 +674,9 @@ if (GETPOST('delprod')) { } $param = ''; +if (!empty($mode)) { + $param = "&mode=".urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -781,6 +786,9 @@ if (in_array($massaction, array('presend', 'predelete','preaffecttag', 'edit_ext $massactionbutton = $form->selectMassAction('', $arrayofmassactions); $newcardbutton = ''; +$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition')); +$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); + if ($type === "") { $perm = ($user->rights->produit->creer || $user->rights->service->creer); } elseif ($type == Product::TYPE_SERVICE) { @@ -788,8 +796,8 @@ if ($type === "") { } elseif ($type == Product::TYPE_PRODUCT) { $perm = $user->rights->produit->creer; } -$oldtype = $type; -$params = array(); + $oldtype = $type; + $params = array(); if ($type === "") { $params['forcenohideoftext'] = 1; } @@ -797,13 +805,12 @@ if ($type === "") { $newcardbutton .= dolGetButtonTitle($langs->trans('NewProduct'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params); $type = Product::TYPE_SERVICE; } -$label = 'NewProduct'; + $label = 'NewProduct'; if ($type == Product::TYPE_SERVICE) { $label = 'NewService'; } -$newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type='.$type, '', $perm, $params); + $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type='.$type, '', $perm, $params); -$type = $oldtype; print '
'; if ($optioncss != '') { @@ -816,6 +823,8 @@ print ''; print ''; //print ''; print ''; +print ''; + if (empty($arrayfields['p.fk_product_type']['checked'])) { print ''; } @@ -1321,13 +1330,15 @@ if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print "\n"; + $product_static = new Product($db); $product_fourn = new ProductFournisseur($db); $i = 0; $totalarray = array(); $totalarray['nbfield'] = 0; -while ($i < min($num, $limit)) { +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); // Multilangs @@ -1346,6 +1357,7 @@ while ($i < min($num, $limit)) { } } } + $parameters = array('staticdata' => $obj); // Note that $action and $object may have been modified by hook // do product_static fetch in hook if wanted or anything else @@ -1397,595 +1409,614 @@ while ($i < min($num, $limit)) { } } + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'lire'); if ($product_static->isService()) { $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); } + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + $product_static->price = $obj->price; + // Output Kanban + print $product_static->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + print '
'; + print ''; + } + } else { + print ''; - print ''; - - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - 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; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + 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 ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Ref - if (!empty($arrayfields['p.rowid']['checked'])) { - print ''; - print $product_static->id; - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref - if (!empty($arrayfields['p.ref']['checked'])) { - print ''; - print $product_static->getNomUrl(1); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref supplier - if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { - print ''; - print $product_static->getNomUrl(1); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Thumbnail - if (!empty($arrayfields['thumbnail']['checked'])) { - $product_thumbnail_html = ''; - if (!empty($product_static->entity)) { - $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); - if ($product_static->nbphoto > 0) { - $product_thumbnail_html = $product_thumbnail; + // Ref + if (!empty($arrayfields['p.rowid']['checked'])) { + print ''; + print $product_static->id; + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } } - print '' . $product_thumbnail_html . ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['p.label']['checked'])) { - print ''.$product_static->label.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['p.fk_product_type']['checked'])) { - print ''; - $s = ''; - if ($product_static->type == 0) { - $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); - } else { - $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); - } - print $s; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Barcode - if (!empty($arrayfields['p.barcode']['checked'])) { - print ''.$product_static->barcode.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Duration - if (!empty($arrayfields['p.duration']['checked'])) { - print ''; - - if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { - $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); - $duration_unit = substr($obj->duration, -1); - - if ((float) $duration_value > 1) { - $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); - } elseif ((float) $duration_value > 0) { - $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")); + // Ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + print $product_static->getNomUrl(1); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } - print $duration_value; - print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); - } 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; } - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Ref supplier + if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { + print ''; + print $product_static->getNomUrl(1); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Finished - if (!empty($arrayfields['p.finished']['checked'])) { - print ''; - print $product_static->getLibFinished(); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } + // Thumbnail + if (!empty($arrayfields['thumbnail']['checked'])) { + $product_thumbnail_html = ''; + if (!empty($product_static->entity)) { + $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); + if ($product_static->nbphoto > 0) { + $product_thumbnail_html = $product_thumbnail; + } + } - // Weight - if (!empty($arrayfields['p.weight']['checked'])) { - print ''; - print $product_static->weight; - print ''; - if (!$i) { - $totalarray['nbfield']++; + print '' . $product_thumbnail_html . ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Weight units - if (!empty($arrayfields['p.weight_units']['checked'])) { - print ''; - if ($product_static->weight != '') { - print measuringUnitString(0, 'weight', $product_static->weight_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length - if (!empty($arrayfields['p.length']['checked'])) { - print ''; - print $product_static->length; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length units - if (!empty($arrayfields['p.length_units']['checked'])) { - print ''; - if ($product_static->length != '') { - print measuringUnitString(0, 'size', $product_static->length_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width - if (!empty($arrayfields['p.width']['checked'])) { - print ''; - print $product_static->width; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width units - if (!empty($arrayfields['p.width_units']['checked'])) { - print ''; - if ($product_static->width != '') { - print measuringUnitString(0, 'size', $product_static->width_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height - if (!empty($arrayfields['p.height']['checked'])) { - print ''; - print $product_static->height; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height units - if (!empty($arrayfields['p.height_units']['checked'])) { - print ''; - if ($product_static->height != '') { - print measuringUnitString(0, 'size', $product_static->height_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface - if (!empty($arrayfields['p.surface']['checked'])) { - print ''; - print $product_static->surface; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface units - if (!empty($arrayfields['p.surface_units']['checked'])) { - print ''; - if ($product_static->surface != '') { - print measuringUnitString(0, 'surface', $product_static->surface_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume - if (!empty($arrayfields['p.volume']['checked'])) { - print ''; - print $product_static->volume; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume units - if (!empty($arrayfields['p.volume_units']['checked'])) { - print ''; - if ($product_static->volume != '') { - print measuringUnitString(0, 'volume', $product_static->volume_units); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Unit - if (!empty($arrayfields['cu.label']['checked'])) { - print ''; - if (!empty($obj->cu_label)) { - print $langs->trans($obj->cu_label); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Sell price - if (!empty($arrayfields['p.sellprice']['checked'])) { - print ''; - if ($product_static->status && $usercancreadprice) { - if ($obj->price_base_type == 'TTC') { - print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; + // Label + if (!empty($arrayfields['p.label']['checked'])) { + print ''.$product_static->label.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if (!empty($arrayfields['p.fk_product_type']['checked'])) { + print ''; + $s = ''; + if ($product_static->type == 0) { + $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); } else { - print ''.price($obj->price).' '.$langs->trans("HT").''; + $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); + } + print $s; + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Multiprices - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - if (! isset($productpricescache)) { - $productpricescache=array(); - } - if (! isset($productpricescache[$obj->rowid])) { - $productpricescache[$obj->rowid] = array(); + // Barcode + if (!empty($arrayfields['p.barcode']['checked'])) { + print ''.$product_static->barcode.''; + if (!$i) { + $totalarray['nbfield']++; + } } - if ($product_static->status && $usercancreadprice) { - // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array - // then reuse the cache array if we need prices for other price levels - $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; - $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; - $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); - $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; - $resultp = $db->query($sqlp); - if ($resultp) { - $nump = $db->num_rows($resultp); - $j = 0; - while ($j < $nump) { - $objp = $db->fetch_object($resultp); + // Duration + if (!empty($arrayfields['p.duration']['checked'])) { + print ''; - if (empty($productpricescache[$obj->rowid][$objp->price_level])) { - $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; - $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; - $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { + $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); + $duration_unit = substr($obj->duration, -1); + + if ((float) $duration_value > 1) { + $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); + } elseif ((float) $duration_value > 0) { + $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]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); + } 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; + } + + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Finished + if (!empty($arrayfields['p.finished']['checked'])) { + print ''; + print $product_static->getLibFinished(); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Weight + if (!empty($arrayfields['p.weight']['checked'])) { + print ''; + print $product_static->weight; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Weight units + if (!empty($arrayfields['p.weight_units']['checked'])) { + print ''; + if ($product_static->weight != '') { + print measuringUnitString(0, 'weight', $product_static->weight_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length + if (!empty($arrayfields['p.length']['checked'])) { + print ''; + print $product_static->length; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length units + if (!empty($arrayfields['p.length_units']['checked'])) { + print ''; + if ($product_static->length != '') { + print measuringUnitString(0, 'size', $product_static->length_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width + if (!empty($arrayfields['p.width']['checked'])) { + print ''; + print $product_static->width; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width units + if (!empty($arrayfields['p.width_units']['checked'])) { + print ''; + if ($product_static->width != '') { + print measuringUnitString(0, 'size', $product_static->width_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height + if (!empty($arrayfields['p.height']['checked'])) { + print ''; + print $product_static->height; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height units + if (!empty($arrayfields['p.height_units']['checked'])) { + print ''; + if ($product_static->height != '') { + print measuringUnitString(0, 'size', $product_static->height_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface + if (!empty($arrayfields['p.surface']['checked'])) { + print ''; + print $product_static->surface; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface units + if (!empty($arrayfields['p.surface_units']['checked'])) { + print ''; + if ($product_static->surface != '') { + print measuringUnitString(0, 'surface', $product_static->surface_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume + if (!empty($arrayfields['p.volume']['checked'])) { + print ''; + print $product_static->volume; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume units + if (!empty($arrayfields['p.volume_units']['checked'])) { + print ''; + if ($product_static->volume != '') { + print measuringUnitString(0, 'volume', $product_static->volume_units); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Unit + if (!empty($arrayfields['cu.label']['checked'])) { + print ''; + if (!empty($obj->cu_label)) { + print $langs->trans($obj->cu_label); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Sell price + if (!empty($arrayfields['p.sellprice']['checked'])) { + print ''; + if ($product_static->status && $usercancreadprice) { + if ($obj->price_base_type == 'TTC') { + print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; + } else { + print ''.price($obj->price).' '.$langs->trans("HT").''; + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + // Multiprices + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + if (! isset($productpricescache)) { + $productpricescache=array(); + } + if (! isset($productpricescache[$obj->rowid])) { + $productpricescache[$obj->rowid] = array(); + } + + if ($product_static->status && $usercancreadprice) { + // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array + // then reuse the cache array if we need prices for other price levels + $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; + $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; + $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); + $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; + $resultp = $db->query($sqlp); + if ($resultp) { + $nump = $db->num_rows($resultp); + $j = 0; + while ($j < $nump) { + $objp = $db->fetch_object($resultp); + + if (empty($productpricescache[$obj->rowid][$objp->price_level])) { + $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; + $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; + $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + } + + $j++; } - $j++; + $db->free($resultp); + } else { + dol_print_error($db); } + } - $db->free($resultp); + foreach ($arraypricelevel as $key => $value) { + if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { + print ''; + if (!empty($productpricescache[$obj->rowid])) { + if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { + print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; + } else { + print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + } + } + + // Better buy price + if (!empty($arrayfields['p.minbuyprice']['checked'])) { + print ''; + if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) { + if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { + if ($product_fourn->product_fourn_price_id > 0) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); + print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; + } else { + print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; + } + } + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Number of buy prices + if (!empty($arrayfields['p.numbuyprice']['checked'])) { + print ''; + if ($product_static->status_buy && $usercancreadprice) { + if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); + print $form->textwithpicto(count($productFournList), $htmltext); + } + } + print ''; + } + + // VAT or Sell Tax Rate + if (!empty($arrayfields['p.tva_tx']['checked'])) { + print ''; + print vatrate($obj->tva_tx, true); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // WAP + if (!empty($arrayfields['p.pmp']['checked'])) { + print ''; + if ($usercancreadprice) { + print ''.price($product_static->pmp, 1, $langs).""; + } + print ''; + } + // Cost price + if (!empty($arrayfields['p.cost_price']['checked'])) { + print ''; + //print $obj->cost_price; + if ($usercancreadprice) { + print ''.price($obj->cost_price).' '.$langs->trans("HT").''; + } + print ''; + } + + // Limit alert + if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { + print ''; + if ($product_static->type != 1) { + print $obj->seuil_stock_alerte; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Desired stock + if (!empty($arrayfields['p.desiredstock']['checked'])) { + print ''; + if ($product_static->type != 1) { + print $obj->desiredstock; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Stock real + if (!empty($arrayfields['p.stock']['checked'])) { + print ''; + if ($product_static->type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + if ($product_static->stock_reel < 0) { print ''; } + print price(price2num($product_static->stock_reel, 'MS')); + if ($product_static->stock_reel < 0) { print ''; } + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Stock virtual + if (!empty($arrayfields['stock_virtual']['checked'])) { + print ''; + if ($product_static->type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + if ($product_static->stock_theorique < 0) { print ''; } + print price(price2num($product_static->stock_theorique, 'MS')); + if ($product_static->stock_theorique < 0) { print ''; } + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Lot/Serial + if (!empty($arrayfields['p.tobatch']['checked'])) { + print ''; + print $product_static->getLibStatut(1, 2); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['p.fk_country']['checked'])) { + print ''.getCountry($obj->fk_country, 0, $db).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['p.fk_state']['checked'])) { + print ''; + if (!empty($obj->fk_state)) { + print getState($obj->fk_state, 0, $db); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Accountancy code sell + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { + print ''.$product_static->accountancy_code_sell.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { + print ''.$product_static->accountancy_code_sell_intra.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { + print ''.$product_static->accountancy_code_sell_export.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Accountancy code buy + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { + print ''.$product_static->accountancy_code_buy.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { + print ''.$product_static->accountancy_code_buy_intra.''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { + print ''.$product_static->accountancy_code_buy_export.''; + 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, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['p.datec']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['p.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Status (to sell) + if (!empty($arrayfields['p.tosell']['checked'])) { + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); } else { - dol_print_error($db); + print $product_static->LibStatut($product_static->status, 5, 0); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status (to buy) + if (!empty($arrayfields['p.tobuy']['checked'])) { + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); + } else { + print $product_static->LibStatut($product_static->status_buy, 5, 1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - foreach ($arraypricelevel as $key => $value) { - if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { - print ''; - if (!empty($productpricescache[$obj->rowid])) { - if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { - print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; - } else { - print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; - } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + 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 ''; + if (!$i) { + $totalarray['nbfield']++; } } + + print "\n"; } - // Better buy price - if (!empty($arrayfields['p.minbuyprice']['checked'])) { - print ''; - if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) { - if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { - if ($product_fourn->product_fourn_price_id > 0) { - if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); - print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; - } else { - print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; - } - } - } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Number of buy prices - if (!empty($arrayfields['p.numbuyprice']['checked'])) { - print ''; - if ($product_static->status_buy && $usercancreadprice) { - if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); - print $form->textwithpicto(count($productFournList), $htmltext); - } - } - print ''; - } - - // VAT or Sell Tax Rate - if (!empty($arrayfields['p.tva_tx']['checked'])) { - print ''; - print vatrate($obj->tva_tx, true); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // WAP - if (!empty($arrayfields['p.pmp']['checked'])) { - print ''; - if ($usercancreadprice) { - print ''.price($product_static->pmp, 1, $langs).""; - } - print ''; - } - // Cost price - if (!empty($arrayfields['p.cost_price']['checked'])) { - print ''; - //print $obj->cost_price; - if ($usercancreadprice) { - print ''.price($obj->cost_price).' '.$langs->trans("HT").''; - } - print ''; - } - - // Limit alert - if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { - print ''; - if ($product_static->type != 1) { - print $obj->seuil_stock_alerte; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Desired stock - if (!empty($arrayfields['p.desiredstock']['checked'])) { - print ''; - if ($product_static->type != 1) { - print $obj->desiredstock; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock real - if (!empty($arrayfields['p.stock']['checked'])) { - print ''; - if ($product_static->type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_reel, 'MS')); - } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock virtual - if (!empty($arrayfields['stock_virtual']['checked'])) { - print ''; - if ($product_static->type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_theorique, 'MS')); - } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Lot/Serial - if (!empty($arrayfields['p.tobatch']['checked'])) { - print ''; - print $product_static->getLibStatut(1, 2); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['p.fk_country']['checked'])) { - print ''.getCountry($obj->fk_country, 0, $db).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['p.fk_state']['checked'])) { - print ''; - if (!empty($obj->fk_state)) { - print getState($obj->fk_state, 0, $db); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code sell - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { - print ''.$product_static->accountancy_code_sell.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { - print ''.$product_static->accountancy_code_sell_intra.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { - print ''.$product_static->accountancy_code_sell_export.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code buy - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { - print ''.$product_static->accountancy_code_buy.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { - print ''.$product_static->accountancy_code_buy_intra.''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { - print ''.$product_static->accountancy_code_buy_export.''; - 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, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['p.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['p.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Status (to sell) - if (!empty($arrayfields['p.tosell']['checked'])) { - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); - } else { - print $product_static->LibStatut($product_static->status, 5, 0); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status (to buy) - if (!empty($arrayfields['p.tobuy']['checked'])) { - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); - } else { - print $product_static->LibStatut($product_static->status_buy, 5, 1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - 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 ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - print "\n"; $i++; } diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index b91ae62f663..10581d19b7c 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -133,6 +133,7 @@ $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; $form = new Form($db); $htmlother = new FormOther($db); +if ($objp->stock_physique < 0) { print ''; } $sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,'; $sql .= ' p.fk_product_type, p.tms as datem,'; @@ -406,8 +407,8 @@ if ($resql) { } print ''; - //Line for column titles - print ""; + // Line for column titles + print ''; // Action column if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre(''); @@ -480,14 +481,20 @@ if ($resql) { print ''; } //print ''.$objp->stock_theorique.''; - print ''.$objp->seuil_stock_alerte.''; - print ''.$objp->desiredstock.''; + print ''; + print $objp->seuil_stock_alerte; + print ''; + print ''; + print $objp->desiredstock; + print ''; // Real stock print ''; if ($objp->seuil_stock_alerte != '' && ($objp->stock_physique < $objp->seuil_stock_alerte)) { - print img_warning($langs->trans("StockTooLow")).' '; + print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' '; } + if ($objp->stock_physique < 0) { print ''; } print price2num($objp->stock_physique, 'MS'); + if ($objp->stock_physique < 0) { print ''; } print ''; // Details per warehouse @@ -505,14 +512,16 @@ if ($resql) { if ($virtualdiffersfromphysical) { print ''; if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < $objp->seuil_stock_alerte)) { - print img_warning($langs->trans("StockTooLow")).' '; + print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' '; } + if ($objp->stock_physique < 0) { print ''; } print price2num($product->stock_theorique, 'MS'); + if ($objp->stock_physique < 0) { print ''; } print ''; } // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { - print ''.$objp->unit_short.''; + print ''.dol_escape_htmltag($objp->unit_short).''; } print ''; print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"'); diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index c07f0785e2c..a0359f0aeb1 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -716,8 +716,9 @@ while ($i < $imaxinloop) { } print ''; - //if ($objp->seuil_stock_alerte && ($objp->stock_physique < $objp->seuil_stock_alerte)) print img_warning($langs->trans("StockTooLow")).' '; + if ($objp->stock_physique < 0) { print ''; } print $objp->stock_physique; + if ($objp->stock_physique < 0) { print ''; } print ''; print ''; diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 42deedd5419..8653953371a 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -252,15 +252,98 @@ if (empty($reshook)) { } } } else { + $cond_reglement_id = 0; + $mode_reglement_id = 0; + $fk_account = 0; + $remise_percent = 0; + $remise_absolue = 0; + $transport_mode_id = 0; + if (!empty($rcp->cond_reglement_id)) { + $cond_reglement_id = $rcp->cond_reglement_id; + } + if (!empty($rcp->mode_reglement_id)) { + $mode_reglement_id = $rcp->mode_reglement_id; + } + if (!empty($rcp->fk_account)) { + $fk_account = $rcp->fk_account; + } + if (!empty($rcp->remise_percent)) { + $remise_percent = $rcp->remise_percent; + } + if (!empty($rcp->remise_absolue)) { + $remise_absolue = $rcp->remise_absolue; + } + if (!empty($rcp->transport_mode_id)) { + $transport_mode_id = $rcp->transport_mode_id; + } + + if (empty($cond_reglement_id) + || empty($mode_reglement_id) + || empty($fk_account) + || empty($remise_percent) + || empty($remise_absolue) + || empty($transport_mode_id) + ) { + if (!isset($rcp->supplier_order)) { + $rcp->fetch_origin(); + } + + // try to get from source of reception (supplier order) + if (!empty($rcp->commandeFournisseur)) { + $supplierOrder = $rcp->commandeFournisseur; + if (empty($cond_reglement_id) && !empty($supplierOrder->cond_reglement_id)) { + $cond_reglement_id = $supplierOrder->cond_reglement_id; + } + if (empty($mode_reglement_id) && !empty($supplierOrder->mode_reglement_id)) { + $mode_reglement_id = $supplierOrder->mode_reglement_id; + } + if (empty($fk_account) && !empty($supplierOrder->fk_account)) { + $fk_account = $supplierOrder->fk_account; + } + if (empty($remise_percent) && !empty($supplierOrder->remise_percent)) { + $remise_percent = $supplierOrder->remise_percent; + } + if (empty($remise_absolue) && !empty($supplierOrder->remise_absolue)) { + $remise_absolue = $supplierOrder->remise_absolue; + } + if (empty($transport_mode_id) && !empty($supplierOrder->transport_mode_id)) { + $transport_mode_id = $supplierOrder->transport_mode_id; + } + } + + // try get from third-party of reception + if (!empty($rcp->thirdparty)) { + $soc = $rcp->thirdparty; + if (empty($cond_reglement_id) && !empty($soc->cond_reglement_supplier_id)) { + $cond_reglement_id = $soc->cond_reglement_supplier_id; + } + if (empty($mode_reglement_id) && !empty($soc->mode_reglement_supplier_id)) { + $mode_reglement_id = $soc->mode_reglement_supplier_id; + } + if (empty($fk_account) && !empty($soc->fk_account)) { + $fk_account = $soc->fk_account; + } + if (empty($remise_percent) && !empty($soc->remise_supplier_percent)) { + $remise_percent = $soc->remise_supplier_percent; + } + if (empty($remise_absolue) && !empty($soc->remise_absolue)) { + $remise_absolue = $soc->remise_absolue; + } + if (empty($transport_mode_id) && !empty($soc->transport_mode_id)) { + $transport_mode_id = $soc->transport_mode_id; + } + } + } + // If we want one invoice per reception or if there is no first invoice yet for this thirdparty. $objecttmp->socid = $rcp->socid; $objecttmp->type = $objecttmp::TYPE_STANDARD; - $objecttmp->cond_reglement_id = $rcp->cond_reglement_id || $rcp->thirdparty->cond_reglement_supplier_id; - $objecttmp->mode_reglement_id = $rcp->mode_reglement_id || $rcp->thirdparty->mode_reglement_supplier_id; - - $objecttmp->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0; - $objecttmp->remise_percent = !empty($rcp->thirdparty->remise_percent) ? $rcp->thirdparty->remise_percent : 0; - $objecttmp->remise_absolue = !empty($rcp->thirdparty->remise_absolue) ? $rcp->thirdparty->remise_absolue : 0; + $objecttmp->cond_reglement_id = $cond_reglement_id; + $objecttmp->mode_reglement_id = $mode_reglement_id; + $objecttmp->fk_account = $fk_account; + $objecttmp->remise_percent = $remise_percent; + $objecttmp->remise_absolue = $remise_absolue; + $objecttmp->transport_mode_id = $transport_mode_id; $objecttmp->fk_project = $rcp->fk_project; //$objecttmp->multicurrency_code = $rcp->multicurrency_code; @@ -280,6 +363,11 @@ if (empty($reshook)) { $objecttmp->origin = 'reception'; $objecttmp->origin_id = $id_reception; + // Auto calculation of date due if not filled by user + if (empty($objecttmp->date_echeance)) { + $objecttmp->date_echeance = $objecttmp->calculate_date_lim_reglement(); + } + $objecttmp->array_options = $rcp->array_options; // Copy extrafields // Set $objecttmp->linked_objects with all links order_supplier existing on reception, so same links will be added to the generated supplier invoice diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 5c010e21e26..dd6c21368db 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -189,6 +189,31 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { bottom: 0; } +/* customize section img box on list of products */ +.info-box-img { + height: 105px !important; + width: 88px; + border-top-left-radius: 2px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 2px; + display: block; + overflow: hidden; + float: left; + text-align: center; + font-size: 2.8em; + line-height: 90px; + margin-right: 5px; + background: var(--colorbacktitle1) !important; +} +.info-box-img > img { + width: 90%; + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + global->MAIN_DISABLE_GLOBAL_BOXSTATS) && !empty($conf->global->MAIN_INCLUDE_GLOBAL_STATS_IN_OPENED_DASHBOARD)) { ?> .info-box-icon-text{ opacity: 1; diff --git a/htdocs/variants/ajax/get_attribute_values.php b/htdocs/variants/ajax/get_attribute_values.php index 1867eb368de..3950a262500 100644 --- a/htdocs/variants/ajax/get_attribute_values.php +++ b/htdocs/variants/ajax/get_attribute_values.php @@ -83,4 +83,4 @@ if ($res == -1) { exit(); } -print json_encode($res); +print json_encode($res, JSON_PARTIAL_OUTPUT_ON_ERROR); diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index 5128f31d0c5..e5043dcd7fa 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -511,7 +511,7 @@ if (!empty($id) || !empty($ref)) {