diff --git a/.travis.yml b/.travis.yml index f7903361b02..ca9641ce63e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ # We use dist: xenial to have php 5.6+ available os: linux dist: xenial +#dist: bionic sudo: required language: php diff --git a/COPYRIGHT b/COPYRIGHT index 2964c915ec1..251ad7f2fe4 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -39,7 +39,7 @@ TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes JS libraries: Ace 1.4.8 BSD Yes JS library to get code syntaxique coloration in a textarea. ChartJS 2.9.3 MIT License Yes JS library for graph -jQuery 3.4.1 MIT License Yes JS library +jQuery 3.5.1 MIT License Yes JS library jQuery UI 1.12.1 GPL and MIT License Yes JS library plugin UI jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups) diff --git a/ChangeLog b/ChangeLog index c74f30755c6..7c9b5c237ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,15 +4,78 @@ English Dolibarr ChangeLog ***** ChangeLog for 13.0.0 compared to 12.0.0 ***** For users: - +NEW: Add module Credit transfer SEPA to manage payment of supplier using bank credit transfer SEPA files +NEW: Module Reception (for a more accurate management of your receptions) moved from experimental to stable WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * Properties ->contactid has been renamed into ->contact_id +* Rename property $paiementid in API api_supplier_invoices into $payment_mode_id +***** ChangeLog for 12.0.2 compared to 12.0.1 ***** +FIX: computation of the bottom margin of returns NaN because body is not loaded yet +FIX: DebugBar hides content at page bottom +FIX: allow more harmless html tags +FIX: Bad back to link +FIX: Bad param +FIX: Can go on page even when module is disabled +FIX: Change position of line in BOM +FIX: Checkbox "drop table" was not checked when using php method to generate backup dump +FIX: ClickToDial tab of users has disappeared +FIX: CSS +FIX: date in supplier price log tooltip. +FIX: Debug module direct debit order. Solve conflict with credit transfer +FIX: Debug setup of receipt printer module +FIX: dolGetElementUrl and agenda page for external modules +FIX: DO not erase variable $key and $label during output of extrafields +FIX: duration fields size with firefox +FIX: Edit extrafield of type long text loose carriage returns +FIX: Fails to retraive accounting code of social contribution sometimes +FIX: Filter too large for extrafields with type text or html +FIX: If using a rounding step, localtax1+2 not included in total +FIX: input field of extrafields must keep data if form submit fails. +FIX: Label of opportunities in graph with special chars badly encoded +FIX: locataxes lost on lines when cloning a vendor invoice +FIX: Look and feel v12 +FIX: Missing PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE conf support in supplier order +FIX: Navigation in object fails to find the next ref in some cases +FIX: null required +FIX: order by amount ht uses wrong column +FIX: Order by amount in product propal stats must be done on d.total_ht and not p.total +FIX: page for confirmation of payments is empty +FIX: Param of fetch_name_optionals_label must be object->table_element +FIX: Picto of HRM module +FIX: product label and desc were never updated when modifying translation +FIX: redirect on contact card from main search +FIX: Reposition and nav +FIX: search warehouse list +FIX: Setup of clicktodial hang on smartphone +FIX: Setup of currency limit and accuracy +FIX: shipping creation: checks not done on weight and sizes +FIX: Should not be able to edit qty on shipment when no stock available +FIX: Size of image on the help popup of modules +FIX: Sql error on stat by referring entries of a product +FIX: Warning if no bank account defined +FIX: We need to see unit line on PDF even though it's an option +FIX: wrong element var for fetch_name_optionals_label function with expeditions +FIX: wrong link to third invoice templates +FIX: Disable svg as supported image by default (can contains javascript). Set MAIN_ALLOW_SVG_FILES_AS_IMAGES to 1 to have svg accepted +FIX: #14076 +FIX: #14146 +FIX: #14209 +FIX: #14222 +FIX: #14236 +FIX: #14241 Mysql 8 compatibility +FIX: #14253 +FIX: #14256 +FIX: #14259 +FIX: #14279 +FIX: #14291 +FIX: #14292 +FIX: #14336 ***** ChangeLog for 12.0.1 compared to 12.0.0 ***** FIX: reposition was broken if url end with #anchor diff --git a/README.md b/README.md index fa5326079ec..19a767c8232 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,15 @@ ![Downloads per day](https://img.shields.io/sourceforge/dw/dolibarr.svg) ![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg) -Dolibarr ERP & CRM is a modern software package to manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda…). +Dolibarr ERP & CRM is a modern software package that helps manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda…). -It's an Open Source Software (written in PHP language) designed for small, medium or large companies, foundations and freelancers. +It's an Open Source Software suite (written in PHP with optional JavaScript enhancements) designed for small, medium or large companies, foundations and freelancers. -You can freely use, study, modify or distribute it according to its Free Software licence. +You can freely use, study, modify or distribute it according to its licence. -You can use it as a standalone application or as a web application to be able to access it from the Internet or a LAN. +You can use it as a standalone application or as a web application to access it from the Internet or a LAN. + +Dolibarr has a large community ready to help you, free forums and [oficially preferred partners ready to offer commercial support should you need it](https://partners.dolibarr.org) ![ScreenShot](https://www.dolibarr.org/images/dolibarr_screenshot1_1920x1080.jpg) @@ -35,11 +37,15 @@ Releases can be downloaded from [official website](https://www.dolibarr.org/). ### Advanced setup -You can use a Web server and a supported database (MariaDB, MySQL or PostgreSQL) to install the standard version. +You can use a web server and a supported database (MariaDB, MySQL or PostgreSQL) to install the standard version. + +On GNU/Linux, first check if your distribution has already packaged Dolibarr. + +#### Generic install steps: - Check that your installed PHP version is supported [see PHP support](https://wiki.dolibarr.org/index.php/Versions). -- Uncompress the downloaded .zip archive to copy the "dolibarr/htdocs" directory and all its files inside your web server root or get the files directly from GitHub (recommanded if you known git): +- Uncompress the downloaded .zip archive to copy the "dolibarr/htdocs" directory and all its files inside your web server root or get the files directly from GitHub (recommanded if you know git as it makes it easier if you want to upgrade later): `git clone https://github.com/dolibarr/dolibarr -b x.y` (where x.y is main version like 3.6, 9.0, ...) @@ -70,13 +76,13 @@ If you don't have time to install it yourself, you can try some commercial 'read ## UPGRADING +Dolibarr supports upgrading usually wihtout the need for any (commercial) support (depending on if you use any commercial extensions) and supports upgrading all the way from any version after 2.8 without breakage. This is unique in the ERP ecosystem and a benefit our users highly appreciate! + - At first make a backup of your Dolibarr files & than see https://wiki.dolibarr.org/index.php/Installation_-_Upgrade#Upgrade_Dolibarr - Check that your installed PHP version is supported by the new version [see PHP support](./doc/phpmatrix.md). - Overwrite all old files from 'dolibarr' directory with files provided into the new version's package. -- At first next access, Dolibarr will redirect your to the "install/" page to follow the upgrade process. -  If an `install.lock` file exists to lock any other upgrade process, the application will ask you to remove the file manually (you should find the `install.lock` file into the directory used to store generated and uploaded documents, in most cases, it is the directory called "*documents*"). - -*Note: migration process can be safely done multiple times by calling the `/install/index.php` page* +- At first next access, Dolibarr will redirect you to the "install/" page to follow the upgrade process. +  If an `install.lock` file exists to lock any other upgrade process, the application will ask you to remove the file manually (you should find the `install.lock` file in the directory used to store generated and uploaded documents, in most cases, it is the directory called "*documents*"). ## WHAT'S NEW @@ -139,7 +145,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) - Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one) - APIs -- An easy to understand, maintain and develop code (PHP with no heavy framework; trigger and hook architecture) +- Code that is easy to understand, maintain and develop (PHP with no heavy framework; trigger and hook architecture) - Support a lot of country specific features: - Spanish Tax RE and ISPF - French NPR VAT rate (VAT called "Non Perçue Récupérable" for DOM-TOM) @@ -149,7 +155,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) - Compatible with [European directives](http://europa.eu/legislation_summaries/taxation/l31057_en.htm) (2006/112/CE ... 2010/45/UE) - Compatible with European GDPR rules - ... -- PDF or ODT generation for invoice, proposals, orders... +- Flexible PDF & ODT generation for invoices, proposals, orders... - … ### System Environment / Requirements @@ -167,12 +173,12 @@ These are features that Dolibarr does **not** yet fully support: - Tasks dependencies in projects - Payroll module -- No native embedded Webmail +- No native embedded Webmail, but you can send email to contacts in Dolibarr with e.g. offers, invoices, etc. - Dolibarr can't do coffee (yet) ## DOCUMENTATION -Administrator, user, developer and translator's documentations are available along with other community resources on the [Wiki](https://wiki.dolibarr.org). +Administrator, user, developer and translator's documentations are available along with other community resources in the [Wiki](https://wiki.dolibarr.org). ## CONTRIBUTING @@ -182,7 +188,7 @@ This project exists thanks to all the people who contribute. [[Contribute](https ## CREDITS -Dolibarr is the work of many contributors over the years and uses some fine libraries. +Dolibarr is the work of many contributors over the years and uses some fine PHP libraries. See [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) file. diff --git a/build/debian/control b/build/debian/control index 970f192f094..0ef5367072f 100755 --- a/build/debian/control +++ b/build/debian/control @@ -14,7 +14,7 @@ Architecture: all Depends: libapache2-mod-php5 | libapache2-mod-php5filter | php5-cgi | php5-fpm | php5 | libapache2-mod-php | libapache2-mod-phpfilter | php-cgi | php-fpm | php, php5-cli | php-cli, # Required PHP extensions - php5-mysql | php5-mysqli | php-mysql | php-mysqli, php5-curl | php-curl, php5-gd | php-gd, php5-ldap | php-gd, + php5-mysql | php5-mysqli | php-mysql | php-mysqli, php5-curl | php-curl, php5-gd | php-gd, php5-ldap | php-gd, php5-zip | php-zip, # Required PHP libraries php-pear, php-mail-mime, # php-tcpdf, diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index 79f927160ee..3c7ff061e49 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -8,6 +8,7 @@ ALL: Check "@CHANGE" + PrestaShopWebservice: --------------------- Replace @@ -27,6 +28,19 @@ With +DEBUGBAR: +--------- + +Move + this.options = { + bodyMarginBottom: true, + bodyMarginBottomHeight: parseInt($('body').css('margin-bottom')), + }; +few line lower in the + initialize: function() { + + + ESCPOS: ------- Replace @@ -167,6 +181,7 @@ In htdocs/includes/tecnickcom/tcpdf/tcpdf.php TCPDI: ------ Add fpdf_tpl.php 1.2 + Add tcpdi.php Add tcpdi_parser.php and replace: @@ -205,8 +220,6 @@ with - - JCROP: ------ * Remove analytics tag into file index.html diff --git a/dev/initdemo/mysqldump_dolibarr_12.0.0.sql b/dev/initdemo/mysqldump_dolibarr_12.0.0.sql index 25663fa6991..3cc1db1cf34 100644 --- a/dev/initdemo/mysqldump_dolibarr_12.0.0.sql +++ b/dev/initdemo/mysqldump_dolibarr_12.0.0.sql @@ -1326,7 +1326,7 @@ CREATE TABLE `llx_boxes_def` ( LOCK TABLES `llx_boxes_def` WRITE; /*!40000 ALTER TABLE `llx_boxes_def` DISABLE KEYS */; -INSERT INTO `llx_boxes_def` VALUES (188,'box_services_vendus.php',1,'2013-08-05 20:40:27',NULL),(323,'box_actions.php',2,'2015-03-13 15:29:19',NULL),(324,'box_clients.php',2,'2015-03-13 20:21:35',NULL),(325,'box_prospect.php',2,'2015-03-13 20:21:35',NULL),(326,'box_contacts.php',2,'2015-03-13 20:21:35',NULL),(327,'box_activity.php',2,'2015-03-13 20:21:35','(WarningUsingThisBoxSlowDown)'),(328,'box_propales.php',2,'2015-03-13 20:32:38',NULL),(329,'box_comptes.php',2,'2015-03-13 20:33:09',NULL),(330,'box_factures_imp.php',2,'2015-03-13 20:33:09',NULL),(331,'box_factures.php',2,'2015-03-13 20:33:09',NULL),(332,'box_produits.php',2,'2015-03-13 20:33:09',NULL),(333,'box_produits_alerte_stock.php',2,'2015-03-13 20:33:09',NULL),(347,'box_clients.php',1,'2017-11-15 22:05:57',NULL),(348,'box_prospect.php',1,'2017-11-15 22:05:57',NULL),(349,'box_contacts.php',1,'2017-11-15 22:05:57',NULL),(350,'box_activity.php',1,'2017-11-15 22:05:57','(WarningUsingThisBoxSlowDown)'),(374,'box_services_contracts.php',1,'2017-11-15 22:38:37',NULL),(377,'box_project.php',1,'2017-11-15 22:38:44',NULL),(378,'box_task.php',1,'2017-11-15 22:38:44',NULL),(388,'box_contracts.php',1,'2017-11-15 22:39:52',NULL),(389,'box_services_expired.php',1,'2017-11-15 22:39:52',NULL),(390,'box_ficheinter.php',1,'2017-11-15 22:39:56',NULL),(392,'box_graph_propales_permonth.php',1,'2017-11-15 22:41:47',NULL),(393,'box_propales.php',1,'2017-11-15 22:41:47',NULL),(396,'box_graph_product_distribution.php',1,'2017-11-15 22:41:47',NULL),(403,'box_goodcustomers.php',1,'2018-07-30 11:13:20','(WarningUsingThisBoxSlowDown)'),(404,'box_external_rss.php',1,'2018-07-30 11:15:25','1 (Dolibarr.org News)'),(409,'box_produits.php',1,'2018-07-30 13:38:11',NULL),(410,'box_produits_alerte_stock.php',1,'2018-07-30 13:38:11',NULL),(411,'box_commandes.php',1,'2018-07-30 13:38:11',NULL),(412,'box_graph_orders_permonth.php',1,'2018-07-30 13:38:11',NULL),(413,'box_graph_invoices_supplier_permonth.php',1,'2018-07-30 13:38:11',NULL),(414,'box_graph_orders_supplier_permonth.php',1,'2018-07-30 13:38:11',NULL),(415,'box_fournisseurs.php',1,'2018-07-30 13:38:11',NULL),(416,'box_factures_fourn_imp.php',1,'2018-07-30 13:38:11',NULL),(417,'box_factures_fourn.php',1,'2018-07-30 13:38:11',NULL),(418,'box_supplier_orders.php',1,'2018-07-30 13:38:11',NULL),(419,'box_actions.php',1,'2018-07-30 15:42:32',NULL),(424,'box_factures_imp.php',1,'2017-02-07 18:56:12',NULL),(425,'box_factures.php',1,'2017-02-07 18:56:12',NULL),(426,'box_graph_invoices_permonth.php',1,'2017-02-07 18:56:12',NULL),(427,'box_comptes.php',1,'2017-02-07 18:56:12',NULL),(429,'box_lastlogin.php',1,'2017-08-27 13:29:14',NULL),(430,'box_bookmarks.php',1,'2018-01-19 11:27:34',NULL),(431,'box_members.php',1,'2018-01-19 11:27:56',NULL),(432,'box_birthdays.php',1,'2019-06-05 08:45:40',NULL),(433,'box_last_ticket',1,'2019-06-05 09:15:29',NULL),(434,'box_last_modified_ticket',1,'2019-06-05 09:15:29',NULL),(436,'box_accountancy_last_manual_entries.php',1,'2019-11-28 11:52:58',NULL),(437,'box_accountancy_suspense_account.php',1,'2019-11-28 11:52:58',NULL),(438,'box_supplier_orders_awaiting_reception.php',1,'2019-11-28 11:52:59',NULL),(439,'box_mos.php',1,'2019-11-29 08:57:42',NULL),(445,'box_shipments.php',1,'2020-01-13 14:38:20',NULL); +INSERT INTO `llx_boxes_def` VALUES (323,'box_actions.php',2,'2015-03-13 15:29:19',NULL),(324,'box_clients.php',2,'2015-03-13 20:21:35',NULL),(325,'box_prospect.php',2,'2015-03-13 20:21:35',NULL),(326,'box_contacts.php',2,'2015-03-13 20:21:35',NULL),(327,'box_activity.php',2,'2015-03-13 20:21:35','(WarningUsingThisBoxSlowDown)'),(328,'box_propales.php',2,'2015-03-13 20:32:38',NULL),(329,'box_comptes.php',2,'2015-03-13 20:33:09',NULL),(330,'box_factures_imp.php',2,'2015-03-13 20:33:09',NULL),(331,'box_factures.php',2,'2015-03-13 20:33:09',NULL),(332,'box_produits.php',2,'2015-03-13 20:33:09',NULL),(333,'box_produits_alerte_stock.php',2,'2015-03-13 20:33:09',NULL),(347,'box_clients.php',1,'2017-11-15 22:05:57',NULL),(348,'box_prospect.php',1,'2017-11-15 22:05:57',NULL),(349,'box_contacts.php',1,'2017-11-15 22:05:57',NULL),(350,'box_activity.php',1,'2017-11-15 22:05:57','(WarningUsingThisBoxSlowDown)'),(374,'box_services_contracts.php',1,'2017-11-15 22:38:37',NULL),(377,'box_project.php',1,'2017-11-15 22:38:44',NULL),(378,'box_task.php',1,'2017-11-15 22:38:44',NULL),(388,'box_contracts.php',1,'2017-11-15 22:39:52',NULL),(389,'box_services_expired.php',1,'2017-11-15 22:39:52',NULL),(390,'box_ficheinter.php',1,'2017-11-15 22:39:56',NULL),(392,'box_graph_propales_permonth.php',1,'2017-11-15 22:41:47',NULL),(393,'box_propales.php',1,'2017-11-15 22:41:47',NULL),(396,'box_graph_product_distribution.php',1,'2017-11-15 22:41:47',NULL),(403,'box_goodcustomers.php',1,'2018-07-30 11:13:20','(WarningUsingThisBoxSlowDown)'),(404,'box_external_rss.php',1,'2018-07-30 11:15:25','1 (Dolibarr.org News)'),(409,'box_produits.php',1,'2018-07-30 13:38:11',NULL),(410,'box_produits_alerte_stock.php',1,'2018-07-30 13:38:11',NULL),(411,'box_commandes.php',1,'2018-07-30 13:38:11',NULL),(412,'box_graph_orders_permonth.php',1,'2018-07-30 13:38:11',NULL),(413,'box_graph_invoices_supplier_permonth.php',1,'2018-07-30 13:38:11',NULL),(414,'box_graph_orders_supplier_permonth.php',1,'2018-07-30 13:38:11',NULL),(415,'box_fournisseurs.php',1,'2018-07-30 13:38:11',NULL),(416,'box_factures_fourn_imp.php',1,'2018-07-30 13:38:11',NULL),(417,'box_factures_fourn.php',1,'2018-07-30 13:38:11',NULL),(418,'box_supplier_orders.php',1,'2018-07-30 13:38:11',NULL),(419,'box_actions.php',1,'2018-07-30 15:42:32',NULL),(424,'box_factures_imp.php',1,'2017-02-07 18:56:12',NULL),(425,'box_factures.php',1,'2017-02-07 18:56:12',NULL),(426,'box_graph_invoices_permonth.php',1,'2017-02-07 18:56:12',NULL),(427,'box_comptes.php',1,'2017-02-07 18:56:12',NULL),(429,'box_lastlogin.php',1,'2017-08-27 13:29:14',NULL),(430,'box_bookmarks.php',1,'2018-01-19 11:27:34',NULL),(431,'box_members.php',1,'2018-01-19 11:27:56',NULL),(432,'box_birthdays.php',1,'2019-06-05 08:45:40',NULL),(433,'box_last_ticket',1,'2019-06-05 09:15:29',NULL),(434,'box_last_modified_ticket',1,'2019-06-05 09:15:29',NULL),(436,'box_accountancy_last_manual_entries.php',1,'2019-11-28 11:52:58',NULL),(437,'box_accountancy_suspense_account.php',1,'2019-11-28 11:52:58',NULL),(438,'box_supplier_orders_awaiting_reception.php',1,'2019-11-28 11:52:59',NULL),(439,'box_mos.php',1,'2019-11-29 08:57:42',NULL),(445,'box_shipments.php',1,'2020-01-13 14:38:20',NULL); /*!40000 ALTER TABLE `llx_boxes_def` ENABLE KEYS */; UNLOCK TABLES; diff --git a/dev/resources/sepa/sample-credit-transfer.xml b/dev/resources/sepa/sample-credit-transfer.xml new file mode 100644 index 00000000000..087fd2f57d7 --- /dev/null +++ b/dev/resources/sepa/sample-credit-transfer.xml @@ -0,0 +1,172 @@ + + + + + message-id-001 + 2010-09-28T14:07:00 + 1 + 10.1 + + Bedrijfsnaam + + + + 123456789123456 + + + + + + + minimaal gevuld + TRF + 1 + 10.1 + 2009-11-01 + + Naam + + + + NL44RABO0123456789 + + + + + RABONL2U + + + + + non ref + + + 10.1 + + SLEV + + + ABNANL2A + + + + Naam creditor + + + + NL90ABNA0111111111 + + + + vrije tekst + + + + + maximaal gevuld + TRF + true + 1 + 20.2 + + NORM + + SEPA + + + IDEAL + + + SECU + + + 2009-11-01 + + Naam + + NL + Debtor straat 1 + 9999 XX Plaats debtor + + + + + NL44RABO0123456789 + + + + + RABONL2U + + + + + + + 12345678 + + klantnummer + + klantnummer uitgifte instantie + + + + + SLEV + + + debtor-to-debtor-bank-01 + End-to-end-id-debtor-to-creditor-01 + + + 20.2 + + + + ABNANL2A + + + + Naam creditor + + NL + Straat creditor 1 + 9999 XX Plaats creditor + + + + + NL90ABNA0111111111 + + + + + + + 1969-07-03 + PLAATS + NL + + + + + + CHAR + + + + + + + SCOR + + CUR + + 1234567 + + + + + + + diff --git a/dev/resources/sepa/test.xml b/dev/resources/sepa/sample-direct-debit.xml similarity index 100% rename from dev/resources/sepa/test.xml rename to dev/resources/sepa/sample-direct-debit.xml diff --git a/dev/resources/sepa/text.txt b/dev/resources/sepa/text.txt index e6c05276be2..dbcfeded5a4 100644 --- a/dev/resources/sepa/text.txt +++ b/dev/resources/sepa/text.txt @@ -1,2 +1,8 @@ +Spec for credit transfer: +https://docs.oracle.com/cd/E39124_01/doc.91/e60210/fields_sepa_pay_file_appx.htm#EOAEL00515 + +To validate a SEPA file: +xmllint --schema pain.001.001.03.xsd T200801.xml --noout + To test a SEPA file: https://www.mesfluxdepaiement.fr/testez-vos-fichiers-sepa diff --git a/htdocs/accountancy/admin/fiscalyear.php b/htdocs/accountancy/admin/fiscalyear.php index b5cc46a3d0d..89aad6e2d0d 100644 --- a/htdocs/accountancy/admin/fiscalyear.php +++ b/htdocs/accountancy/admin/fiscalyear.php @@ -79,6 +79,7 @@ $object = new Fiscalyear($db); $max = 100; $form = new Form($db); +$fiscalyearstatic = new Fiscalyear($db); $title = $langs->trans('AccountingPeriods'); $helpurl = ""; @@ -132,13 +133,15 @@ if ($result) print ''; if ($num) { - $fiscalyearstatic = new Fiscalyear($db); - while ($i < $num && $i < $max) { $obj = $db->fetch_object($result); + $fiscalyearstatic->id = $obj->rowid; + print ''; - print ''.img_object($langs->trans("ShowFiscalYear"), "technic").' '.$obj->rowid.''; + print ''; + print $fiscalyearstatic->getNomUrl(1); + print ''; print ''.$obj->label.''; print ''.dol_print_date($db->jdate($obj->date_start), 'day').''; print ''.dol_print_date($db->jdate($obj->date_end), 'day').''; diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 006db08fe9c..26ea76d2277 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -31,6 +31,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; // Load translation files required by the page $langs->loadLangs(array("compta", "bills", "admin", "accountancy")); @@ -51,7 +52,9 @@ $list = array( // 'ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT', // adjust size displayed for select account description for dol_trunc ); - +$list_binding = array( + 'ACCOUNTING_DATE_START_BINDING', +); /* * Actions @@ -75,6 +78,22 @@ if ($action == 'update') { if ($error) { setEventMessages($langs->trans("Error"), null, 'errors'); } + + foreach ($list_binding as $constname) + { + $constvalue = GETPOST($constname, 'alpha'); + + if ($constname == 'ACCOUNTING_DATE_START_BINDING') { + $constvalue = dol_mktime(12, 0, 0, GETPOST($constname.'month', 'int'), GETPOST($constname.'day', 'int'), GETPOST($constname.'year', 'int')); + } + + if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) { + $error++; + } + } + if ($error) { + setEventMessages($langs->trans("Error"), null, 'errors'); + } } if (!$error) { @@ -158,6 +177,7 @@ if ($action == 'setenablesubsidiarylist') { /* * View */ +$form = new Form($db); $title = $langs->trans('ConfigAccountingExpert'); llxHeader('', $title); @@ -200,41 +220,15 @@ print "\n"; print '
'; */ -// Others params - +// Params print ''; print ''; -print ''; +print ''; print "\n"; if (!empty($user->admin)) { // TO DO Mutualize code for yes/no constants - print ''; - print ''; - if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO)) { - print ''; - } else { - print ''; - } - print ''; - - print ''; - print ''; - if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE)) { - print ''; - } else { - print ''; - } - print ''; /* Set this option as a hidden option but keep it for some needs. print ''; @@ -251,7 +245,7 @@ if (!empty($user->admin)) print ''; */ - print ''; + print ''; print ''; if (!empty($conf->global->BANK_DISABLE_DIRECT_INPUT)) { print ''; } print ''; + + // Param a user $user->rights->accounting->chartofaccount can access + foreach ($list as $key) + { + print ''; + + if (!empty($conf->global->ACCOUNTING_MANAGE_ZERO) && ($key == 'ACCOUNTING_LENGTH_GACCOUNT' || $key == 'ACCOUNTING_LENGTH_AACCOUNT')) continue; + + // Param + $label = $langs->trans($key); + print ''; + // Value + print ''; + + print ''; + } +} +print '
'.$langs->trans('OtherOptions').''.$langs->trans('Options').'
'.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_TODO").''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print '
'.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_DONE").''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print '
'.$langs->trans("BANK_DISABLE_DIRECT_INPUT").''; @@ -289,22 +283,81 @@ if (!empty($user->admin)) print '
'.$label.''; + print ''; + + print '
'; +print '
'; + +// Binding params +print ''; +print ''; +print ''; +print "\n"; + +if (!empty($user->admin)) +{ + // TO DO Mutualize code for yes/no constants + print ''; + print ''; + if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO)) { + print ''; + } else { + print ''; + } + print ''; + + print ''; + print ''; + if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE)) { + print ''; + } else { + print ''; + } + print ''; } - // Param a user $user->rights->accounting->chartofaccount can access -foreach ($list as $key) +foreach ($list_binding as $key) { print ''; - if (!empty($conf->global->ACCOUNTING_MANAGE_ZERO) && ($key == 'ACCOUNTING_LENGTH_GACCOUNT' || $key == 'ACCOUNTING_LENGTH_AACCOUNT')) continue; - // Param $label = $langs->trans($key); print ''; // Value print ''; print ''; @@ -315,10 +368,6 @@ print '
'.$langs->trans('BindingOptions').'
'.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_TODO").''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print '
'.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_DONE").''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print '
'.$label.''; - print ''; + if ($key == 'ACCOUNTING_DATE_START_BINDING') { + print $form->selectDate(($conf->global->$key ? $db->idate($conf->global->$key) : -1), $key, 0, 0, 1); + } else { + print ''; + } + print '
'; print '
'; -print '
'; -print '
'; - -print '
'; print ''; // End of page diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 1f4ac513806..d9c0c7b399f 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -32,6 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; // Load translation files required by the page @@ -78,6 +79,7 @@ if ($sortfield == "") $sortfield = "t.doc_date,t.rowid"; // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new BookKeeping($db); +$formfile = new FormFile($db); $hookmanager->initHooks(array('bookkeepingbyaccountlist')); $formaccounting = new FormAccounting($db); @@ -543,7 +545,7 @@ while ($i < min($num, $limit)) // Show the break account print ""; - print ''; + print ''; if ($line->numero_compte != "" && $line->numero_compte != '-1') print length_accountg($line->numero_compte).' : '.$object->get_compte_desc($line->numero_compte); else print ''.$langs->trans("Unknown").''; print ''; diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 452db02d30b..69135e75c4d 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -256,6 +256,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND f.fk_statut > 0"; $sql .= " AND fd.product_type <= 2"; $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy @@ -330,6 +334,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; $sql .= " AND fd.product_type <= 2"; @@ -405,6 +413,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; $sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; + // Define begin binding date + if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; + } $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; $sql .= " AND fd.product_type <= 2"; @@ -458,6 +470,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; $sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; + // Define begin binding date + if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; + } $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; $sql .= " AND fd.product_type <= 2"; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index bf28da1d5d2..b55d587c48b 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -227,6 +227,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$chartaccountcode."' AND aa3.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Add search filter like if ($search_societe) { $sql .= natural_search('s.nom', $search_societe); @@ -384,7 +388,7 @@ if ($result) { print ''; print ''; print ''; - print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth150', 'code2', 1, 0, 1); + print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1); //print ''; print ''; print ''; @@ -407,7 +411,7 @@ if ($result) { print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Country", $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder); - print_liste_field_titre("VATIntra", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("VATIntraShort", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'nowraponall '); print_liste_field_titre("IntoAccount", '', '', '', '', '', '', '', 'center '); $checkpicto = ''; @@ -553,14 +557,14 @@ if ($result) { print ''.dol_print_date($db->jdate($objp->datef), 'day').''; // Ref Product - print ''; + print ''; if ($product_static->id > 0) { print $product_static->getNomUrl(1); } - if ($objp->product_label) print '
'.$objp->product_label.''; + if ($objp->product_label) print '
'.$objp->product_label.''; print ''; - print ''; + print ''; $text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description)); $trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION) ? 32 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION; print $form->textwithtooltip(dol_trunc($text, $trunclength), $objp->description); diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 9fe07b18a37..4b06c49a0cb 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -174,6 +174,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expensereport as er ON er.rowid = erd.fk_e $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = erd.fk_code_ventilation"; $sql .= " WHERE er.date_debut >= '".$db->idate($search_date_start)."'"; $sql .= " AND er.date_debut <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND er.date_debut >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseReport::STATUS_CLOSED.")"; $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; @@ -243,6 +247,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expensereport as er ON er.rowid = erd.fk_e $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = erd.fk_code_ventilation"; $sql .= " WHERE er.date_debut >= '".$db->idate($search_date_start)."'"; $sql .= " AND er.date_debut <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND er.date_debut >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseReport::STATUS_CLOSED.")"; $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NOT NULL"; @@ -312,6 +320,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expensereport as er ON er.rowid = erd.fk_expensereport"; $sql .= " WHERE er.date_debut >= '".$db->idate($search_date_start)."'"; $sql .= " AND er.date_debut <= '".$db->idate($search_date_end)."'"; + // Define begin binding date + if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND er.date_debut >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; + } $sql .= " AND er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseReport::STATUS_CLOSED.")"; $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index e15bc779555..166a448d5ff 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -198,6 +198,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_type_fees as f ON f.id = erd.fk_c_type_f $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = er.fk_user_author"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON f.accountancy_code = aa.account_number AND aa.fk_pcg_version = '".$chartaccountcode."' AND aa.entity = ".$conf->entity; $sql .= " WHERE er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseReport::STATUS_CLOSED.") AND erd.fk_code_ventilation <= 0"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND er.date_debut >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Add search filter like if (strlen(trim($search_login))) { $sql .= natural_search("u.login", $search_login); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index b6bfbdc9942..29f1cb76d0b 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -124,6 +124,10 @@ $sql .= " WHERE ba.fk_accountancy_journal=".$id_journal; $sql .= ' AND b.amount != 0 AND ba.entity IN ('.getEntity('bank_account', 0).')'; // We don't share object for accountancy if ($date_start && $date_end) $sql .= " AND b.dateo >= '".$db->idate($date_start)."' AND b.dateo <= '".$db->idate($date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND b.dateo >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Already in bookkeeping or not if ($in_bookkeeping == 'already') { diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index d42ef92333c..4a1d2935f0f 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -101,6 +101,10 @@ $sql .= " AND erd.fk_code_ventilation > 0"; $sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy if ($date_start && $date_end) $sql .= " AND er.date_debut >= '".$db->idate($date_start)."' AND er.date_debut <= '".$db->idate($date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND er.date_debut >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Already in bookkeeping or not if ($in_bookkeeping == 'already') { diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index acdc3fbface..4c9e25725f2 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -111,6 +111,10 @@ if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { } if ($date_start && $date_end) $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Already in bookkeeping or not if ($in_bookkeeping == 'already') { diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 77a911db9b3..4b66feb9e3d 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -115,6 +115,10 @@ if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { // Non common s $sql .= " AND fd.product_type IN (0,1)"; if ($date_start && $date_end) $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Already in bookkeeping or not if ($in_bookkeeping == 'already') { diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index afcaca3df11..3deb3cc9d1c 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -245,6 +245,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn as ff ON ff.rowid = ffd.fk_ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = ffd.fk_code_ventilation"; $sql .= " WHERE ff.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND ff.datef <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND ff.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND ff.fk_statut > 0"; $sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy @@ -314,6 +318,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn as ff ON ff.rowid = ffd.fk_ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = ffd.fk_code_ventilation"; $sql .= " WHERE ff.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND ff.datef <= '".$db->idate($search_date_end)."'"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND ff.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} $sql .= " AND ff.fk_statut > 0"; $sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy @@ -383,6 +391,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn"; $sql .= " WHERE ff.datef >= '".$db->idate($search_date_start)."'"; $sql .= " AND ff.datef <= '".$db->idate($search_date_end)."'"; + // Define begin binding date + if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND ff.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; + } $sql .= " AND ff.fk_statut > 0"; $sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index de562d8dbbf..073b8791f2b 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -231,6 +231,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$chartaccountcode."' AND aa3.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; +// Define begin binding date +if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { + $sql .= " AND f.datef >= '".$db->idate($conf->global->ACCOUNTING_DATE_START_BINDING)."'"; +} // Add search filter like if ($search_societe) { $sql .= natural_search('s.nom', $search_societe); @@ -371,7 +375,7 @@ if ($result) { print ''; print ''; print ''; - print ''; + //print ''; print ''; if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; print ''; @@ -383,7 +387,7 @@ if ($result) { print ''; print ''; print ''; - print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth150', 'code2', 1, 0, 1); + print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1); //print ''; print ''; print ''; @@ -398,7 +402,7 @@ if ($result) { print ''; print_liste_field_titre("LineId", $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder); - print_liste_field_titre("InvoiceLabel", $_SERVER["PHP_SELF"], "f.libelle", "", $param, '', $sortfield, $sortorder); + //print_liste_field_titre("InvoiceLabel", $_SERVER["PHP_SELF"], "f.libelle", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, '', $sortfield, $sortorder, 'center '); print_liste_field_titre("ProductRef", $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder); //print_liste_field_titre("ProductLabel", $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder); @@ -407,7 +411,7 @@ if ($result) { print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Country", $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder); - print_liste_field_titre("VATIntra", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("VATIntraShort", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'nowraponall '); print_liste_field_titre("IntoAccount", '', '', '', '', '', '', '', 'center '); $checkpicto = ''; @@ -459,6 +463,7 @@ if ($result) { $facturefourn_static->ref = $objp->ref; $facturefourn_static->id = $objp->facid; $facturefourn_static->type = $objp->type; + $facturefourn_static->label = $objp->invoice_label; $code_buy_p_notset = ''; $objp->aarowid_suggest = ''; // Will be set later @@ -531,21 +536,22 @@ if ($result) { // Ref Invoice print ''.$facturefourn_static->getNomUrl(1).''; - print ''; + /*print ''; print $objp->invoice_label; print ''; + */ print ''.dol_print_date($db->jdate($objp->datef), 'day').''; // Ref Product - print ''; + print ''; if ($product_static->id > 0) print $product_static->getNomUrl(1); - if ($objp->product_label) print '
'.$objp->product_label.''; + if ($objp->product_label) print '
'.$objp->product_label.''; print ''; // Description - print ''; + print ''; $text = dolGetFirstLineOfText(dol_string_nohtmltag($objp->description)); $trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION) ? 32 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION; print $form->textwithtooltip(dol_trunc($text, $trunclength), $objp->description); diff --git a/htdocs/adherents/admin/adherent_emails.php b/htdocs/adherents/admin/adherent_emails.php index c6eec8b2d83..97411a27abf 100644 --- a/htdocs/adherents/admin/adherent_emails.php +++ b/htdocs/adherents/admin/adherent_emails.php @@ -88,6 +88,7 @@ if ($action == 'update' || $action == 'add') { $constnote = (GETPOSTISSET('constnote_'.$constname) ? GETPOST('constnote_'.$constname, 'none') : GETPOST('constnote')); $typetouse = empty($oldtypetonewone[$consttype]) ? $consttype : $oldtypetonewone[$consttype]; + $constvalue = preg_replace('/:member$/', '', $constvalue); $res = dolibarr_set_const($db, $constname, $constvalue, $typetouse, 0, $constnote, $conf->entity); @@ -100,23 +101,6 @@ if ($action == 'update' || $action == 'add') { } } -// Action to enable a submodule of the adherent module -if ($action == 'set') { - $result = dolibarr_set_const($db, GETPOST('name', 'alpha'), GETPOST('value'), '', 0, '', $conf->entity); - if ($result < 0) { - print $db->error(); - } -} - -// Action to disable a submodule of the adherent module -if ($action == 'unset') { - $result = dolibarr_del_const($db, GETPOST('name', 'alpha'), $conf->entity); - if ($result < 0) { - print $db->error(); - } -} - - /* * View diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 50ca013886b..2a177ebade4 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -25,7 +25,7 @@ /** * \file htdocs/adherents/card.php * \ingroup member - * \brief Page of member + * \brief Page of a member */ require '../main.inc.php'; @@ -850,9 +850,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Type print ''.$langs->trans("MemberType").''; - $listetype = $adht->liste_array(); + $listetype = $adht->liste_array(1); if (count($listetype)) { - print $form->selectarray("typeid", $listetype, GETPOST('typeid', 'int') ?GETPOST('typeid', 'int') : $typeid, count($listetype) > 1 ? 1 : 0); + print $form->selectarray("typeid", $listetype, (GETPOST('typeid', 'int') ? GETPOST('typeid', 'int') : $typeid), (count($listetype) > 1 ? 1 : 0), 0, 0, '', 0, 0, 0, '', '', 1); } else { print ''.$langs->trans("NoTypeDefinedGoToSetup").''; } @@ -862,7 +862,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $morphys["phy"] = $langs->trans("Physical"); $morphys["mor"] = $langs->trans("Moral"); print ''.$langs->trans("MemberNature")."\n"; - print $form->selectarray("morphy", $morphys, GETPOST('morphy', 'alpha') ?GETPOST('morphy', 'alpha') : $object->morphy, 1); + print $form->selectarray("morphy", $morphys, (GETPOST('morphy', 'alpha') ?GETPOST('morphy', 'alpha') : $object->morphy), 1, 0, 0, '', 0, 0, 0, '', '', 1); print "\n"; // Company @@ -870,7 +870,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Civility print ''.$langs->trans("UserTitle").''; - print $formcompany->select_civility(GETPOST('civility_id', 'int') ?GETPOST('civility_id', 'int') : $object->civility_id, 'civility_id').''; + print $formcompany->select_civility(GETPOST('civility_id', 'int') ? GETPOST('civility_id', 'int') : $object->civility_id, 'civility_id', 'maxwidth150', 1).''; print ''; // Lastname @@ -885,7 +885,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.$langs->trans("Gender").''; print ''; $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); - print $form->selectarray('gender', $arraygender, GETPOST('gender', 'alphanohtml'), 1); + print $form->selectarray('gender', $arraygender, GETPOST('gender', 'alphanohtml'), 1, 0, 0, '', 0, 0, 0, '', '', 1); print ''; // EMail @@ -1074,13 +1074,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $morphys["phy"] = $langs->trans("Physical"); $morphys["mor"] = $langs->trans("Moral"); print ''.$langs->trans("MemberNature").''; - print $form->selectarray("morphy", $morphys, (GETPOSTISSET("morphy") ? GETPOST("morphy", 'alpha') : $object->morphy)); + print $form->selectarray("morphy", $morphys, (GETPOSTISSET("morphy") ? GETPOST("morphy", 'alpha') : $object->morphy), 0, 0, 0, '', 0, 0, 0, '', '', 1); print ""; // Type print ''.$langs->trans("Type").''; if ($user->rights->adherent->creer) { - print $form->selectarray("typeid", $adht->liste_array(), (GETPOSTISSET("typeid") ? GETPOST("typeid", 'int') : $object->typeid)); + print $form->selectarray("typeid", $adht->liste_array(), (GETPOSTISSET("typeid") ? GETPOST("typeid", 'int') : $object->typeid), 0, 0, 0, '', 0, 0, 0, '', '', 1); } else { print $adht->getNomUrl(1); print ''; @@ -1092,7 +1092,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Civility print ''.$langs->trans("UserTitle").''; - print $formcompany->select_civility(GETPOSTISSET("civility_id") ? GETPOST("civility_id", 'alpha') : $object->civility_id)."\n"; + print $formcompany->select_civility(GETPOSTISSET("civility_id") ? GETPOST("civility_id", 'alpha') : $object->civility_id, 'civility_id', 'maxwidth150', 1); print ''; print ''; @@ -1108,7 +1108,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.$langs->trans("Gender").''; print ''; $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); - print $form->selectarray('gender', $arraygender, GETPOSTISSET('gender') ? GETPOST('gender', 'alphanohtml') : $object->gender, 1); + print $form->selectarray('gender', $arraygender, GETPOSTISSET('gender') ? GETPOST('gender', 'alphanohtml') : $object->gender, 1, 0, 0, '', 0, 0, 0, '', '', 1); print ''; // Photo @@ -1164,7 +1164,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.img_picto('', 'object_phoning').' phone_perso).'">'; // Mobile phone - print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print ''.$langs->trans("PhoneMobile").''; print ''.img_picto('', 'object_phoning_mobile').' phone_mobile).'">'; if (!empty($conf->socialnetworks->enabled)) { diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 25df072fbde..3f8a5ce1b25 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -112,7 +112,7 @@ class AdherentType extends CommonObject public function __construct($db) { $this->db = $db; - $this->statut = 1; + $this->status = 1; } /** @@ -280,7 +280,7 @@ class AdherentType extends CommonObject $error = 0; - $this->statut = (int) $this->statut; + $this->status = (int) $this->status; $this->label = trim($this->label); $this->db->begin(); @@ -347,7 +347,7 @@ class AdherentType extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."adherent_type "; $sql .= "SET "; - $sql .= "statut = ".$this->statut.","; + $sql .= "statut = ".$this->status.","; $sql .= "libelle = '".$this->db->escape($this->label)."',"; $sql .= "morphy = '".$this->db->escape($this->morphy)."',"; $sql .= "subscription = '".$this->db->escape($this->subscription)."',"; @@ -456,7 +456,6 @@ class AdherentType extends CommonObject $this->ref = $obj->rowid; $this->label = $obj->label; $this->morphy = $obj->morphy; - $this->statut = $obj->status; // deprecated $this->status = $obj->status; $this->duration = $obj->duration; $this->duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); @@ -483,9 +482,10 @@ class AdherentType extends CommonObject /** * Return list of members' type * - * @return array List of types of members + * @param int $status Filter on status of type + * @return array List of types of members */ - public function liste_array() + public function liste_array($status = -1) { // phpcs:enable global $conf, $langs; @@ -495,6 +495,7 @@ class AdherentType extends CommonObject $sql = "SELECT rowid, libelle as label"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type"; $sql .= " WHERE entity IN (".getEntity('member_type').")"; + if ($status >= 0) $sql .= " AND statut = ".((int) $status); $resql = $this->db->query($sql); if ($resql) { @@ -719,7 +720,7 @@ class AdherentType extends CommonObject $this->subscription = 1; $this->vote = 0; - $this->statut = 1; + $this->status = 1; // Members of this member type is just me $this->members = array( diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 9c5c6327747..60e10ba44ea 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -121,7 +121,7 @@ $arrayfields = array( 'd.gender'=>array('label'=>$langs->trans("Gender"), 'checked'=>0), 'd.company'=>array('label'=>$langs->trans("Company"), 'checked'=>1), 'd.login'=>array('label'=>$langs->trans("Login"), 'checked'=>1), - 'd.morphy'=>array('label'=>$langs->trans("MorPhy"), 'checked'=>1), + 'd.morphy'=>array('label'=>$langs->trans("MemberNature"), 'checked'=>1), 't.libelle'=>array('label'=>$langs->trans("Type"), 'checked'=>1), 'd.email'=>array('label'=>$langs->trans("Email"), 'checked'=>1), 'd.address'=>array('label'=>$langs->trans("Address"), 'checked'=>0), @@ -707,9 +707,20 @@ while ($i < min($num, $limit)) { print "".$obj->login."\n"; if (!$i) $totalarray['nbfield']++; } - // Moral/Physique + // Nature (Moral/Physical) if (!empty($arrayfields['d.morphy']['checked'])) { - print "".$memberstatic->getmorphylib($obj->morphy)."\n"; + print ''; + $s = ''; + if ($obj->morphy == 'phy') + { + $s .= ''.dol_substr($langs->trans("Physical"), 0, 1).''; + } + if ($obj->morphy == 'mor') + { + $s .= ''.dol_substr($langs->trans("Moral"), 0, 1).''; + } + print $s; + print "\n"; if (!$i) $totalarray['nbfield']++; } // Type label diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 06b8cecf7f3..f2cb8c440c2 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -890,7 +890,10 @@ if ($rowid > 0) { if (empty($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) || $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS != 'defaultforfoundationcountry') print '. '.$langs->trans("NoVatOnSubscription", 0).''; if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { $prodtmp = new Product($db); - $prodtmp->fetch($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); + $result = $prodtmp->fetch($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); + if ($result < 0) { + setEventMessage($prodtmp->error, 'errors'); + } print '. '.$langs->transnoentitiesnoconv("ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS", $prodtmp->getNomUrl(1)); // must use noentitiesnoconv to avoid to encode html into getNomUrl of product } print '
'; @@ -912,7 +915,10 @@ if ($rowid > 0) { if (empty($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) || $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS != 'defaultforfoundationcountry') print '. '.$langs->trans("NoVatOnSubscription", 0).''; if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { $prodtmp = new Product($db); - $prodtmp->fetch($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); + $result = $prodtmp->fetch($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); + if ($result < 0) { + setEventMessage($prodtmp->error, 'errors'); + } print '. '.$langs->transnoentitiesnoconv("ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS", $prodtmp->getNomUrl(1)); // must use noentitiesnoconv to avoid to encode html into getNomUrl of product } print '
'; diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 524ed0e466a..7d744b599de 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -61,7 +61,7 @@ if (!$sortfield) { $sortfield = "d.lastname"; } $label = GETPOST("label", "alpha"); $morphy = GETPOST("morphy", "alpha"); -$statut = GETPOST("statut", "int"); +$status = GETPOST("status", "int"); $subscription = GETPOST("subscription", "int"); $duration_value = GETPOST('duration_value', 'int'); $duration_unit = GETPOST('duration_unit', 'alpha'); @@ -108,7 +108,7 @@ if ($cancel) { if ($action == 'add' && $user->rights->adherent->configurer) { $object->label = trim($label); $object->morphy = trim($morphy); - $object->statut = (int) $statut; + $object->status = (int) $status; $object->subscription = (int) $subscription; $object->duration_value = $duration_value; $object->duration_unit = $duration_unit; @@ -157,7 +157,7 @@ if ($action == 'update' && $user->rights->adherent->configurer) { $object->label = trim($label); $object->morphy = trim($morphy); - $object->statut = (int) $statut; + $object->status = (int) $status; $object->subscription = (int) $subscription; $object->duration_value = $duration_value; $object->duration_unit = $duration_unit; @@ -205,7 +205,6 @@ $formproduct = new FormProduct($db); llxHeader('', $langs->trans("MembersTypeSetup"), 'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros'); - // List of members type if (!$rowid && $action != 'create' && $action != 'edit') { //dol_fiche_head(''); @@ -317,7 +316,7 @@ if ($action == 'create') { print ''.$langs->trans("Label").''; print ''.$langs->trans("Status").''; - print $form->selectarray('statut', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), 1); + print $form->selectarray('status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), 1); print ''; // Morphy @@ -448,7 +447,7 @@ if ($rowid > 0) { } // Add - if ($user->rights->adherent->configurer && !empty($object->statut)) { + if ($user->rights->adherent->configurer && !empty($object->status)) { print '
'.$langs->trans("AddMember").'
'; } else { print '
'.$langs->trans("AddMember").'
'; @@ -470,7 +469,7 @@ if ($rowid > 0) { $sql = "SELECT d.rowid, d.login, d.firstname, d.lastname, d.societe as company,"; $sql .= " d.datefin,"; - $sql .= " d.email, d.fk_adherent_type as type_id, d.morphy, d.statut,"; + $sql .= " d.email, d.fk_adherent_type as type_id, d.morphy, d.statut as status,"; $sql .= " t.libelle as type, t.subscription"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent as d, ".MAIN_DB_PREFIX."adherent_type as t"; $sql .= " WHERE d.fk_adherent_type = t.rowid "; @@ -643,13 +642,13 @@ if ($rowid > 0) { // Statut print ''; - print $adh->LibStatut($objp->statut, $objp->subscription, $datefin, 2); + print $adh->LibStatut($objp->status, $objp->subscription, $datefin, 2); print ""; // Date end subscription if ($datefin) { print ''; - if ($datefin < dol_now() && $objp->statut > 0) { + if ($datefin < dol_now() && $objp->status > 0) { print dol_print_date($datefin, 'day')." ".img_warning($langs->trans("SubscriptionLate")); } else { print dol_print_date($datefin, 'day'); @@ -659,7 +658,7 @@ if ($rowid > 0) { print ''; if ($objp->subscription == 'yes') { print $langs->trans("SubscriptionNotReceived"); - if ($objp->statut > 0) print " ".img_warning(); + if ($objp->status > 0) print " ".img_warning(); } else { print ' '; } @@ -720,7 +719,7 @@ if ($rowid > 0) { print ''.$langs->trans("Label").''; print ''.$langs->trans("Status").''; - print $form->selectarray('statut', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $object->statut); + print $form->selectarray('status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $object->status); print ''; // Morphy @@ -741,7 +740,7 @@ if ($rowid > 0) { print ''.$langs->trans("Duration").''; print ' '; - print $formproduct->selectMeasuringUnits("duration_unit", "time", $object->duration_unit, 0, 1); + print $formproduct->selectMeasuringUnits("duration_unit", "time", ($object->duration_unit === '' ? 'y' : $object->duration_unit), 0, 1); print ''; print ''.$langs->trans("Description").''; diff --git a/htdocs/admin/bank.php b/htdocs/admin/bank.php index 6c91367f6c2..53110b9cad8 100644 --- a/htdocs/admin/bank.php +++ b/htdocs/admin/bank.php @@ -350,13 +350,13 @@ foreach ($dirmodels as $reldir) { // Active if (in_array($name, $def)) { print ''."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''; } else { print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print ""; } @@ -365,7 +365,7 @@ foreach ($dirmodels as $reldir) { if ($conf->global->BANKADDON_PDF == $name) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/bom.php b/htdocs/admin/bom.php index 46db7dd6c6c..3aebadf25a6 100644 --- a/htdocs/admin/bom.php +++ b/htdocs/admin/bom.php @@ -370,13 +370,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''; } else { print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print ""; } @@ -386,7 +386,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/bom_extrafields.php b/htdocs/admin/bom_extrafields.php index 70d7720e994..70303f1dcda 100644 --- a/htdocs/admin/bom_extrafields.php +++ b/htdocs/admin/bom_extrafields.php @@ -68,7 +68,7 @@ $linkback = 'trans("ExtraFields"), -1, 'account'); diff --git a/htdocs/admin/boxes.php b/htdocs/admin/boxes.php index a45208db3b9..ca3fd795b8b 100644 --- a/htdocs/admin/boxes.php +++ b/htdocs/admin/boxes.php @@ -95,8 +95,10 @@ if ($action == 'add') { { if (!$error && $fk_user != '') { + $arrayofexistingboxid = array(); $nbboxonleft = $nbboxonright = 0; - $sql = "SELECT box_order FROM ".MAIN_DB_PREFIX."boxes WHERE position = ".$pos." AND fk_user = ".$fk_user." AND entity = ".$conf->entity; + $sql = "SELECT box_id, box_order FROM ".MAIN_DB_PREFIX."boxes"; + $sql .= " WHERE position = ".$pos." AND fk_user = ".$fk_user." AND entity = ".$conf->entity; dol_syslog("boxes.php activate box", LOG_DEBUG); $resql = $db->query($sql); if ($resql) @@ -106,21 +108,26 @@ if ($action == 'add') { $boxorder = $obj->box_order; if (preg_match('/A/', $boxorder)) $nbboxonleft++; if (preg_match('/B/', $boxorder)) $nbboxonright++; + $arrayofexistingboxid[$obj->box_id] = 1; } } else dol_print_error($db); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes ("; - $sql .= "box_id, position, box_order, fk_user, entity"; - $sql .= ") values ("; - $sql .= $boxid['value'].", ".$pos.", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".$fk_user.", ".$conf->entity; - $sql .= ")"; + if (empty($arrayofexistingboxid[$boxid['value']])) { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes ("; + $sql .= "box_id, position, box_order, fk_user, entity"; + $sql .= ") values ("; + $sql .= $boxid['value'].", ".$pos.", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".$fk_user.", ".$conf->entity; + $sql .= ")"; - dol_syslog("boxes.php activate box", LOG_DEBUG); - $resql = $db->query($sql); - if (!$resql) - { - setEventMessages($db->lasterror(), null, 'errors'); - $error++; + dol_syslog("boxes.php activate box", LOG_DEBUG); + $resql = $db->query($sql); + if (!$resql) + { + setEventMessages($db->lasterror(), null, 'errors'); + $error++; + } + } else { + dol_syslog("boxes.php activate box - already exists in database", LOG_DEBUG); } } } @@ -314,7 +321,7 @@ $boxactivated = InfoBox::listBoxes($db, 'activated', -1, null); print "
\n"; print "\n\n".''."\n"; -print load_fiche_titre($langs->trans("BoxesAvailable")); +print load_fiche_titre($langs->trans("BoxesAvailable"), '', ''); print '
'."\n"; print ''."\n"; @@ -341,7 +348,7 @@ foreach ($boxtoadd as $box) print "\n".''."\n"; print ''."\n"; - print ''.img_object("", $logo).' '.$langs->transnoentitiesnoconv($box->boxlabel); + print ''.img_object("", $logo, 'height="14px"').' '.$langs->transnoentitiesnoconv($box->boxlabel); if (!empty($box->class) && preg_match('/graph_/', $box->class)) print ' ('.$langs->trans("Graph").')'; print ''."\n"; print ''; @@ -355,7 +362,7 @@ foreach ($boxtoadd as $box) // For each possible position, an activation link is displayed if the box is not already active for that position print ''; - print $form->selectarray("boxid[".$box->box_id."][pos]", $pos_name, 0, 1, 0, 0, '', 1)."\n"; + print $form->selectarray("boxid[".$box->box_id."][pos]", $pos_name, -1, 1, 0, 0, '', 1)."\n"; print ''."\n"; print ''; @@ -377,7 +384,7 @@ print "\n".''."\n"; //var_dump($boxactivated); print "
\n\n"; -print load_fiche_titre($langs->trans("BoxesActivated")); +print load_fiche_titre($langs->trans("BoxesActivated"), '', ''); print '
'; print ''."\n"; @@ -403,7 +410,7 @@ foreach ($boxactivated as $key => $box) print "\n".''."\n"; print ''; - print ''; print ''; } else { print '"; } @@ -451,7 +451,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index 1138eb44ddc..f2e69f81707 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -109,6 +109,12 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha')) foreach ($arrayofimages as $varforimage) { + if ($_FILES[$varforimage]["name"] && ! preg_match('/(\.jpeg|\.jpg|\.png)$/i', $_FILES[$varforimage]["name"])) { // Logo can be used on a lot of different places. Only jpg and png can be supported. + $langs->load("errors"); + setEventMessages($langs->trans("ErrorBadImageFormat"), null, 'errors'); + break; + } + if ($_FILES[$varforimage]["tmp_name"]) { $reg = array(); @@ -473,10 +479,17 @@ if (!empty($mysoc->logo_mini)) { print ''; } print ''; -} else { - print '
'; - print ''; - print '
'; +} elseif (!empty($mysoc->logo)) { + if (file_exists($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) { + print '
'; + print ''; + print '
'; + print ''; + } else { + print '
'; + print ''; + print '
'; + } } print ''; print ''; @@ -493,10 +506,18 @@ if (!empty($mysoc->logo_squarred_mini)) { print ''; } print ''; -} else { - print '
'; - print ''; - print '
'; +} elseif (!empty($mysoc->logo_squarred)) { + if (file_exists($conf->mycompany->dir_output.'/logos/'.$mysoc->logo_squarred)) { + print '
'; + print ''; + print '
'; + print ''; + } + else { + print '
'; + print ''; + print '
'; + } } print ''; print ''; diff --git a/htdocs/admin/confexped.php b/htdocs/admin/confexped.php index 620a6fe01ea..d2ea8da6d3f 100644 --- a/htdocs/admin/confexped.php +++ b/htdocs/admin/confexped.php @@ -92,7 +92,7 @@ print load_fiche_titre($langs->trans("SendingsSetup"), $linkback, 'title_setup') print '
'; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'general', $langs->trans("Sendings"), -1, 'sending'); +dol_fiche_head($head, 'general', $langs->trans("Sendings"), -1, 'shipment'); // Miscellaneous parameters diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index f07011f4968..19ae30d7674 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -365,13 +365,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; } else { print '"; } @@ -381,7 +381,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 7f468cc1f1a..b6d5df3644a 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -12,6 +12,7 @@ * Copyright (C) 2015 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud * Copyright (C) 2019 Frédéric France + * Copyright (C) 2020 Open-Dsi * * 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 @@ -90,7 +91,11 @@ $hookmanager->initHooks(array('admin')); // Put here declaration of dictionaries properties // Sort order to show dictionary (0 is space). All other dictionaries (added by modules) will be at end of this. -$taborder = array(9, 0, 4, 3, 2, 0, 1, 8, 19, 16, 27, 38, 0, 5, 11, 0, 32, 33, 34, 0, 6, 0, 29, 0, 7, 24, 28, 17, 35, 36, 0, 10, 23, 12, 13, 0, 14, 0, 22, 20, 18, 21, 0, 15, 30, 0, 37, 0, 25, 0); +if (! empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { + $taborder = array(9, 0, 4, 3, 2, 0, 1, 8, 19, 16, 39, 27, 40, 38, 0, 5, 11, 0, 32, 33, 34, 0, 6, 0, 29, 0, 7, 24, 28, 17, 35, 36, 0, 10, 23, 12, 13, 0, 14, 0, 22, 20, 18, 21, 0, 15, 30, 0, 37, 0, 25, 0); +} else { + $taborder = array(9, 0, 4, 3, 2, 0, 1, 8, 19, 16, 27, 38, 0, 5, 11, 0, 32, 33, 34, 0, 6, 0, 29, 0, 7, 24, 28, 17, 35, 36, 0, 10, 23, 12, 13, 0, 14, 0, 22, 20, 18, 21, 0, 15, 30, 0, 37, 0, 25, 0); +} // Name of SQL tables of dictionaries $tabname = array(); @@ -133,6 +138,8 @@ $tabname[35] = MAIN_DB_PREFIX."c_exp_tax_cat"; $tabname[36] = MAIN_DB_PREFIX."c_exp_tax_range"; $tabname[37] = MAIN_DB_PREFIX."c_units"; $tabname[38] = MAIN_DB_PREFIX."c_socialnetworks"; +$tabname[39] = MAIN_DB_PREFIX."c_prospectcontactlevel"; +$tabname[40] = MAIN_DB_PREFIX."c_stcommcontact"; // Dictionary labels $tablib = array(); @@ -174,6 +181,8 @@ $tablib[35] = "DictionaryExpenseTaxCat"; $tablib[36] = "DictionaryExpenseTaxRange"; $tablib[37] = "DictionaryMeasuringUnits"; $tablib[38] = "DictionarySocialNetworks"; +$tablib[39] = "DictionaryProspectContactLevel"; +$tablib[40] = "DictionaryProspectContactStatus"; // Requests to extract data $tabsql = array(); @@ -203,7 +212,7 @@ $tabsql[23] = "SELECT t.rowid as rowid, t.taux, t.revenuestamp_type, c.label as $tabsql[24] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_type_resource"; $tabsql[25] = "SELECT rowid as rowid, code, label, active, module FROM ".MAIN_DB_PREFIX."c_type_container as t WHERE t.entity IN (".getEntity('c_type_container').")"; //$tabsql[26]= "SELECT rowid as rowid, code, label, short_label, active FROM ".MAIN_DB_PREFIX."c_units"; -$tabsql[27] = "SELECT id as rowid, code, libelle, active FROM ".MAIN_DB_PREFIX."c_stcomm"; +$tabsql[27] = "SELECT id as rowid, code, libelle, picto, active FROM ".MAIN_DB_PREFIX."c_stcomm"; $tabsql[28] = "SELECT h.rowid as rowid, h.code, h.label, h.affect, h.delay, h.newbymonth, h.fk_country as country_id, c.code as country_code, c.label as country, h.active FROM ".MAIN_DB_PREFIX."c_holiday_types as h LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON h.fk_country=c.rowid"; $tabsql[29] = "SELECT rowid as rowid, code, label, percent, position, active FROM ".MAIN_DB_PREFIX."c_lead_status"; $tabsql[30] = "SELECT rowid, code, name, paper_size, orientation, metric, leftmargin, topmargin, nx, ny, spacex, spacey, width, height, font_size, custom_x, custom_y, active FROM ".MAIN_DB_PREFIX."c_format_cards"; @@ -215,6 +224,8 @@ $tabsql[35] = "SELECT c.rowid, c.label, c.active, c.entity FROM ".MAIN_DB_PREFIX $tabsql[36] = "SELECT r.rowid, r.fk_c_exp_tax_cat, r.range_ik, r.active, r.entity FROM ".MAIN_DB_PREFIX."c_exp_tax_range r"; $tabsql[37] = "SELECT r.rowid, r.code, r.label, r.short_label, r.unit_type, r.scale, r.active FROM ".MAIN_DB_PREFIX."c_units r"; $tabsql[38] = "SELECT rowid, entity, code, label, url, icon, active FROM ".MAIN_DB_PREFIX."c_socialnetworks"; +$tabsql[39] = "SELECT code, label as libelle, sortorder, active FROM ".MAIN_DB_PREFIX."c_prospectcontactlevel"; +$tabsql[40] = "SELECT id as rowid, code, libelle, picto, active FROM ".MAIN_DB_PREFIX."c_stcommcontact"; // Criteria to sort dictionaries $tabsqlsort = array(); @@ -256,6 +267,8 @@ $tabsqlsort[35] = "c.label ASC"; $tabsqlsort[36] = "r.fk_c_exp_tax_cat ASC, r.range_ik ASC"; $tabsqlsort[37] = "r.unit_type ASC, r.scale ASC, r.code ASC"; $tabsqlsort[38] = "rowid, code ASC"; +$tabsqlsort[39] = "sortorder ASC"; +$tabsqlsort[40] = "code ASC"; // Field names in select result for dictionary display $tabfield = array(); @@ -285,7 +298,7 @@ $tabfield[23] = "country_id,country,taux,revenuestamp_type,accountancy_code_sell $tabfield[24] = "code,label"; $tabfield[25] = "code,label"; //$tabfield[26]= "code,label,short_label"; -$tabfield[27] = "code,libelle"; +$tabfield[27] = "code,libelle,picto"; $tabfield[28] = "code,label,affect,delay,newbymonth,country_id,country"; $tabfield[29] = "code,label,percent,position"; $tabfield[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; @@ -297,6 +310,8 @@ $tabfield[35] = "label"; $tabfield[36] = "range_ik,fk_c_exp_tax_cat"; $tabfield[37] = "code,label,short_label,unit_type,scale"; $tabfield[38] = "code,label,url,icon,entity"; +$tabfield[39] = "code,libelle,sortorder"; +$tabfield[40] = "code,libelle,picto"; // Edit field names for editing a record $tabfieldvalue = array(); @@ -326,7 +341,7 @@ $tabfieldvalue[23] = "country,taux,revenuestamp_type,accountancy_code_sell,accou $tabfieldvalue[24] = "code,label"; $tabfieldvalue[25] = "code,label"; //$tabfieldvalue[26]= "code,label,short_label"; -$tabfieldvalue[27] = "code,libelle"; +$tabfieldvalue[27] = "code,libelle,picto"; $tabfieldvalue[28] = "code,label,affect,delay,newbymonth,country"; $tabfieldvalue[29] = "code,label,percent,position"; $tabfieldvalue[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; @@ -338,6 +353,8 @@ $tabfieldvalue[35] = "label"; $tabfieldvalue[36] = "range_ik,fk_c_exp_tax_cat"; $tabfieldvalue[37] = "code,label,short_label,unit_type,scale"; $tabfieldvalue[38] = "code,label,url,icon"; +$tabfieldvalue[39] = "code,libelle,sortorder"; +$tabfieldvalue[40] = "code,libelle,picto"; // Field names in the table for inserting a record $tabfieldinsert = array(); @@ -367,7 +384,7 @@ $tabfieldinsert[23] = "fk_pays,taux,revenuestamp_type,accountancy_code_sell,acco $tabfieldinsert[24] = "code,label"; $tabfieldinsert[25] = "code,label"; //$tabfieldinsert[26]= "code,label,short_label"; -$tabfieldinsert[27] = "code,libelle"; +$tabfieldinsert[27] = "code,libelle,picto"; $tabfieldinsert[28] = "code,label,affect,delay,newbymonth,fk_country"; $tabfieldinsert[29] = "code,label,percent,position"; $tabfieldinsert[30] = "code,name,paper_size,orientation,metric,leftmargin,topmargin,nx,ny,spacex,spacey,width,height,font_size,custom_x,custom_y"; @@ -380,6 +397,8 @@ $tabfieldinsert[35] = "label"; $tabfieldinsert[36] = "range_ik,fk_c_exp_tax_cat"; $tabfieldinsert[37] = "code,label,short_label,unit_type,scale"; $tabfieldinsert[38] = "code,label,url,icon,entity"; +$tabfieldinsert[39] = "code,label,sortorder"; +$tabfieldinsert[40] = "code,libelle,picto"; // Rowid name of field depending if field is autoincrement on or off.. // Use "" if id field is "rowid" and has autoincrement on @@ -423,6 +442,8 @@ $tabrowid[35] = ""; $tabrowid[36] = ""; $tabrowid[37] = ""; $tabrowid[38] = ""; +$tabrowid[39] = "code"; +$tabrowid[40] = "id"; // Condition to show dictionary in setup page $tabcond = array(); @@ -464,6 +485,8 @@ $tabcond[35] = !empty($conf->expensereport->enabled); $tabcond[36] = !empty($conf->expensereport->enabled); $tabcond[37] = !empty($conf->product->enabled); $tabcond[38] = !empty($conf->socialnetworks->enabled); +$tabcond[39] = (! empty($conf->societe->enabled) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)); +$tabcond[40] = ! empty($conf->societe->enabled); // List of help for fields $tabhelp = array(); @@ -493,7 +516,7 @@ $tabhelp[23] = array('revenuestamp_type'=>'FixedOrPercent'); $tabhelp[24] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[25] = array('code'=>$langs->trans('EnterAnyCode')); //$tabhelp[26] = array('code'=>$langs->trans("EnterAnyCode")); -$tabhelp[27] = array('code'=>$langs->trans("EnterAnyCode")); +$tabhelp[27] = array('code'=>$langs->trans("EnterAnyCode"),'picto'=>$langs->trans("PictoHelp")); $tabhelp[28] = array('affect'=>$langs->trans("FollowedByACounter"), 'delay'=>$langs->trans("MinimumNoticePeriod"), 'newbymonth'=>$langs->trans("NbAddedAutomatically")); $tabhelp[29] = array('code'=>$langs->trans("EnterAnyCode"), 'percent'=>$langs->trans("OpportunityPercent"), 'position'=>$langs->trans("PositionIntoComboList")); $tabhelp[30] = array('code'=>$langs->trans("EnterAnyCode"), 'name'=>$langs->trans("LabelName"), 'paper_size'=>$langs->trans("LabelPaperSize")); @@ -505,6 +528,8 @@ $tabhelp[35] = array(); $tabhelp[36] = array('range_ik'=>$langs->trans('PrevRangeToThisRange')); $tabhelp[37] = array('code'=>$langs->trans("EnterAnyCode"), 'unit_type' => $langs->trans('MeasuringUnitTypeDesc'), 'scale' => $langs->trans('MeasuringScaleDesc')); $tabhelp[38] = array('code'=>$langs->trans("EnterAnyCode"), 'url' => $langs->trans('UrlSocialNetworksDesc'), 'icon' => $langs->trans('FafaIconSocialNetworksDesc')); +$tabhelp[39] = array('code'=>$langs->trans("EnterAnyCode")); +$tabhelp[40] = array('code'=>$langs->trans("EnterAnyCode"),'picto'=>$langs->trans("PictoHelp")); // List of check for fields (NOT USED YET) $tabfieldcheck = array(); @@ -546,6 +571,8 @@ $tabfieldcheck[35] = array(); $tabfieldcheck[36] = array(); $tabfieldcheck[37] = array(); $tabfieldcheck[38] = array(); +$tabfieldcheck[39] = array(); +$tabfieldcheck[40] = array(); // Complete all arrays with entries found into modules complete_dictionary_with_modules($taborder, $tabname, $tablib, $tabsql, $tabsqlsort, $tabfield, $tabfieldvalue, $tabfieldinsert, $tabrowid, $tabcond, $tabhelp, $tabfieldcheck); @@ -647,7 +674,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($value == 'dayrule' && empty($_POST['dayrule'])) continue; if ($value == 'sortorder') continue; // For a column name 'sortorder', we use the field name 'position' if ((!isset($_POST[$value]) || $_POST[$value] == '') - && (!in_array($listfield[$f], array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking')) // Fields that are not mandatory + && (!in_array($listfield[$f], array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto')) // Fields that are not mandatory && (!($id == 10 && $listfield[$f] == 'code')) // Code is mandatory fir table 10 ) ) { diff --git a/htdocs/admin/events.php b/htdocs/admin/events.php index 75976f0b07b..92ff5c7631a 100644 --- a/htdocs/admin/events.php +++ b/htdocs/admin/events.php @@ -102,7 +102,7 @@ print ''; $head = security_prepare_head(); -dol_fiche_head($head, 'audit', $langs->trans("Security"), -1); +dol_fiche_head($head, 'audit', '', -1); print '
'.img_object("", $logo).' '.$langs->transnoentitiesnoconv($box->boxlabel); + print ''.img_object("", $logo, 'height="14px"').' '.$langs->transnoentitiesnoconv($box->boxlabel); if (!empty($box->class) && preg_match('/graph_/', $box->class)) print ' ('.$langs->trans("Graph").')'; print ''; @@ -436,7 +443,7 @@ print '
'; // Other parameters print "\n\n".''."\n"; -print load_fiche_titre($langs->trans("Other")); +print load_fiche_titre($langs->trans("Other"), '', ''); print ''; print ''; print ''; diff --git a/htdocs/admin/clicktodial.php b/htdocs/admin/clicktodial.php index 4c386aa7792..5fa7b78ca8b 100644 --- a/htdocs/admin/clicktodial.php +++ b/htdocs/admin/clicktodial.php @@ -60,6 +60,8 @@ if ($action == 'setvalue' && $user->admin) * View */ +$form = new Form($db); + $user->fetch_clicktodial(); $wikihelp = 'EN:Module_ClickToDial_En|FR:Module_ClickToDial|ES:Módulo_ClickTodial_Es'; @@ -75,6 +77,7 @@ print ''; print ''; print ''; +print '
'; print ''; print ''; print ''; @@ -107,6 +110,7 @@ print $langs->trans("Example").':
http://myphoneserver/mypage?login=__LOGIN__ print ''; print '
'.$langs->trans("Name").'
'; +print '
'; print '

'; diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 9acecc11604..1e6d21b6f58 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -435,13 +435,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print '
'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "
'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "
'; print ""; diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php index 21cb83c356a..32ab8c2e277 100644 --- a/htdocs/admin/expedition.php +++ b/htdocs/admin/expedition.php @@ -184,7 +184,7 @@ print load_fiche_titre($langs->trans("SendingsSetup"), $linkback, 'title_setup') print '
'; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'shipment', $langs->trans("Sendings"), -1, 'sending'); +dol_fiche_head($head, 'shipment', $langs->trans("Sendings"), -1, 'shipment'); // Shipment numbering model @@ -373,13 +373,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; } else { print '"; } @@ -389,7 +389,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/expedition_extrafields.php b/htdocs/admin/expedition_extrafields.php index 6ff8cd42669..e40519f9104 100644 --- a/htdocs/admin/expedition_extrafields.php +++ b/htdocs/admin/expedition_extrafields.php @@ -76,7 +76,7 @@ print "
\n"; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'attributes_shipment', $langs->trans("Sendings"), -1, 'sending'); +dol_fiche_head($head, 'attributes_shipment', $langs->trans("Sendings"), -1, 'shipment'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/expeditiondet_extrafields.php b/htdocs/admin/expeditiondet_extrafields.php index 8b27aec895e..03cd140d0ee 100644 --- a/htdocs/admin/expeditiondet_extrafields.php +++ b/htdocs/admin/expeditiondet_extrafields.php @@ -77,7 +77,7 @@ print "
\n"; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'attributeslines_shipment', $langs->trans("Sendings"), -1, 'sending'); +dol_fiche_head($head, 'attributeslines_shipment', $langs->trans("Sendings"), -1, 'shipment'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index f25a87b6a12..ac24f1e0404 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -500,13 +500,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; } else { print '"; } @@ -516,7 +516,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("SetAsDefault"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("SetAsDefault"), 'off').''; } print ''; diff --git a/htdocs/admin/holiday.php b/htdocs/admin/holiday.php index 5ad46e5bab6..c8094b99239 100644 --- a/htdocs/admin/holiday.php +++ b/htdocs/admin/holiday.php @@ -378,13 +378,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; } else { print '"; } @@ -394,7 +394,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/livraison.php b/htdocs/admin/livraison.php index 66f3a44cdcf..5e0c0ce4784 100644 --- a/htdocs/admin/livraison.php +++ b/htdocs/admin/livraison.php @@ -179,7 +179,7 @@ print load_fiche_titre($langs->trans("SendingsSetup"), $linkback, 'title_setup') print '
'; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'receivings', $langs->trans("Receivings"), -1, 'sending'); +dol_fiche_head($head, 'receivings', $langs->trans("Receivings"), -1, 'shipment'); // Delivery numbering model diff --git a/htdocs/admin/livraison_extrafields.php b/htdocs/admin/livraison_extrafields.php index 5594273320f..3b6d03ac98e 100644 --- a/htdocs/admin/livraison_extrafields.php +++ b/htdocs/admin/livraison_extrafields.php @@ -76,7 +76,7 @@ print "
\n"; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'attributes_receivings', $langs->trans("Receivings"), -1, 'sending'); +dol_fiche_head($head, 'attributes_receivings', $langs->trans("Receivings"), -1, 'shipment'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/livraisondet_extrafields.php b/htdocs/admin/livraisondet_extrafields.php index 2c9aae6b253..ebed8de9608 100644 --- a/htdocs/admin/livraisondet_extrafields.php +++ b/htdocs/admin/livraisondet_extrafields.php @@ -77,7 +77,7 @@ print "
\n"; $head = expedition_admin_prepare_head(); -dol_fiche_head($head, 'attributeslines_receivings', $langs->trans("Receivings"), -1, 'sending'); +dol_fiche_head($head, 'attributeslines_receivings', $langs->trans("Receivings"), -1, 'shipment'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 4334236f813..9e2f443b5a6 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -153,20 +153,20 @@ $sourceList = array(); // We save list of template email Dolibarr can manage. This list can found by a grep into code on "->param['models']" $elementList = array(); -if ($conf->propal->enabled) $elementList['propal_send'] = $langs->trans('MailToSendProposal'); -if ($conf->commande->enabled) $elementList['order_send'] = $langs->trans('MailToSendOrder'); -if ($conf->facture->enabled) $elementList['facture_send'] = $langs->trans('MailToSendInvoice'); +if ($conf->propal->enabled && $user->rights->propal->lire) $elementList['propal_send'] = $langs->trans('MailToSendProposal'); +if ($conf->commande->enabled && $user->rights->commande->lire) $elementList['order_send'] = $langs->trans('MailToSendOrder'); +if ($conf->facture->enabled && $user->rights->facture->lire) $elementList['facture_send'] = $langs->trans('MailToSendInvoice'); if ($conf->expedition->enabled) $elementList['shipping_send'] = $langs->trans('MailToSendShipment'); if ($conf->reception->enabled) $elementList['reception_send'] = $langs->trans('MailToSendReception'); if ($conf->ficheinter->enabled) $elementList['fichinter_send'] = $langs->trans('MailToSendIntervention'); if ($conf->supplier_proposal->enabled) $elementList['supplier_proposal_send'] = $langs->trans('MailToSendSupplierRequestForQuotation'); -if ($conf->fournisseur->enabled && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_order->enabled) $elementList['order_supplier_send'] = $langs->trans('MailToSendSupplierOrder'); -if ($conf->fournisseur->enabled && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_invoice->enabled) $elementList['invoice_supplier_send'] = $langs->trans('MailToSendSupplierInvoice'); -if ($conf->societe->enabled) $elementList['thirdparty'] = $langs->trans('MailToThirdparty'); -if ($conf->adherent->enabled) $elementList['member'] = $langs->trans('MailToMember'); -if ($conf->contrat->enabled) $elementList['contract'] = $langs->trans('MailToSendContract'); +if (($conf->fournisseur->enabled && $user->rights->fournisseur->commande->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || ($conf->supplier_order->enabled && $user->rights->supplier_order->lire)) $elementList['order_supplier_send'] = $langs->trans('MailToSendSupplierOrder'); +if (($conf->fournisseur->enabled && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || ($conf->supplier_invoice->enabled && $user->rights->supplier_invoice->lire)) $elementList['invoice_supplier_send'] = $langs->trans('MailToSendSupplierInvoice'); +if ($conf->societe->enabled && $user->rights->societe->lire) $elementList['thirdparty'] = $langs->trans('MailToThirdparty'); +if ($conf->adherent->enabled && $user->rights->adherent->lire) $elementList['member'] = $langs->trans('MailToMember'); +if ($conf->contrat->enabled && $user->rights->contrat->lire) $elementList['contract'] = $langs->trans('MailToSendContract'); if ($conf->projet->enabled) $elementList['project'] = $langs->trans('MailToProject'); -if ($conf->ticket->enabled) $elementList['ticket_send'] = $langs->trans('MailToTicket'); +if ($conf->ticket->enabled && $user->rights->ticket->read) $elementList['ticket_send'] = $langs->trans('MailToTicket'); $elementList['user'] = $langs->trans('MailToUser'); $parameters = array('elementList'=>$elementList); @@ -540,10 +540,11 @@ print ""; // Show fields for topic, join files and body $fieldsforcontent = array('topic', 'joinfiles', 'content'); -if (!empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) { $fieldsforcontent = array('content', 'content_lines'); } +if (!empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) { $fieldsforcontent = array('topic', 'joinfiles', 'content', 'content_lines'); } foreach ($fieldsforcontent as $tmpfieldlist) { print ''; + $filterfound = 0; foreach ($fieldlist as $field => $value) { - if ($value == 'label') print ''; - elseif ($value == 'lang') - { + if ($value == 'label') { + print ''; + } elseif ($value == 'lang') { print ''; - } elseif ($value == 'fk_user') - { + } elseif ($value == 'fk_user') { print ''; - } elseif ($value == 'topic') print ''; - elseif ($value == 'type_template') - { + } elseif ($value == 'topic') { + print ''; + } elseif ($value == 'type_template') { print ''; - } elseif (!in_array($value, array('content', 'content_lines'))) print ''; + } elseif (!in_array($value, array('content', 'content_lines'))) { + print ''; + } } + if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) print ''; + // Action column print ''; } else { print '"; } @@ -387,7 +387,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; diff --git a/htdocs/admin/mrp_extrafields.php b/htdocs/admin/mrp_extrafields.php index 55df2a065d0..cab7232f569 100644 --- a/htdocs/admin/mrp_extrafields.php +++ b/htdocs/admin/mrp_extrafields.php @@ -68,7 +68,7 @@ $linkback = 'trans("ExtraFields"), -1, 'account'); diff --git a/htdocs/admin/paymentbybanktransfer.php b/htdocs/admin/paymentbybanktransfer.php index 3464a0857b7..a19a69c75a5 100644 --- a/htdocs/admin/paymentbybanktransfer.php +++ b/htdocs/admin/paymentbybanktransfer.php @@ -291,7 +291,7 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; @@ -299,7 +299,7 @@ foreach ($dirmodels as $reldir) else { print '"; } @@ -311,7 +311,7 @@ foreach ($dirmodels as $reldir) } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; } print ''; diff --git a/htdocs/admin/perms.php b/htdocs/admin/perms.php index d5bc8fd938b..0662a571cc9 100644 --- a/htdocs/admin/perms.php +++ b/htdocs/admin/perms.php @@ -116,7 +116,7 @@ $db->commit(); $head = security_prepare_head(); -dol_fiche_head($head, 'default', $langs->trans("Security"), -1); +dol_fiche_head($head, 'default', '', -1); // Show warning about external users diff --git a/htdocs/admin/prelevement.php b/htdocs/admin/prelevement.php index 42c7b52cb75..3419551f627 100644 --- a/htdocs/admin/prelevement.php +++ b/htdocs/admin/prelevement.php @@ -298,7 +298,7 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; @@ -306,7 +306,7 @@ foreach ($dirmodels as $reldir) else { print '"; } @@ -318,7 +318,7 @@ foreach ($dirmodels as $reldir) } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; } print ''; diff --git a/htdocs/admin/proxy.php b/htdocs/admin/proxy.php index bf1283daa6d..795cbec5ede 100644 --- a/htdocs/admin/proxy.php +++ b/htdocs/admin/proxy.php @@ -94,7 +94,7 @@ print ''; $head = security_prepare_head(); -dol_fiche_head($head, 'proxy', $langs->trans("Security"), -1); +dol_fiche_head($head, 'proxy', '', -1); if ($conf->use_javascript_ajax) diff --git a/htdocs/admin/receiptprinter.php b/htdocs/admin/receiptprinter.php index c76482f4597..4332c4feab0 100644 --- a/htdocs/admin/receiptprinter.php +++ b/htdocs/admin/receiptprinter.php @@ -65,13 +65,13 @@ if (!function_exists('gzdecode')) { } } + /* * Action */ if ($action == 'addprinter' && $user->admin) { $error = 0; - $db->begin(); if (empty($printername)) { $error++; setEventMessages($langs->trans("PrinterNameEmpty"), null, 'errors'); @@ -82,7 +82,8 @@ if ($action == 'addprinter' && $user->admin) { } if (!$error) { - $result = $printer->addPrinter($printername, GETPOST('printertypeid', 'int'), GETPOST('printerprofileid', 'int'), $parameter); + $db->begin(); + $result = $printer->addPrinter($printername, GETPOST('printertypeid', 'int'), GETPOST('printerprofileid', 'int'), $parameter); if ($result > 0) $error++; if (!$error) @@ -99,14 +100,14 @@ if ($action == 'addprinter' && $user->admin) { if ($action == 'deleteprinter' && $user->admin) { $error = 0; - $db->begin(); if (empty($printerid)) { $error++; setEventMessages($langs->trans("PrinterIdEmpty"), null, 'errors'); } if (!$error) { - $result = $printer->deletePrinter($printerid); + $db->begin(); + $result = $printer->deletePrinter($printerid); if ($result > 0) $error++; if (!$error) @@ -123,14 +124,14 @@ if ($action == 'deleteprinter' && $user->admin) { if ($action == 'updateprinter' && $user->admin) { $error = 0; - $db->begin(); if (empty($printerid)) { $error++; setEventMessages($langs->trans("PrinterIdEmpty"), null, 'errors'); } if (!$error) { - $result = $printer->updatePrinter($printername, GETPOST('printertypeid', 'int'), GETPOST('printerprofileid', 'int'), $parameter, $printerid); + $db->begin(); + $result = $printer->updatePrinter($printername, GETPOST('printertypeid', 'int'), GETPOST('printerprofileid', 'int'), $parameter, $printerid); if ($result > 0) $error++; if (!$error) { @@ -189,14 +190,14 @@ if ($action == 'testtemplate' && $user->admin) { if ($action == 'updatetemplate' && $user->admin) { $error = 0; - $db->begin(); if (empty($templateid)) { $error++; setEventMessages($langs->trans("TemplateIdEmpty"), null, 'errors'); } if (!$error) { - $result = $printer->updateTemplate($templatename, $template, $templateid); + $db->begin(); + $result = $printer->updateTemplate($templatename, $template, $templateid); if ($result > 0) $error++; if (!$error) { @@ -212,14 +213,14 @@ if ($action == 'updatetemplate' && $user->admin) { if ($action == 'addtemplate' && $user->admin) { $error = 0; - $db->begin(); if (empty($templatename)) { $error++; setEventMessages($langs->trans("TemplateNameEmpty"), null, 'errors'); } if (!$error) { - $result = $printer->addTemplate($templatename, $template); + $db->begin(); + $result = $printer->addTemplate($templatename, $template); if ($result > 0) $error++; if (!$error) { @@ -233,6 +234,29 @@ if ($action == 'addtemplate' && $user->admin) { $action = ''; } +if ($action == 'deletetemplate' && $user->admin) { + $error = 0; + if (empty($templateid)) { + $error++; + setEventMessages($langs->trans("TemplateIdEmpty"), null, 'errors'); + } + + if (!$error) { + $db->begin(); + $result = $printer->deleteTemplate($templateid); + if ($result > 0) $error++; + + if (!$error) { + $db->commit(); + setEventMessages($langs->trans("TemplateDeleted", $templatename), null); + } else { + $db->rollback(); + dol_print_error($db); + } + } + $action = ''; +} + /* * View @@ -247,6 +271,7 @@ print load_fiche_titre($langs->trans("ReceiptPrinterSetup"), $linkback, 'title_s $head = receiptprinteradmin_prepare_head($mode); +// mode = config if ($mode == 'config' && $user->admin) { print ''; print ''; @@ -259,7 +284,7 @@ if ($mode == 'config' && $user->admin) { dol_fiche_head($head, $mode, $langs->trans("ModuleSetup"), -1, 'technic'); - print $langs->trans("ReceiptPrinterDesc")."

\n"; + print ''.$langs->trans("ReceiptPrinterDesc")."

\n"; print '
'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("SetAsDefault"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("SetAsDefault"), 'switch_off').''; print "'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "
'; + // Label if ($tmpfieldlist == 'topic') { @@ -557,6 +558,7 @@ foreach ($fieldsforcontent as $tmpfieldlist) print $form->textwithpicto($langs->trans("Content"), $tabhelp[$id][$tmpfieldlist], 1, 'help', '', 0, 2, $tmpfieldlist).'
'; if ($tmpfieldlist == 'content_lines') print $form->textwithpicto($langs->trans("ContentForLines"), $tabhelp[$id][$tmpfieldlist], 1, 'help', '', 0, 2, $tmpfieldlist).'
'; + // Input field if ($tmpfieldlist == 'topic') { print ''; @@ -633,30 +635,34 @@ if ($resql) // Title line with search boxes print '
'; print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth100'); print ''; $restrictid = array(); if (!$user->admin) $restrictid = array($user->id); //var_dump($restrictid); print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, 'hierarchyme', null, 0, 0, 1, '', 0, '', 'maxwidth100'); print ''.$form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100 maxwidth100onsmartphone').''; $searchpicto = $form->showFilterButtons(); diff --git a/htdocs/admin/menus.php b/htdocs/admin/menus.php index 0b19285a072..ff15bbdcd40 100644 --- a/htdocs/admin/menus.php +++ b/htdocs/admin/menus.php @@ -151,7 +151,7 @@ print ''; print ''; print ''; -dol_fiche_head($head, 'handler', $langs->trans("Menus"), -1); +dol_fiche_head($head, 'handler', '', -1); print ''.$langs->trans("MenusDesc")."
\n"; print "
\n"; diff --git a/htdocs/admin/menus/index.php b/htdocs/admin/menus/index.php index b7305679ce5..095905afe8b 100644 --- a/htdocs/admin/menus/index.php +++ b/htdocs/admin/menus/index.php @@ -229,7 +229,7 @@ $head[$h][1] = $langs->trans("Miscellaneous"); $head[$h][2] = 'misc'; $h++; -dol_fiche_head($head, 'editor', $langs->trans("Menus"), -1); +dol_fiche_head($head, 'editor', '', -1); print ''.$langs->trans("MenusEditorDesc")."
\n"; print "
\n"; diff --git a/htdocs/admin/menus/other.php b/htdocs/admin/menus/other.php index 6d88153611d..2fad8491e7a 100644 --- a/htdocs/admin/menus/other.php +++ b/htdocs/admin/menus/other.php @@ -75,7 +75,7 @@ $head[$h][1] = $langs->trans("Miscellaneous"); $head[$h][2] = 'misc'; $h++; -dol_fiche_head($head, 'misc', $langs->trans("Menus"), -1); +dol_fiche_head($head, 'misc', '', -1); // Other Options diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index b082b7eb170..2e256f3c5ad 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -262,7 +262,7 @@ print '
'; $picto = 'object_'.$objMod->picto; -print load_fiche_titre(($modulename ? $modulename : $moduledesc), $moreinfo, $picto); +print load_fiche_titre(($modulename ? $modulename : $moduledesc), $moreinfo, $picto, 0, '', 'titlemodulehelp'); print '
'; dol_fiche_head($head, $mode, '', -1); diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index e5e221c529b..3c525200442 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -38,7 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/dolistore.class.php'; // Load translation files required by the page $langs->loadLangs(array("errors", "admin", "modulebuilder")); -$mode = GETPOSTISSET('mode') ? GETPOST('mode', 'alpha') : 'commonkanban'; +$mode = GETPOSTISSET('mode') ? GETPOST('mode', 'alpha') : (empty($conf->global->MAIN_MODULE_SETUP_ON_LIST_BY_DEFAULT) ? 'commonkanban' : 'common'); if (empty($mode)) $mode = 'common'; $action = GETPOST('action', 'alpha'); //var_dump($_POST);exit; @@ -506,10 +506,10 @@ if ($mode == 'common' || $mode == 'commonkanban') $moreforfilter .= '
'.$moreinfo.'
'.$moreinfo2.'
'; $moreforfilter .= '
'; - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $langs->trans('Keyword').': '; $moreforfilter .= '
'; - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $langs->trans('Origin').': '.$form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100'); $moreforfilter .= '
'; if (!empty($conf->global->MAIN_FEATURES_LEVEL)) @@ -518,11 +518,11 @@ if ($mode == 'common' || $mode == 'commonkanban') if ($conf->global->MAIN_FEATURES_LEVEL < 0) $array_version['deprecated'] = $langs->trans("Deprecated"); if ($conf->global->MAIN_FEATURES_LEVEL > 0) $array_version['experimental'] = $langs->trans("Experimental"); if ($conf->global->MAIN_FEATURES_LEVEL > 1) $array_version['development'] = $langs->trans("Development"); - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $langs->trans('Version').': '.$form->selectarray('search_version', $array_version, $search_version, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100'); $moreforfilter .= '
'; } - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $langs->trans('Status').': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100'); $moreforfilter .= '
'; $moreforfilter .= ' '; diff --git a/htdocs/admin/mrp.php b/htdocs/admin/mrp.php index de1a6888de0..fe4e4a05818 100644 --- a/htdocs/admin/mrp.php +++ b/htdocs/admin/mrp.php @@ -371,13 +371,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print '
'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"),'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').''; print "'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"),'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').''; print "
'."\n"; print ''; @@ -272,6 +297,22 @@ if ($mode == 'config' && $user->admin) { $ret = $printer->listprinters(); $nbofprinters = count($printer->listprinters); + if ($action != 'editprinter') { + print ''; + print ''; + $ret = $printer->selectTypePrinter(); + print ''; + $ret = $printer->selectProfilePrinter(); + print ''; + print ''; + print ''; + print ''; + } + if ($ret > 0) { setEventMessages($printer->error, $printer->errors, 'errors'); } else { @@ -285,7 +326,9 @@ if ($mode == 'config' && $user->admin) { $ret = $printer->selectProfilePrinter($printer->listprinters[$line]['fk_profile']); print ''; print ''; - print ''; + print ''; print ''; } else { print ''; @@ -293,15 +336,15 @@ if ($mode == 'config' && $user->admin) { print ''; print ''; // edit icon - print ''; print ''; @@ -309,38 +352,10 @@ if ($mode == 'config' && $user->admin) { } } - if ($action != 'editprinter') { - if ($nbofprinters > 0) { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - } - - print ''; - print ''; - $ret = $printer->selectTypePrinter(); - print ''; - $ret = $printer->selectProfilePrinter(); - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - } print '
'.$printer->resprint.''.$printer->profileresprint.''; + if ($action != 'editprinter') { + print '
'; + } + print '
'.$printer->profileresprint.''; + print '
'; + print '
'.$printer->listprinters[$line]['name'].''.$langs->trans($printer->listprinters[$line]['fk_profile_name']).''.$printer->listprinters[$line]['parameter'].''; + print ''; print img_picto($langs->trans("Edit"), 'edit'); print ''; // delete icon - print ''; + print ''; print img_picto($langs->trans("Delete"), 'delete'); print ''; // test icon - print ''; + print ''; print img_picto($langs->trans("TestPrinter"), 'printer'); print '
'.$langs->trans("Name").''.$langs->trans("Type").''.$langs->trans("Profile").''.$langs->trans("Parameters").'
'.$printer->resprint.''.$printer->profileresprint.'
'; dol_fiche_end(); - if ($action != 'editprinter') { - print '
'; - } else { - print '
'; - } print ''; print '
'; @@ -370,8 +385,11 @@ if ($mode == 'config' && $user->admin) { print ''; } +// mode = template if ($mode == 'template' && $user->admin) { - print '
'; + dol_fiche_head($head, $mode, $langs->trans("ModuleSetup"), -1, 'technic'); + + print ''; print ''; if ($action != 'edittemplate') { print ''; @@ -379,16 +397,11 @@ if ($mode == 'template' && $user->admin) { print ''; } - - print load_fiche_titre($langs->trans("ReceiptPrinterTemplateDesc"), '', '')."

\n"; - print ''."\n"; print ''; print ''; print ''; print ''; - print ''; - print ''; print "\n"; $ret = $printer->listPrintersTemplates(); //print '
'.print_r($printer->listprinterstemplates, true).'
'; @@ -401,22 +414,23 @@ if ($mode == 'template' && $user->admin) { if ($action == 'edittemplate' && $printer->listprinterstemplates[$line]['rowid'] == $templateid) { print ''; print ''; - print ''; print ''; } else { print ''; print ''; // edit icon - print ''; } @@ -424,20 +438,30 @@ if ($mode == 'template' && $user->admin) { } } - print '
'.$langs->trans("Name").''.$langs->trans("Template").'
'; + print ''; + print ''; print ''.$printer->listprinterstemplates[$line]['name'].''.nl2br(htmlentities($printer->listprinterstemplates[$line]['template'])).''; + print ''; print img_picto($langs->trans("Edit"), 'edit'); print ''; // delete icon - print ''; + print ''; print img_picto($langs->trans("Delete"), 'delete'); print ''; // test icon - print ''; + print ''; print img_picto($langs->trans("TestPrinterTemplate"), 'printer'); print '
'; if ($action != 'edittemplate') { - print ''; + print ''; print ''; - print ''; + print ''; + print ''; print ''; print ''; + print ''; + } - print '
'; + print ''; + + if ($action != 'edittemplate') { + print ''; + print '
'; } else { print '
'; } print '
'; + dol_fiche_end(); + print '
'; print ''."\n"; diff --git a/htdocs/admin/reception_setup.php b/htdocs/admin/reception_setup.php index 7bcd054f13e..89b16023d4c 100644 --- a/htdocs/admin/reception_setup.php +++ b/htdocs/admin/reception_setup.php @@ -379,13 +379,13 @@ foreach ($dirmodels as $reldir) if (in_array($name, $def)) { print ''; } else { print '"; } @@ -395,7 +395,7 @@ foreach ($dirmodels as $reldir) { print img_picto($langs->trans("Default"), 'on'); } else { - print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; } print ''; @@ -487,7 +487,7 @@ print "\n"; */ print '
'."\n"; - print ''; + print ''; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; print ''."\n"; - print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; print "
'; -print '
'; +//print '
'; print ''; diff --git a/htdocs/admin/security.php b/htdocs/admin/security.php index 4dcb83c32e6..aa23a24c526 100644 --- a/htdocs/admin/security.php +++ b/htdocs/admin/security.php @@ -197,7 +197,7 @@ print "
\n"; $head = security_prepare_head(); -dol_fiche_head($head, 'passwords', $langs->trans("Security"), -1); +dol_fiche_head($head, 'passwords', '', -1); // Choix du gestionnaire du generateur de mot de passe diff --git a/htdocs/admin/security_file.php b/htdocs/admin/security_file.php index cbdfb676702..d4d8b0718ae 100644 --- a/htdocs/admin/security_file.php +++ b/htdocs/admin/security_file.php @@ -100,7 +100,7 @@ print ''; $head = security_prepare_head(); -dol_fiche_head($head, 'file', $langs->trans("Security"), -1); +dol_fiche_head($head, 'file', '', -1); // Upload options diff --git a/htdocs/admin/security_other.php b/htdocs/admin/security_other.php index 363340445c2..2bc477f6e39 100644 --- a/htdocs/admin/security_other.php +++ b/htdocs/admin/security_other.php @@ -93,7 +93,7 @@ print ''; $head = security_prepare_head(); -dol_fiche_head($head, 'misc', $langs->trans("Security"), -1); +dol_fiche_head($head, 'misc', '', -1); // Other Options diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 881e970bec5..0df5deea2f2 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -37,18 +37,40 @@ $langs->loadLangs(array("admin", "stocks")); if (!$user->admin) accessforbidden(); $action = GETPOST('action', 'alpha'); +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type = 'stock'; /* * Action */ +$reg = array(); + if (preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) { $code = $reg[1]; + + // If constant is for a unique choice, delete other choices + if (in_array($code, array('STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE'))) { + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_BILL', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_VALIDATE_ORDER', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SHIPMENT', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE', $conf->entity); + } + if (in_array($code, array('STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER'))) { + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_BILL', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_RECEPTION', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_RECEPTION_CLOSE', $conf->entity); + dolibarr_del_const($db, 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', $conf->entity); + } + if (dolibarr_set_const($db, $code, 1, 'chaine', 0, '', $conf->entity) > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); + header("Location: ".$_SERVER["PHP_SELF"]); exit; } else { dol_print_error($db); @@ -77,11 +99,84 @@ if ($action == 'warehouse') if (!$res > 0) $error++; } +if ($action == 'specimen') +{ + $modele = GETPOST('module', 'alpha'); + + $object = new Entrepot($db); + $object->initAsSpecimen(); + + // Search template files + $file = ''; $classname = ''; $filefound = 0; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $file = dol_buildpath($reldir."core/modules/stock/doc/pdf_".$modele.".modules.php", 0); + if (file_exists($file)) + { + $filefound = 1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) + { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($object, $langs) > 0) + { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=stock&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} + +// Activate a model +elseif ($action == 'set') { + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') { + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + if ($conf->global->STOCK_ADDON_PDF == "$value") dolibarr_del_const($db, 'STOCK_ADDON_PDF', $conf->entity); + } +} + +// Set default model +elseif ($action == 'setdoc') +{ + if (dolibarr_set_const($db, "STOCK_ADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) + { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->STOCK_ADDON_PDF = $value; + } + + // On active le modele + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $ret = addDocumentModel($value, $type, $label, $scandir); + } +} + /* * View */ +$form = new Form($db); +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + llxHeader('', $langs->trans("StockSetup")); $linkback = ''.$langs->trans("BackToModuleList").''; @@ -130,7 +225,7 @@ print ''; if (!empty($conf->facture->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_BILL'); + print ajax_constantonoff('STOCK_CALCULATE_ON_BILL', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_BILL); @@ -148,7 +243,7 @@ print ''; if (!empty($conf->commande->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_VALIDATE_ORDER'); + print ajax_constantonoff('STOCK_CALCULATE_ON_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER); @@ -168,7 +263,7 @@ print ''; if (!empty($conf->expedition->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT'); + print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT); @@ -186,7 +281,7 @@ print ''; if (!empty($conf->expedition->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE'); + print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE); @@ -197,18 +292,12 @@ if (!empty($conf->expedition->enabled)) print "\n\n"; $found++; -/*if (! $found) -{ - - print ''; - print ''.$langs->trans("NoModuleToManageStockDecrease").''; - print "\n"; -}*/ - print ''; + print '
'; + // Title rule for stock increase print ''; print ''; @@ -224,7 +313,7 @@ print ''; $i++; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 28d2170e49a..77ba4456c1c 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1824,6 +1824,7 @@ class Commande extends CommonOrder $this->note = $obj->note_private; // deprecated $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->last_main_doc = $obj->last_main_doc; $this->mode_reglement_id = $obj->fk_mode_reglement; @@ -3719,6 +3720,8 @@ class Commande extends CommonOrder $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -3859,6 +3862,7 @@ class Commande extends CommonOrder global $conf, $langs; $langs->load("orders"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'einstein'; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 5770df78a82..7ed5fe6e919 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -116,7 +116,7 @@ $hookmanager->initHooks(array('orderlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('commande'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // List of fields to search into when doing a "search in all" diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 010911b788b..ded439748e5 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -469,7 +469,7 @@ class Account extends CommonObject * Add an entry into table ".MAIN_DB_PREFIX."bank * * @param int $date Date operation - * @param string $oper 1,2,3,4... (deprecated) or 'TYP','VIR','PRE','LIQ','VAD','CB','CHQ'... + * @param string $oper 'VIR','PRE','LIQ','VAD','CB','CHQ'... * @param string $label Descripton * @param float $amount Amount * @param string $num_chq Numero cheque ou virement diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 73b99341be3..c5e93bc41ad 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -1555,6 +1555,8 @@ class FactureRec extends CommonInvoice $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index c18724c9103..e40c614ea08 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -423,7 +423,7 @@ class Facture extends CommonInvoice $this->brouillon = 1; // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) - if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code); + if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date); else $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); if (empty($this->fk_multicurrency)) { @@ -1581,6 +1581,7 @@ class Facture extends CommonInvoice $this->note_public = $obj->note_public; $this->user_author = $obj->fk_user_author; $this->user_valid = $obj->fk_user_valid; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->last_main_doc = $obj->last_main_doc; $this->situation_cycle_ref = $obj->situation_cycle_ref; @@ -4089,6 +4090,8 @@ class Facture extends CommonInvoice $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -4296,6 +4299,7 @@ class Facture extends CommonInvoice global $conf, $langs; $langs->load("bills"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { diff --git a/htdocs/compta/facture/invoicetemplate_list.php b/htdocs/compta/facture/invoicetemplate_list.php index dfda4a5b16d..400fb3be7ed 100644 --- a/htdocs/compta/facture/invoicetemplate_list.php +++ b/htdocs/compta/facture/invoicetemplate_list.php @@ -53,6 +53,8 @@ $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'inv $socid = GETPOST('socid', 'int'); +$socid = GETPOST('socid', 'int'); + // Security check $id = (GETPOST('facid', 'int') ?GETPOST('facid', 'int') : GETPOST('id', 'int')); $lineid = GETPOST('lineid', 'int'); @@ -106,7 +108,7 @@ $hookmanager->initHooks(array('invoicereclist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('facture_rec'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); @@ -151,6 +153,11 @@ if ($socid > 0) { } +if ($socid > 0) { + $tmpthirdparty = new Societe($db); + $res = $tmpthirdparty->fetch($socid); + if ($res > 0) $search_societe = $tmpthirdparty->name; +} /* * Actions diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index a0ce91bec86..461706edee7 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -5,7 +5,7 @@ * Copyright (C) 2005 Marc Barilley / Ocebo * Copyright (C) 2005-2015 Regis Houssin * Copyright (C) 2006 Andre Cianfarani - * Copyright (C) 2010-2012 Juanjo Menent + * Copyright (C) 2010-2020 Juanjo Menent * Copyright (C) 2012 Christophe Battarel * Copyright (C) 2013 Florian Henry * Copyright (C) 2013 Cédric Salvador @@ -150,7 +150,7 @@ $hookmanager->initHooks(array('invoicelist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('facture'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); @@ -545,6 +545,8 @@ if (!$sall) $sql .= ' f.paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec, f.tms, f.date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; + $sql .= ' f.fk_user_author, f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva,'; + $sql .= ' f.multicurrency_total_tva, f.multicurrency_total_ttc,'; $sql .= ' s.rowid, s.nom, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql .= ' typent.code,'; $sql .= ' state.code_departement, state.nom,'; @@ -830,12 +832,15 @@ if ($resql) { print ''; } @@ -1442,7 +1447,7 @@ if ($resql) { $userstatic->id = $obj->fk_user_author; $userstatic->login = $obj->login; - print '\n"; @@ -1592,19 +1597,21 @@ if ($resql) print "\n"; - $hidegeneratedfilelistifempty = 1; - if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty = 0; + if ($contextpage != 'poslist') { + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty = 0; - // Show list of available documents - $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; - $urlsource .= str_replace('&', '&', $param); + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); - $filedir = $diroutputmassaction; - $genallowed = $user->rights->facture->lire; - $delallowed = $user->rights->facture->creer; - $title = ''; + $filedir = $diroutputmassaction; + $genallowed = $user->rights->facture->lire; + $delallowed = $user->rights->facture->creer; + $title = ''; - print $formfile->showdocuments('massfilesarea_invoices', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); + print $formfile->showdocuments('massfilesarea_invoices', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); + } } else { dol_print_error($db); } diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 951dc9ed059..88a0b922e55 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -38,8 +38,6 @@ require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; -if (!$user->rights->facture->lire) accessforbidden(); - // Load translation files required by the page $langs->loadLangs(array('bills', 'banks', 'withdrawals', 'companies')); @@ -51,7 +49,6 @@ $type = GETPOST('type', 'aZ09'); $fieldid = (!empty($ref) ? 'ref' : 'rowid'); if ($user->socid) $socid = $user->socid; -$result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid); if ($type == 'bank-transfer') { $object = new FactureFournisseur($db); @@ -63,6 +60,7 @@ if ($type == 'bank-transfer') { if ($id > 0 || !empty($ref)) { $ret = $object->fetch($id, $ref); + $isdraft = (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); if ($ret > 0) { $object->fetch_thirdparty(); @@ -71,6 +69,13 @@ if ($id > 0 || !empty($ref)) $hookmanager->initHooks(array('directdebitcard', 'globalcard')); +if ($type == 'bank-transfer') { + $result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture', 'fk_soc', $fieldid, $isdraft); + if (!$user->rights->fournisseur->facture->lire) accessforbidden(); +} else { + $result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid, $isdraft); + if (!$user->rights->facture->lire) accessforbidden(); +} /* diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index d5daadcb557..3121aeffb17 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -2,7 +2,7 @@ /* Copyright (C) 2001-2005 Rodolphe Quiedeville * Copyright (C) 2004-2013 Laurent Destailleur * Copyright (C) 2005-2015 Regis Houssin - * Copyright (C) 2015-2016 Juanjo Menent + * Copyright (C) 2015-2020 Juanjo Menent * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Marcos García @@ -161,6 +161,14 @@ if (!empty($conf->facture->enabled) && $user->rights->facture->lire) $reshook = $hookmanager->executeHooks('printFieldListWhereCustomerDraft', $parameters); $sql .= $hookmanager->resPrint; + $sql.= " GROUP BY f.rowid, f.ref, f.datef, f.total, f.tva, f.total_ttc, f.ref_client, f.type, "; + $sql.= "s.email, s.nom, s.rowid, s.code_client, s.code_compta, s.code_fournisseur, s.code_compta_fournisseur"; + + // Add Group from hooks + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldListGroupByCustomerDraft', $parameters); + $sql .= $hookmanager->resPrint; + $resql = $db->query($sql); if ($resql) @@ -458,7 +466,7 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU $sql .= $hookmanager->resPrint; $sql .= " GROUP BY ff.rowid, ff.ref, ff.fk_statut, ff.libelle, ff.total_ht, ff.tva, ff.total_tva, ff.total_ttc, ff.tms, ff.paye,"; - $sql .= " s.nom, s.rowid, s.code_fournisseur, s.code_compta_fournisseur"; + $sql .= " s.nom, s.rowid, s.code_fournisseur, s.code_compta_fournisseur, s.email"; $sql .= " ORDER BY ff.tms DESC "; $sql .= $db->plimit($max, 0); diff --git a/htdocs/compta/paymentbybanktransfer/index.php b/htdocs/compta/paymentbybanktransfer/index.php index 2fc16e3dc06..e2477d86544 100644 --- a/htdocs/compta/paymentbybanktransfer/index.php +++ b/htdocs/compta/paymentbybanktransfer/index.php @@ -68,7 +68,7 @@ print '
'; $thirdpartystatic = new Societe($db); -$invoicestatic = new Facture($db); +$invoicestatic = new FactureFournisseur($db); $bprev = new BonPrelevement($db); print '
'; @@ -94,7 +94,7 @@ print '
'; if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL'); + print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL); @@ -243,7 +332,7 @@ print ''; if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER'); + print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER); @@ -261,7 +350,7 @@ if (!empty($conf->reception->enabled)) print ''; if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION'); + print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION", $arrval, $conf->global->STOCK_CALCULATE_ON_RECEPTION); @@ -276,7 +365,7 @@ if (!empty($conf->reception->enabled)) print ''; if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION_CLOSE'); + print ajax_constantonoff('STOCK_CALCULATE_ON_RECEPTION_CLOSE', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_RECEPTION_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE); @@ -290,7 +379,7 @@ if (!empty($conf->reception->enabled)) if (!empty($conf->fournisseur->enabled)) { if ($conf->use_javascript_ajax) { - print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER'); + print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', array(), null, 0, 0, 0, 2, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER); @@ -409,6 +498,161 @@ if ($virtualdiffersfromphysical) print '
'; } + + +/* + * Document templates generators + */ + +print load_fiche_titre($langs->trans("WarehouseModelModules"), '', ''); + +// Load array def with activated templates +$def = array(); +$sql = "SELECT nom"; +$sql .= " FROM ".MAIN_DB_PREFIX."document_model"; +$sql .= " WHERE type = '".$type."'"; +$sql .= " AND entity = ".$conf->entity; +$resql = $db->query($sql); +if ($resql) +{ + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) + { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } +} else { + dol_print_error($db); +} + + +print "\n"; +print "\n"; +print ''; +print ''; +print '\n"; +print '\n"; +print ''; +print ''; +print "\n"; + +clearstatcache(); + +foreach ($dirmodels as $reldir) +{ + foreach (array('', '/doc') as $valdir) + { + $realpath = $reldir."core/modules/stock".$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) + { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) + { + if (file_exists($dir.'/'.$file)) + { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified = 1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified = 0; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified = 0; + + if ($modulequalified) + { + print ''; + + // Active + if (in_array($name, $def)) + { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') + { + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } +} + +print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) print $module->info($langs); + else print $module->description; + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + if ($conf->global->STOCK_ADDON_PDF == $name) + { + print img_picto($langs->trans("Default"), 'on'); + } else { + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print ''; + if ($module->type == 'pdf') + { + print ''.img_object($langs->trans("Preview"), 'bill').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
'; + + +// Other + +print load_fiche_titre($langs->trans("Other"), '', ''); + print ''; print ''; diff --git a/htdocs/admin/system/database-tables.php b/htdocs/admin/system/database-tables.php index 4530b7671a5..c0a52337a25 100644 --- a/htdocs/admin/system/database-tables.php +++ b/htdocs/admin/system/database-tables.php @@ -28,21 +28,27 @@ require '../../main.inc.php'; $langs->load("admin"); -if (!$user->admin) +if (!$user->admin) { accessforbidden(); +} $action = GETPOST('action', 'alpha'); if ($action == 'convert') { - $sql = "ALTER TABLE ".$db->escape(GETPOST("table", "aZ09"))." ENGINE=INNODB"; + $sql = "ALTER TABLE ".$db->escape(GETPOST("table", "aZ09"))." ENGINE=INNODB"; $db->query($sql); } if ($action == 'convertutf8') { - $sql = "ALTER TABLE ".$db->escape(GETPOST("table", "aZ09"))." CHARACTER SET utf8 COLLATE utf8_unicode_ci"; - $db->query($sql); + $sql = "ALTER TABLE ".$db->escape(GETPOST("table", "aZ09"))." CHARACTER SET utf8 COLLATE utf8_unicode_ci"; + $db->query($sql); +} +if ($action == 'convertdynamic') +{ + $sql = "ALTER TABLE ".$db->escape(GETPOST("table", "aZ09"))." ROW_FORMAT=DYNAMIC;"; + $db->query($sql); } @@ -82,8 +88,8 @@ if (!$base) } else { if ($base == 1) { - print '
'; - print '
'; + print '
'; + print '
'; print ''; print ''; print ''; @@ -112,13 +118,17 @@ if (!$base) print ''; print ''; - if (isset($obj->Engine) && $obj->Engine == "MyISAM") - { - print ''; + if (isset($obj->Engine) && $obj->Engine == "MyISAM") { + print ''; } else { print ''; } - print ''; + print ''; print ''; print ''; print ''; @@ -127,9 +137,8 @@ if (!$base) print ''; print ''; print ''; print ''; @@ -142,8 +151,8 @@ if (!$base) if ($base == 2) { - print '
'; - print '
'.$langs->trans("TableName").''.$langs->trans("Type").''.$obj->Name.''.$obj->Engine.''.$langs->trans("Convert").' InnoDB'.$langs->trans("Convert").' InnoDb '.$obj->Row_format.''; + print $obj->Row_format; + if (isset($obj->Row_format) && (in_array($obj->Row_format, array("Compact")))) { + print '
'.$langs->trans("Convert").' Dynamic'; + } + print '
'.$obj->Rows.''.$obj->Avg_row_length.''.$obj->Data_length.''.$obj->Auto_increment.''.$obj->Check_time.''.$obj->Collation; - if (isset($obj->Collation) && (in_array($obj->Collation, array("utf8mb4_general_ci", "utf8mb4_unicode_ci", "latin1_swedish_ci")))) - { - print '
'.$langs->trans("Convert").' UTF8'; + if (isset($obj->Collation) && (in_array($obj->Collation, array("utf8mb4_general_ci", "utf8mb4_unicode_ci", "latin1_swedish_ci")))) { + print '
'.$langs->trans("Convert").' UTF8'; } print '
'; + print '
'; + print '
'; print ''; print ''; print ''; @@ -182,8 +191,8 @@ if (!$base) if ($base == 4) { // Sqlite by PDO or by Sqlite3 - print '
'; - print '
'.$langs->trans("TableName").'Nb of tuples
'; + print '
'; + print '
'; print ''; print ''; print ''; diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index e27eb53ef2b..974f8874096 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -348,7 +348,7 @@ if (empty($conf->global->FCKEDITOR_ENABLE_MAIL)) { // @todo Use module notification instead... // Email d'envoi des notifications -print ''; +print ''; print ''; print ''; echo ''; - $product_static->fetch($objectlink->fk_product); - echo ''; + + echo ''; echo ''; echo ''; } diff --git a/htdocs/bookmarks/card.php b/htdocs/bookmarks/card.php index 69c7207a817..bd6d1fc2cf3 100644 --- a/htdocs/bookmarks/card.php +++ b/htdocs/bookmarks/card.php @@ -145,6 +145,7 @@ if ($action == 'create') print ''."\n"; print ''; print ''; + print ''; print load_fiche_titre($langs->trans("NewBookmark")); diff --git a/htdocs/bookmarks/list.php b/htdocs/bookmarks/list.php index a132b708c20..a4f0939c054 100644 --- a/htdocs/bookmarks/list.php +++ b/htdocs/bookmarks/list.php @@ -154,7 +154,7 @@ print ''; print ''; $newcardbutton = ''; -$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/bookmarks/card.php?action=create', '', !empty($user->rights->bookmark->creer)); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/bookmarks/card.php?action=create&backtopage='.urlencode(DOL_URL_ROOT.'/bookmarks/list.php'), '', !empty($user->rights->bookmark->creer)); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'bookmark', 0, $newcardbutton, '', $limit, 0, 0, 1); diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index d5a2f76ecd5..6c27b9e82ff 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -819,8 +819,8 @@ class Categorie extends CommonObject $objs = array(); - $tmpclass = $this->MAP_OBJ_CLASS[$type]; - $obj = new $tmpclass($this->db); + $classnameforobj = $this->MAP_OBJ_CLASS[$type]; + $obj = new $classnameforobj($this->db); $sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]); $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c"; @@ -842,12 +842,14 @@ class Categorie extends CommonObject { while ($rec = $this->db->fetch_array($resql)) { - if ($onlyids) - { + if ($onlyids) { $objs[] = $rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])]; } else { - $obj = new $this->MAP_OBJ_CLASS[$type]($this->db); + $classnameforobj = $this->MAP_OBJ_CLASS[$type]; + + $obj = new $classnameforobj($this->db); $obj->fetch($rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])]); + $objs[] = $obj; } } @@ -1213,7 +1215,8 @@ class Categorie extends CommonObject //print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'
'."\n"; // We count number of _ to have level - $this->cats[$id_categ]['level'] = dol_strlen(preg_replace('/[^_]/i', '', $this->cats[$id_categ]['fullpath'])); + $nbunderscore = substr_count($this->cats[$id_categ]['fullpath'], '_'); + $this->cats[$id_categ]['level'] = ($nbunderscore ? $nbunderscore : null); return; } @@ -2009,4 +2012,25 @@ class Categorie extends CommonObject return ""; } } + + /** + * Count all categories + * + * @return int Number of categories, -1 on error + */ + public function countNbOfCategories() + { + dol_syslog(get_class($this)."::count_all_categories", LOG_DEBUG); + $sql = "SELECT COUNT(rowid) FROM ".MAIN_DB_PREFIX."categorie"; + $sql .= " WHERE entity IN (".getEntity('category').")"; + + $res = $this->db->query($sql); + if ($res) { + $obj = $this->db->fetch_object($res); + return $obj->count; + } else { + dol_print_error($this->db); + return -1; + } + } } diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 34d7b26bd8e..9ee98aa9f2b 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -9,6 +9,7 @@ * Copyright (C) 2013 Alexandre Spangaro * Copyright (C) 2015-2019 Frédéric France * Copyright (C) 2015 Marcos García + * Copyright (C) 2020 Open-Dsi * * 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 @@ -526,6 +527,7 @@ if ($object->id > 0) print "
'.$langs->trans("TableName").''.$langs->trans("NbOfRecord").'
'.$langs->trans("TicketEmailNotificationFrom").'
'.$langs->trans("TicketEmailNotificationFrom").''; print ''; diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 112cc111e29..0361e8cf9bb 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -237,7 +237,8 @@ if (in_array($type, array('mysql', 'mysqli'))) { print ''; print ''; print ''; - print ''; + + print ''; print ''; print '
'; print ''; diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index ce734aadeb5..69fef80fd6b 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -419,8 +419,10 @@ class Documents extends DolibarrApi $object = new Product($this->db); $result = $object->fetch($id, $ref); - if (!$result) { + if ($result==0) { throw new RestException(404, 'Product not found'); + } elseif ($result<0) { + throw new RestException(500, 'Error while fetching object: '.$object->error); } $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref); @@ -630,7 +632,7 @@ class Documents extends DolibarrApi } elseif ($result < 0) { - throw new RestException(500, 'Error while fetching object.'); + throw new RestException(500, 'Error while fetching object: '.$object->error); } } diff --git a/htdocs/api/index.php b/htdocs/api/index.php index d31b7cb5983..1ae504f523a 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -251,15 +251,17 @@ if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && if ($tmpmodule != 'api') $tmpmodule = preg_replace('/api$/i', '', $tmpmodule); $classfile = str_replace('_', '', $tmpmodule); - if ($module == 'supplierproposals') + + // Special cases that does not match name rules conventions + if ($moduleobject == 'supplierproposals') $classfile = 'supplier_proposals'; - if ($module == 'supplierorders') + if ($moduleobject == 'supplierorders') $classfile = 'supplier_orders'; - if ($module == 'supplierinvoices') + if ($moduleobject == 'supplierinvoices') $classfile = 'supplier_invoices'; - if ($module == 'ficheinter') + if ($moduleobject == 'ficheinter') $classfile = 'interventions'; - if ($module == 'interventions') + if ($moduleobject == 'interventions') $classfile = 'interventions'; $dir_part_file = dol_buildpath('/'.$moduledirforclass.'/class/api_'.$classfile.'.class.php', 0, 2); diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index f6dea256f6a..1ac908f361a 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -57,9 +57,11 @@ $thirdpartytmp = new Societe($db); if (GETPOST('submitproduct') && GETPOST('submitproduct')) { $action = ''; // We reset because we don't want to build doc - if (GETPOST('productid') > 0) - { - $producttmp->fetch(GETPOST('productid')); + if (GETPOST('productid') > 0) { + $result = $producttmp->fetch(GETPOST('productid')); + if ($result < 0) { + setEventMessage($producttmp->error, 'errors'); + } $forbarcode = $producttmp->barcode; $fk_barcode_type = $producttmp->barcode_type; diff --git a/htdocs/bom/bom_agenda.php b/htdocs/bom/bom_agenda.php index a764a2cd5ae..43f1604e08c 100644 --- a/htdocs/bom/bom_agenda.php +++ b/htdocs/bom/bom_agenda.php @@ -130,7 +130,7 @@ if ($object->id > 0) // Object card // ------------------------------------------------------------ - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
'; /* diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 202373dd302..6826204804f 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -192,10 +192,10 @@ if (empty($reshook)) $error = 0; // Set if we used free entry or predefined product - $qty = GETPOST('qty', 'int'); + $qty = price2num(GETPOST('qty', 'int')); $qty_frozen = GETPOST('qty_frozen', 'int'); $disable_stock_change = GETPOST('disable_stock_change', 'int'); - $efficiency = GETPOST('efficiency', 'int'); + $efficiency = price2num(GETPOST('efficiency', 'int')); if ($qty == '') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); @@ -219,6 +219,8 @@ if (empty($reshook)) unset($_POST['qty']); unset($_POST['qty_frozen']); unset($_POST['disable_stock_change']); + + $object->fetchLines(); } } } @@ -541,7 +543,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (!empty($object->table_element_line)) { - print '
+ print ' diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 4a1c4e2f179..d180c00426f 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -929,6 +929,7 @@ class BOM extends CommonObject global $conf, $langs; $langs->load("mrp"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'standard'; @@ -1004,7 +1005,11 @@ class BOM extends CommonObject foreach ($this->lines as &$line) { $tmpproduct = new Product($this->db); - $tmpproduct->fetch($line->fk_product); + $result= $tmpproduct->fetch($line->fk_product); + if ($result < 0) { + $this->error=$tmpproduct->error; + return -1; + } $line->unit_cost = price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp); if (empty($line->unit_cost)) { if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) diff --git a/htdocs/bom/tpl/linkedobjectblock.tpl.php b/htdocs/bom/tpl/linkedobjectblock.tpl.php index d6b8ebf9a7c..45340577228 100644 --- a/htdocs/bom/tpl/linkedobjectblock.tpl.php +++ b/htdocs/bom/tpl/linkedobjectblock.tpl.php @@ -52,8 +52,15 @@ foreach ($linkedObjectBlock as $key => $objectlink) } echo '
'.$objectlink->getNomUrl(1).''.$product_static->getNomUrl(1).''; + $result=$product_static->fetch($objectlink->fk_product); + if ($result<0) { + setEventMessage($product_static->error, 'errors'); + } elseif ($result>0) { + $product_static->getNomUrl(1); + } + print ''.dol_print_date($objectlink->date_creation, 'day').''; if ($user->rights->commande->lire) { diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index 8501f1ca30f..74eb88393df 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -113,7 +113,7 @@ if ($conf->global->PRODUCT_USE_UNITS) { $coldisplay++; print ''; - print $form->selectUnits($line->fk_unit, "units"); + print $form->selectUnits(empty($line->fk_unit) ? $conf->global->PRODUCT_USE_UNITS : $line->fk_unit, "units"); print '
"; + // Prospection level and status if ($object->client == 2 || $object->client == 3) { print '
'; @@ -533,12 +535,12 @@ if ($object->id > 0) print '
'; print ''; - // Level of prospect + // Level of prospection print '"; print ''; - // Status + // Status of prospection $object->loadCacheOfProspStatus(); print ''; print "
'; print ''; + if ($action != 'editlevel' && $user->rights->societe->creer) print ''; print '
'; print $langs->trans('ProspectLevel'); print ''; - if ($action != 'editlevel' && $user->rights->societe->creer) print 'id.'">'.img_edit($langs->trans('Modify'), 1).'id.'">'.img_edit($langs->trans('Modify'), 1).'
'; print '
'; if ($action == 'editlevel') @@ -550,17 +552,17 @@ if ($object->id > 0) print "
'.$langs->trans("StatusProsp").''.$object->getLibProspCommStatut(4, $object->cacheprospectstatus[$object->stcomm_id]['label']); print '     '; print '
'; foreach ($object->cacheprospectstatus as $key => $val) { - $titlealt = 'default'; - if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label']; - if ($object->stcomm_id != $val['id']) print ''.img_action($titlealt, $val['code']).''; - } + $titlealt = 'default'; + if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label']; + if ($object->stcomm_id != $val['id']) print ''.img_action($titlealt, $val['code'], $val['picto']).''; + } print '
"; } @@ -1127,7 +1129,7 @@ if ($object->id > 0) } /* - * Last invoices + * Latest invoices */ if (!empty($conf->facture->enabled) && $user->rights->facture->lire) { diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 72c7826e61b..f275f16ee03 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -230,6 +230,7 @@ if (empty($reshook)) $outputlangs->setDefaultLang($newlang); } $ret = $object->fetch($id); // Reload to get new records + if ($ret > 0) $object->fetch_thirdparty(); $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); } @@ -767,6 +768,7 @@ if (empty($reshook)) $outputlangs->setDefaultLang($newlang); } $ret = $object->fetch($id); // Reload to get new records + if ($ret > 0) $object->fetch_thirdparty(); $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); } } elseif ($action == "setabsolutediscount" && $usercancreate) { @@ -1240,6 +1242,7 @@ if (empty($reshook)) $outputlangs->setDefaultLang($newlang); } $ret = $object->fetch($id); // Reload to get new records + if ($ret > 0) $object->fetch_thirdparty(); $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); } diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index ccaabcbe765..1feab037b22 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1494,6 +1494,7 @@ class Propal extends CommonObject $this->fk_project = $obj->fk_project; $this->project = null; // Clear if another value was already set by fetch_projet + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->last_main_doc = $obj->last_main_doc; $this->note = $obj->note_private; // TODO deprecated @@ -3341,6 +3342,8 @@ class Propal extends CommonObject $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -3664,6 +3667,7 @@ class Propal extends CommonObject global $conf, $langs; $langs->load("propale"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'azur'; diff --git a/htdocs/comm/prospect/index.php b/htdocs/comm/prospect/index.php index b49f334dadd..d99b3509b26 100644 --- a/htdocs/comm/prospect/index.php +++ b/htdocs/comm/prospect/index.php @@ -2,6 +2,7 @@ /* Copyright (C) 2001-2004 Rodolphe Quiedeville * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2020 Open-Dsi * * 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 @@ -71,7 +72,7 @@ if (!empty($conf->propal->enabled)) * */ -$sql = "SELECT count(*) as cc, st.libelle, st.id"; +$sql = "SELECT count(*) as cc, st.libelle, st.picto, st.id"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= ", ".MAIN_DB_PREFIX."c_stcomm as st "; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -98,7 +99,7 @@ if ($resql) print '
'; print ''; - print img_action($langs->trans("Show"), $obj->id).' '; + print img_action($langs->trans("Show"), $obj->id, $obj->picto).' '; print $langs->trans("StatusProspect".$obj->id); print ''.$obj->cc.'
'; print '
'; + /* print $langs->trans('From').' '; print $form->selectDate($search_datelimit_start ? $search_datelimit_start : -1, 'search_datelimit_start', 0, 0, 1); print '
'; print '
'; - print $langs->trans('to').' '; + print $langs->trans('to').' ';*/ + print $langs->trans("Before").' '; print $form->selectDate($search_datelimit_end ? $search_datelimit_end : -1, 'search_datelimit_end', 0, 0, 1); + print '
'.$langs->trans("Alert"); print '
'; print '
'; + print ''; if ($userstatic->id) print $userstatic->getLoginUrl(1); else print ' '; print "

'; */ $sql = "SELECT f.ref, f.rowid, f.total_ttc, f.fk_statut, f.paye, f.type,"; $sql .= " pfd.date_demande, pfd.amount,"; -$sql .= " s.nom as name, s.email, s.rowid as socid"; +$sql .= " s.nom as name, s.email, s.rowid as socid, s.tva_intra"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,"; $sql .= " ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -138,13 +138,14 @@ if ($resql) $thirdpartystatic->id = $obj->socid; $thirdpartystatic->name = $obj->name; $thirdpartystatic->email = $obj->email; + $thirdpartystatic->tva_intra = $obj->tva_intra; print ''; print $invoicestatic->getNomUrl(1, 'withdraw'); print ''; print ''; - print $thirdpartystatic->getNomUrl(1, 'customer'); + print $thirdpartystatic->getNomUrl(1, 'supplier'); print ''; print ''; diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index d1a932a7685..4ec2b5d3443 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -31,10 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.p require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Load translation files required by the page -$langs->loadLangs(array('banks', 'categories', 'bills', 'withdrawals')); - -if (!$user->rights->prelevement->bons->lire) -accessforbidden(); +$langs->loadLangs(array('banks', 'categories', 'bills', 'companies', 'withdrawals')); // Security check if ($user->socid > 0) accessforbidden(); @@ -44,7 +41,6 @@ $action = GETPOST('action', 'alpha'); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); $socid = GETPOST('socid', 'int'); - $type = GETPOST('type', 'aZ09'); // Load variable for pagination @@ -67,6 +63,13 @@ include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be includ $hookmanager->initHooks(array('directdebitprevcard', 'globalcard', 'directdebitprevlist')); +if (!$user->rights->prelevement->bons->lire && $object->type != 'bank-transfer') { + accessforbidden(); +} +if (!$user->rights->paymentbybanktransfer->read && $object->type == 'bank-transfer') { + accessforbidden(); +} + /* * Actions @@ -83,7 +86,11 @@ if (empty($reshook)) $res = $object->delete($user); if ($res > 0) { - header("Location: index.php"); + if ($object->type == 'bank-transfer') { + header("Location: ".DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php'); + } else { + header("Location: ".DOL_URL_ROOT.'/compta/prelevement/index.php'); + } exit; } } @@ -139,11 +146,9 @@ if (empty($reshook)) $dt = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); $error = $object->set_infocredit($user, $dt); - if ($error) { - header("Location: card.php?id=".$id."&error=$error"); - exit; + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -174,7 +179,7 @@ if ($id > 0 || $ref) }*/ - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); @@ -200,7 +205,7 @@ if ($id > 0 || $ref) print ''.$langs->trans("TransData").''; print dol_print_date($object->date_trans, 'day'); - print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; + print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; print ''.$langs->trans("TransMetod").''; print $object->methodes_trans[$object->method_trans]; print ''; @@ -223,7 +228,9 @@ if ($id > 0 || $ref) $result = $acc->fetch($conf->global->PRELEVEMENT_ID_BANKACCOUNT); print ''; - print $langs->trans("BankToReceiveWithdraw"); + $labelofbankfield = "BankToReceiveWithdraw"; + if ($object->type == 'bank-transfer') $labelofbankfield = 'BankToPayCreditTransfer'; + print $langs->trans($labelofbankfield); print ''; print ''; if ($acc->id > 0) @@ -232,9 +239,13 @@ if ($id > 0 || $ref) print ''; print ''; - print $langs->trans("WithdrawalFile").''; + $labelfororderfield = 'WithdrawalFile'; + if ($object->type == 'bank-transfer') $labelfororderfield = 'CreditTransferFile'; + print $langs->trans($labelfororderfield).''; $relativepath = 'receipts/'.$object->ref.'.xml'; - print ''.$relativepath.''; + $modulepart = 'prelevement'; + if ($object->type == 'bank-transfer') $modulepart = 'paymentbybanktransfer'; + print ''.$relativepath.''; print ''; print ''; diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index a190873116a..1bea234abfc 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -32,6 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php'; @@ -67,6 +68,9 @@ class BonPrelevement extends CommonObject public $emetteur_bic; public $emetteur_ics; + public $date_trans; + public $user_trans; + public $total; public $fetched; public $statut; // 0-Wait, 1-Trans, 2-Done @@ -283,6 +287,7 @@ class BonPrelevement extends CommonObject $sql .= ", p.method_trans, p.fk_user_trans"; $sql .= ", p.date_credit as date_credit"; $sql .= ", p.fk_user_credit"; + $sql .= ", p.type"; $sql .= ", p.statut as status"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= " WHERE p.entity IN (".getEntity('invoice').")"; @@ -310,6 +315,8 @@ class BonPrelevement extends CommonObject $this->date_credit = $this->db->jdate($obj->date_credit); $this->user_credit = $obj->fk_user_credit; + $this->type = $obj->type; + $this->status = $obj->status; $this->statut = $obj->status; // For backward compatibility @@ -402,7 +409,7 @@ class BonPrelevement extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Set direct debit order to "credited" status. + * Set direct debit or credit transfer order to "paid" status. * * @param User $user Id of user * @param int $date date of action @@ -417,118 +424,151 @@ class BonPrelevement extends CommonObject if ($this->fetched == 1) { - if ($date >= $this->date_trans) + if ($date < $this->date_trans) { - if ($this->db->begin()) + $this->error = 'DateOfMovementLowerThanDateOfFileTransmission'; + dol_syslog("bon-prelevment::set_infocredit 1027 ".$this->error); + return -1027; + } + + $this->db->begin(); + + $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons "; + $sql .= " SET fk_user_credit = ".$user->id; + $sql .= ", statut = ".self::STATUS_CREDITED; + $sql .= ", date_credit = '".$this->db->idate($date)."'"; + $sql .= " WHERE rowid=".$this->id; + $sql .= " AND entity = ".$conf->entity; + $sql .= " AND statut = ".self::STATUS_TRANSFERED; + + $resql = $this->db->query($sql); + if ($resql) + { + $langs->load('withdrawals'); + $subject = $langs->trans("InfoCreditSubject", $this->ref); + $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour')); + + //Add payment of withdrawal into bank + $bankaccount = $conf->global->PRELEVEMENT_ID_BANKACCOUNT; + $facs = array(); + $amounts = array(); + $amountsperthirdparty = array(); + + $facs = $this->getListInvoices(1); + + // Loop on each invoice. $facs=array(0=>id, 1=>amount requested) + $num = count($facs); + for ($i = 0; $i < $num; $i++) { - $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons "; - $sql .= " SET fk_user_credit = ".$user->id; - $sql .= ", statut = ".self::STATUS_CREDITED; - $sql .= ", date_credit = '".$this->db->idate($date)."'"; - $sql .= " WHERE rowid=".$this->id; - $sql .= " AND entity = ".$conf->entity; - $sql .= " AND statut = ".self::STATUS_TRANSFERED; - - if ($this->db->query($sql)) - { - $langs->load('withdrawals'); - $subject = $langs->trans("InfoCreditSubject", $this->ref); - $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour')); - - //Add payment of withdrawal into bank - $bankaccount = $conf->global->PRELEVEMENT_ID_BANKACCOUNT; - $facs = array(); - $amounts = array(); - $amountsperthirdparty = array(); - - $facs = $this->getListInvoices(1); - - // Loop on each invoice. $facs=array(0=>id, 1=>amount requested) - $num = count($facs); - for ($i = 0; $i < $num; $i++) - { - $fac = new Facture($this->db); - $fac->fetch($facs[$i][0]); - $amounts[$fac->id] = $facs[$i][1]; - $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1]; - - $totalpaye = $fac->getSommePaiement(); - $totalcreditnotes = $fac->getSumCreditNotesUsed(); - $totaldeposits = $fac->getSumDepositsUsed(); - $alreadypayed = $totalpaye + $totalcreditnotes + $totaldeposits; - - if (price2num($alreadypayed + $facs[$i][1], 'MT') == $fac->total_ttc) { - $result = $fac->set_paid($user); - } - } - - // Make one payment per customer - foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) - { - $paiement = new Paiement($this->db); - $paiement->datepaye = $date; - $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice - $paiement->paiementid = 3; // - $paiement->num_payment = $this->ref; // Set ref of direct debit note - $paiement->num_paiement = $this->ref; // For backward compatibility - $paiement->id_prelevement = $this->id; - - $paiement_id = $paiement->create($user); - if ($paiement_id < 0) - { - dol_syslog(get_class($this)."::set_infocredit AddPayment Error"); - $error++; - } else { - $result = $paiement->addPaymentToBank($user, 'payment', '(WithdrawalPayment)', $bankaccount, '', ''); - if ($result < 0) - { - dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error"); - $error++; - } - } - //var_dump($paiement->amounts); - //var_dump($thirdpartyid); - //var_dump($cursoramounts); - } - - // Update withdrawal line - // TODO: Translate to ligneprelevement.class.php - $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes"; - $sql .= " SET statut = 2"; - $sql .= " WHERE fk_prelevement_bons = ".$this->id; - - if (!$this->db->query($sql)) - { - dol_syslog(get_class($this)."::set_infocredit Update lines Error"); - $error++; - } + if ($this->type == 'bank-transfer') { + $fac = new FactureFournisseur($this->db); } else { - dol_syslog(get_class($this)."::set_infocredit Update Bons Error"); + $fac = new Facture($this->db); + } + + $result = $fac->fetch($facs[$i][0]); + + $amounts[$fac->id] = $facs[$i][1]; + $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1]; + + $totalpaye = $fac->getSommePaiement(); + $totalcreditnotes = $fac->getSumCreditNotesUsed(); + $totaldeposits = $fac->getSumDepositsUsed(); + $alreadypayed = $totalpaye + $totalcreditnotes + $totaldeposits; + + // @TODO Move this after creation of payment + if (price2num($alreadypayed + $facs[$i][1], 'MT') == $fac->total_ttc) { + $result = $fac->set_paid($user); + if ($result < 0) { + $this->error = $fac->error; + $this->errors = $fac->errors; + } + } + } + //var_dump($amountsperthirdparty);exit; + + // Make one payment per customer + foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) + { + if ($this->type == 'bank-transfer') { + $paiement = new PaiementFourn($this->db); + } else { + $paiement = new Paiement($this->db); + } + $paiement->datepaye = $date; + $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice + + if ($this->type == 'bank-transfer') { + $paiement->paiementid = 2; + $paiement->paiementcode = 'VIR'; + } else { + $paiement->paiementid = 3; + $paiement->paiementcode = 'PRE'; + } + + $paiement->num_payment = $this->ref; // Set ref of direct debit note + $paiement->num_paiement = $this->ref; // For backward compatibility + $paiement->id_prelevement = $this->id; + + $paiement_id = $paiement->create($user); // This use ->paiementid, that is ID of payment mode + if ($paiement_id < 0) + { + $error++; + $this->error = $paiement->error; + $this->errors = $paiement->errors; + dol_syslog(get_class($this)."::set_infocredit AddPayment Error ".$this->error); + } else { + if ($this->type == 'bank-transfer') { + $modeforaddpayment = 'payment_supplier'; + } else { + $modeforaddpayment = 'payment'; + } + + $result = $paiement->addPaymentToBank($user, $modeforaddpayment, '(WithdrawalPayment)', $bankaccount, '', ''); + if ($result < 0) + { + $error++; + $this->error = $paiement->error; + $this->errors = $paiement->errors; + dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error ".$this->error); + } + } + //var_dump($paiement->amounts); + //var_dump($thirdpartyid); + //var_dump($cursoramounts); + } + + // Update withdrawal line + // TODO: Translate to ligneprelevement.class.php + if (! $error) { + $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes"; + $sql .= " SET statut = 2"; + $sql .= " WHERE fk_prelevement_bons = ".$this->id; + + if (!$this->db->query($sql)) { + dol_syslog(get_class($this)."::set_infocredit Update lines Error"); $error++; } - - /* - * End of procedure - */ - if ($error == 0) - { - $this->date_credit = $date; - $this->statut = self::STATUS_CREDITED; - - $this->db->commit(); - return 0; - } else { - $this->db->rollback(); - dol_syslog("bon-prelevment::set_infocredit ROLLBACK "); - return -1; - } - } else { - dol_syslog(get_class($this)."::set_infocredit 1025 Open SQL transaction impossible "); - return -1025; } } else { - dol_syslog("bon-prelevment::set_infocredit 1027 Date de credit < Date de trans "); - return -1027; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this)."::set_infocredit Update Bons Error"); + $error++; + } + + /* + * End of procedure + */ + if ($error == 0) + { + $this->date_credit = $date; + $this->statut = self::STATUS_CREDITED; + + $this->db->commit(); + return 0; + } else { + $this->db->rollback(); + return -1; } } else { return -1026; @@ -558,7 +598,7 @@ class BonPrelevement extends CommonObject $sql .= " SET fk_user_trans = ".$user->id; $sql .= " , date_trans = '".$this->db->idate($date)."'"; $sql .= " , method_trans = ".$method; - $sql .= " , statut = 1"; + $sql .= " , statut = ".self::STATUS_TRANSFERED; $sql .= " WHERE rowid = ".$this->id; $sql .= " AND entity = ".$conf->entity; $sql .= " AND statut = 0"; @@ -580,6 +620,7 @@ class BonPrelevement extends CommonObject { $this->date_trans = $date; $this->statut = 1; + $this->user_trans = $user->id; $this->db->commit(); return 0; @@ -610,7 +651,12 @@ class BonPrelevement extends CommonObject /* * Returns all invoices presented within same order */ - $sql = "SELECT fk_facture"; + $sql = "SELECT "; + if ($this->type == 'bank-transfer') { + $sql .= " pf.fk_facture_fourn"; + } else { + $sql .= " pf.fk_facture"; + } if ($amounts) $sql .= ", SUM(pl.amount)"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl"; @@ -619,7 +665,13 @@ class BonPrelevement extends CommonObject $sql .= " AND pl.fk_prelevement_bons = p.rowid"; $sql .= " AND p.rowid = ".$this->id; $sql .= " AND p.entity = ".$conf->entity; - if ($amounts) $sql .= " GROUP BY fk_facture"; + if ($amounts) { + if ($this->type == 'bank-transfer') { + $sql .= " GROUP BY fk_facture_fourn"; + } else { + $sql .= " GROUP BY fk_facture"; + } + } $resql = $this->db->query($sql); if ($resql) @@ -832,14 +884,11 @@ class BonPrelevement extends CommonObject $sql .= " AND f.rowid = pfd.fk_facture_fourn"; } $sql .= " AND s.rowid = f.fk_soc"; - //if ($banque || $agence) $sql.= " AND s.rowid = sr.fk_soc"; - $sql .= " AND f.fk_statut = 1"; + $sql .= " AND f.fk_statut = 1"; // Invoice validated $sql .= " AND f.paye = 0"; $sql .= " AND pfd.traite = 0"; $sql .= " AND f.total_ttc > 0"; $sql .= " AND pfd.ext_payment_id IS NULL"; - //if ($banque) $sql.= " AND sr.code_banque = '".$conf->global->PRELEVEMENT_CODE_BANQUE."'"; - //if ($agence) $sql.= " AND sr.code_guichet = '".$conf->global->PRELEVEMENT_CODE_GUICHET."'"; dol_syslog(__METHOD__."::Read invoices, sql=".$sql, LOG_DEBUG); @@ -883,14 +932,14 @@ class BonPrelevement extends CommonObject foreach ($factures as $key => $fac) { if ($type != 'bank-transfer') { - $fact = new Facture($this->db); + $tmpinvoice = new Facture($this->db); } else { - $fact = new FactureFournisseur($this->db); + $tmpinvoice = new FactureFournisseur($this->db); } - $resfetch = $fact->fetch($fac[0]); + $resfetch = $tmpinvoice->fetch($fac[0]); if ($resfetch >= 0) // Field 0 of $fac is rowid of invoice { - if ($soc->fetch($fact->socid) >= 0) + if ($soc->fetch($tmpinvoice->socid) >= 0) { $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $soc->id); @@ -914,9 +963,9 @@ class BonPrelevement extends CommonObject $i++; //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG); } else { - dol_syslog(__METHOD__."::Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$fact->socid." ".$soc->name, LOG_WARNING); - $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$fact->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0); - $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$fact->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0); + dol_syslog(__METHOD__."::Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING); + $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0); + $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0); } } else { dol_syslog(__METHOD__."::Check BAN Failed to read company", LOG_WARNING); @@ -948,15 +997,13 @@ class BonPrelevement extends CommonObject if (count($factures_prev) > 0) { - if ($mode == 'real') - { + if ($mode == 'real') { $ok = 1; } else { - print $langs->trans("ModeWarning"); //"Option for real mode was not set, we stop after this simulation\n"; + print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n"; } } - if ($ok) { /* @@ -999,7 +1046,7 @@ class BonPrelevement extends CommonObject // Create withdraw receipt in database $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons ("; - $sql .= " ref, entity, datec, type"; + $sql .= "ref, entity, datec, type"; $sql .= ") VALUES ("; $sql .= "'".$this->db->escape($ref)."'"; $sql .= ", ".$conf->entity; @@ -1025,6 +1072,12 @@ class BonPrelevement extends CommonObject if (!$error) { + if ($type != 'bank-transfer') { + $fact = new Facture($this->db); + } else { + $fact = new FactureFournisseur($this->db); + } + /* * Create withdrawal receipt in database */ @@ -1033,11 +1086,14 @@ class BonPrelevement extends CommonObject foreach ($factures_prev as $fac) // Add a link in database for each invoice { // Fetch invoice - $fact = new Facture($this->db); - $fact->fetch($fac[0]); + $result = $fact->fetch($fac[0]); + if ($result < 0) { + $this->error = 'ERRORBONPRELEVEMENT Failed to load invoice with id '.$fac[0]; + break; + } /* - * Add standing order + * Add standing order. This add record into llx_prelevement_lignes * * $fac[0] : invoice_id * $fac[1] : ??? @@ -1048,9 +1104,7 @@ class BonPrelevement extends CommonObject * $fac[6] : cle rib * $fac[7] : amount * $fac[8] : client nom - * $fac[2] : client id */ - $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type); if ($ri <> 0) { @@ -1065,7 +1119,6 @@ class BonPrelevement extends CommonObject $sql .= " WHERE rowid = ".$fac[1]; $resql = $this->db->query($sql); - if (!$resql) { $error++; @@ -1078,10 +1131,10 @@ class BonPrelevement extends CommonObject if (!$error) { /* - * Create file of direct debit order or credit transfer into a XML file + * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file */ - dol_syslog(__METHOD__."::Init direct debit file for ".count($factures_prev)." invoices", LOG_DEBUG); + dol_syslog(__METHOD__."::Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG); if (count($factures_prev) > 0) { @@ -1089,6 +1142,9 @@ class BonPrelevement extends CommonObject $this->reference_remise = $ref; $id = $conf->global->PRELEVEMENT_ID_BANKACCOUNT; + if ($type == 'bank-transfer') { + $id = $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT; + } $account = new Account($this->db); if ($account->fetch($id) > 0) { @@ -1107,27 +1163,34 @@ class BonPrelevement extends CommonObject $this->factures = $factures_prev_id; $this->context['factures_prev'] = $factures_prev; - // Generation of SEPA file $this->filename - // This also the the property $this->total that is included into file + // Generation of direct debit or credti transfer file $this->filename (May be a SEPA file for european countries) + // This also set the property $this->total with amount that is included into file $result = $this->generate($format, $executiondate, $type); + if ($result < 0) { + /*var_dump($this->error); + var_dump($this->invoice_in_error); */ + $error++; + } } dol_syslog(__METHOD__."::End withdraw receipt, file ".$this->filename, LOG_DEBUG); } - //var_dump($factures_prev);exit; + //var_dump($this->total);exit; /* * Update total defined after generation of file */ - $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons"; - $sql .= " SET amount = ".price2num($this->total); - $sql .= " WHERE rowid = ".$this->id; - $sql .= " AND entity = ".$conf->entity; + if (! $error) { + $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons"; + $sql .= " SET amount = ".price2num($this->total); + $sql .= " WHERE rowid = ".$this->id; + $sql .= " AND entity = ".$conf->entity; - $resql = $this->db->query($sql); - if (!$resql) - { - $error++; - dol_syslog(__METHOD__."::Error update total: ".$this->db->error(), LOG_ERR); + $resql = $this->db->query($sql); + if (!$resql) + { + $error++; + dol_syslog(__METHOD__."::Error update total: ".$this->db->error(), LOG_ERR); + } } if (!$error && !$notrigger) @@ -1146,11 +1209,11 @@ class BonPrelevement extends CommonObject if (!$error) { $this->db->commit(); + return count($factures_prev); } else { $this->db->rollback(); + return -1; } - - return count($factures_prev); } else { return 0; } @@ -1396,7 +1459,7 @@ class BonPrelevement extends CommonObject * * @param string $format FRST, RCUR or ALL * @param string $executiondate Date to execute transfer - * @param string $type 'direct-debit' or 'credit-transfer' + * @param string $type 'direct-debit' or 'bank-transfer' * @return int >=0 if OK, <0 if KO */ public function generate($format = 'ALL', $executiondate = '', $type = 'direct-debit') @@ -1424,12 +1487,9 @@ class BonPrelevement extends CommonObject { $found++; - if ($type == 'bank-transfer') { - print 'TODO'; - exit; - } else { + if ($type != 'bank-transfer') { /** - * SECTION CREATION FICHIER SEPA + * SECTION CREATION FICHIER SEPA - DIRECT DEBIT */ // SEPA Initialisation $CrLf = "\n"; @@ -1451,9 +1511,10 @@ class BonPrelevement extends CommonObject * Section Debitor (sepa Debiteurs bloc lines) */ - $sql = "SELECT soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; + $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; - $sql .= " f.ref as fac, pf.fk_facture as idfac, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum"; + $sql .= " f.ref as fac, pf.fk_facture as idfac,"; + $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum"; $sql .= " FROM"; $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,"; $sql .= " ".MAIN_DB_PREFIX."facture as f,"; @@ -1464,42 +1525,51 @@ class BonPrelevement extends CommonObject $sql .= " WHERE pl.fk_prelevement_bons = ".$this->id; $sql .= " AND pl.rowid = pf.fk_prelevement_lignes"; $sql .= " AND pf.fk_facture = f.rowid"; + $sql .= " AND f.fk_soc = soc.rowid"; $sql .= " AND soc.fk_pays = c.rowid"; - $sql .= " AND soc.rowid = f.fk_soc"; $sql .= " AND rib.fk_soc = f.fk_soc"; $sql .= " AND rib.default_rib = 1"; $sql .= " AND rib.type = 'ban'"; - //print $sql; // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice. $resql = $this->db->query($sql); if ($resql) { + $cachearraytotestduplicate = array(); + $num = $this->db->num_rows($resql); while ($i < $num) { $obj = $this->db->fetch_object($resql); + + if (! empty($cachearraytotestduplicate[$obj->idfac])) { + $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid); + $this->invoice_in_error[$obj->idfac] = $this->error; + $result = -2; + break; + } + $cachearraytotestduplicate[$obj->idfac] = $obj->rowid; + $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec); - $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->fac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum); + $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->fac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type); $this->total = $this->total + $obj->somme; $i++; } $nbtotalDrctDbtTxInf = $i; } else { + $this->error = $this->db->lasterror(); fputs($this->file, 'ERROR DEBITOR '.$sql.$CrLf); // DEBITOR = Customers $result = -2; } - // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all DrctDbtTxInf + // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf if ($result != -2) { - $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format); - } else { - fputs($this->file, 'ERROR CREDITOR'.$CrLf); // CREDITOR = My company + $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type); } /** - * SECTION CREATION SEPA FILE + * SECTION CREATION SEPA FILE - ISO200022 */ // SEPA File Header fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf); @@ -1507,7 +1577,7 @@ class BonPrelevement extends CommonObject fputs($this->file, ' '.$CrLf); // SEPA Group header fputs($this->file, ' '.$CrLf); - fputs($this->file, ' '.('PREL'.$dateTime_YMD.'/REF'.$this->id).''.$CrLf); + fputs($this->file, ' '.('DD/'.$dateTime_YMD.'/REF'.$this->id).''.$CrLf); fputs($this->file, ' '.$dateTime_ECMA.''.$CrLf); fputs($this->file, ' '.$i.''.$CrLf); fputs($this->file, ' '.$this->total.''.$CrLf); @@ -1532,21 +1602,135 @@ class BonPrelevement extends CommonObject fputs($this->file, ' '.$CrLf); fputs($this->file, ' '.$CrLf); fputs($this->file, ''.$CrLf); + } else { + /** + * SECTION CREATION FICHIER SEPA - CREDIT TRANSFER + */ + // SEPA Initialisation + $CrLf = "\n"; + + $now = dol_now(); + + $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S'); + + $date_actu = $now; + if (!empty($executiondate)) $date_actu = $executiondate; + + $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d'); + $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S'); + $fileCrediteurSection = ''; + $fileEmetteurSection = ''; + $i = 0; + + /* + * Section Creditor (sepa Crediteurs bloc lines) + */ + + $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; + $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; + $sql .= " f.ref as fac, pf.fk_facture_fourn as idfac,"; + $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum"; + $sql .= " FROM"; + $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,"; + $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,"; + $sql .= " ".MAIN_DB_PREFIX."prelevement_facture as pf,"; + $sql .= " ".MAIN_DB_PREFIX."societe as soc,"; + $sql .= " ".MAIN_DB_PREFIX."c_country as c,"; + $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib"; + $sql .= " WHERE pl.fk_prelevement_bons = ".$this->id; + $sql .= " AND pl.rowid = pf.fk_prelevement_lignes"; + $sql .= " AND pf.fk_facture_fourn = f.rowid"; + $sql .= " AND f.fk_soc = soc.rowid"; + $sql .= " AND soc.fk_pays = c.rowid"; + $sql .= " AND rib.fk_soc = f.fk_soc"; + $sql .= " AND rib.default_rib = 1"; + $sql .= " AND rib.type = 'ban'"; + + // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice. + $resql = $this->db->query($sql); + if ($resql) + { + $cachearraytotestduplicate = array(); + + $num = $this->db->num_rows($resql); + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + + if (! empty($cachearraytotestduplicate[$obj->idfac])) { + $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid); + $this->invoice_in_error[$obj->idfac] = $this->error; + $result = -2; + break; + } + $cachearraytotestduplicate[$obj->idfac] = $obj->rowid; + + $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec); + $fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->fac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type); + $this->total = $this->total + $obj->somme; + $i++; + } + $nbtotalDrctDbtTxInf = $i; + } else { + $this->error = $this->db->lasterror(); + fputs($this->file, 'ERROR CREDITOR '.$sql.$CrLf); // CREDITORS = Suppliers + $result = -2; + } + + // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf + if ($result != -2) { + $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type); + } + + /** + * SECTION CREATION SEPA FILE - CREDIT TRANSFER - ISO200022 + */ + // SEPA File Header + fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf); + fputs($this->file, ''.$CrLf); + fputs($this->file, ' '.$CrLf); + // SEPA Group header + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.('TRF/'.$dateTime_YMD.'/REF'.$this->id).''.$CrLf); + fputs($this->file, ' '.$dateTime_ECMA.''.$CrLf); + fputs($this->file, ' '.$i.''.$CrLf); + fputs($this->file, ' '.$this->total.''.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.strtoupper(dol_string_unaccent($this->raison_sociale)).''.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$conf->global->PRELEVEMENT_ICS.''.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + // SEPA File Emetteur (mycompany) + if ($result != -2) + { fputs($this-> file, $fileEmetteurSection); } + // SEPA File Creditors + if ($result != -2) + { fputs($this-> file, $fileCrediteurSection); } + // SEPA FILE FOOTER + fputs($this->file, ' '.$CrLf); + fputs($this->file, ' '.$CrLf); + fputs($this->file, ''.$CrLf); } } // Build file for Other Countries with unknow format if (!$found) { - if ($type == 'bank-transfer') { + if ($type != 'bank-transfer') { $sql = "SELECT pl.amount"; $sql .= " FROM"; $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,"; - $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,"; + $sql .= " ".MAIN_DB_PREFIX."facture as f,"; $sql .= " ".MAIN_DB_PREFIX."prelevement_facture as pf"; $sql .= " WHERE pl.fk_prelevement_bons = ".$this->id; $sql .= " AND pl.rowid = pf.fk_prelevement_lignes"; - $sql .= " AND pf.fk_facture_fourn = f.rowid"; + $sql .= " AND pf.fk_facture = f.rowid"; // Lines $i = 0; @@ -1570,11 +1754,11 @@ class BonPrelevement extends CommonObject $sql = "SELECT pl.amount"; $sql .= " FROM"; $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,"; - $sql .= " ".MAIN_DB_PREFIX."facture as f,"; + $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,"; $sql .= " ".MAIN_DB_PREFIX."prelevement_facture as pf"; $sql .= " WHERE pl.fk_prelevement_bons = ".$this->id; $sql .= " AND pl.rowid = pf.fk_prelevement_lignes"; - $sql .= " AND pf.fk_facture = f.rowid"; + $sql .= " AND pf.fk_facture_fourn = f.rowid"; // Lines $i = 0; @@ -1611,6 +1795,22 @@ class BonPrelevement extends CommonObject } + /** + * Generate dynamically a RUM number for a customer bank account + * + * @param string $row_code_client Customer code (soc.code_client) + * @param int $row_datec Creation date of bank account (rib.datec) + * @param string $row_drum Id of customer bank account (rib.rowid) + * @return string RUM number + */ + public static function buildRumNumber($row_code_client, $row_datec, $row_drum) + { + global $langs; + $pre = substr(dol_string_nospecial(dol_string_unaccent($langs->transnoentitiesnoconv('RUM'))), 0, 3); // Must always be on 3 char ('RUM' or 'UMR'. This is a protection against bad translation) + return $pre.'-'.$row_code_client.'-'.$row_drum.'-'.date('U', $row_datec); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Write recipient of request (customer) @@ -1624,9 +1824,11 @@ class BonPrelevement extends CommonObject * @param string $ref ref of invoice * @param int $facid id of invoice * @param string $rib_dom rib domiciliation + * @param string $type 'direct-debit' or 'bank-transfer' * @return void + * @see EnregDestinataireSEPA() */ - public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '') + public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit') { // phpcs:enable fputs($this->file, "06"); @@ -1683,22 +1885,6 @@ class BonPrelevement extends CommonObject fputs($this->file, "\n"); } - - /** - * Build RUM number for a customer bank account - * - * @param string $row_code_client Customer code (soc.code_client) - * @param int $row_datec Creation date of bank account (rib.datec) - * @param string $row_drum Id of customer bank account (rib.rowid) - * @return string RUM number - */ - public static function buildRumNumber($row_code_client, $row_datec, $row_drum) - { - global $langs; - $pre = substr(dol_string_nospecial(dol_string_unaccent($langs->transnoentitiesnoconv('RUM'))), 0, 3); // Must always be on 3 char ('RUM' or 'UMR'. This is a protection against bad translation) - return $pre.'-'.$row_code_client.'-'.$row_drum.'-'.date('U', $row_datec); - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Write recipient of request (customer) @@ -1720,9 +1906,11 @@ class BonPrelevement extends CommonObject * @param string $row_datec rib.datec, * @param string $row_drum rib.rowid used to generate rum * @param string $row_rum rib.rum Rum defined on company bank account + * @param string $type 'direct-debit' or 'bank-transfer' * @return string Return string with SEPA part DrctDbtTxInf + * @see EnregDestinataire() */ - public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum) + public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type = 'direct-debit') { // phpcs:enable global $conf; @@ -1730,7 +1918,7 @@ class BonPrelevement extends CommonObject include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; $CrLf = "\n"; - $Rowing = sprintf("%06d", $row_idfac); + $Rowing = sprintf("%010d", $row_idfac); // Define value for RUM // Example: RUMCustomerCode-CustomerBankAccountId-01424448606 (note: Date is date of creation of CustomerBankAccountId) @@ -1739,57 +1927,108 @@ class BonPrelevement extends CommonObject // Define date of RUM signature $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d'); - $XML_DEBITOR = ''; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - // $XML_DEBITOR .=' '.('AS-'.dol_trunc($row_ref,20).'-'.$Rowing).''.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters - $XML_DEBITOR .= ' '.(($conf->global->PRELEVEMENT_END_TO_END != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('AS-'.dol_trunc($row_ref, 20)).'-'.$Rowing).''.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.round($row_somme, 2).''.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$Rum.''.$CrLf; - $XML_DEBITOR .= ' '.$DtOfSgntr.''.$CrLf; - $XML_DEBITOR .= ' false'.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$row_bic.''.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.dolEscapeXML(strtoupper(dol_string_unaccent($row_nom))).''.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$row_country_code.''.$CrLf; - $addressline1 = dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))); - $addressline2 = dol_string_unaccent(strtr($row_zip.(($row_zip && $row_town) ? ' ' : ''.$row_town), array(CHR(13) => ", ", CHR(10) => ""))); - if (trim($addressline1)) $XML_DEBITOR .= ' '.dolEscapeXML(dol_trunc($addressline1, 70, 'right', 'UTF-8', true)).''.$CrLf; - if (trim($addressline2)) $XML_DEBITOR .= ' '.dolEscapeXML(dol_trunc($addressline2, 70, 'right', 'UTF-8', true)).''.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.preg_replace('/\s/', '', $row_iban).''.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - // $XML_DEBITOR .=' '.($row_ref.'/'.$Rowing.'/'.$Rum).''.$CrLf; - // $XML_DEBITOR .=' '.dol_trunc($row_ref, 135).''.$CrLf; // 140 max - $XML_DEBITOR .= ' '.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135)).''.$CrLf; // 140 max - $XML_DEBITOR .= ' '.$CrLf; - $XML_DEBITOR .= ' '.$CrLf; - return $XML_DEBITOR; + if ($type != 'bank-transfer') { + // SEPA Paiement Information of buyer for Direct debit + $XML_DEBITOR = ''; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum) + $XML_DEBITOR .= ' '.(($conf->global->PRELEVEMENT_END_TO_END != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('AS-'.dol_trunc($row_ref, 20)).'-'.$Rowing).''.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.round($row_somme, 2).''.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$Rum.''.$CrLf; + $XML_DEBITOR .= ' '.$DtOfSgntr.''.$CrLf; + $XML_DEBITOR .= ' false'.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$row_bic.''.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.dolEscapeXML(strtoupper(dol_string_unaccent($row_nom))).''.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$row_country_code.''.$CrLf; + $addressline1 = dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))); + $addressline2 = dol_string_unaccent(strtr($row_zip.(($row_zip && $row_town) ? ' ' : ''.$row_town), array(CHR(13) => ", ", CHR(10) => ""))); + if (trim($addressline1)) $XML_DEBITOR .= ' '.dolEscapeXML(dol_trunc($addressline1, 70, 'right', 'UTF-8', true)).''.$CrLf; + if (trim($addressline2)) $XML_DEBITOR .= ' '.dolEscapeXML(dol_trunc($addressline2, 70, 'right', 'UTF-8', true)).''.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.preg_replace('/\s/', '', $row_iban).''.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + // A string with some information on payment - 140 max + $XML_DEBITOR .= ' '.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135)).''.$CrLf; // 140 max + $XML_DEBITOR .= ' '.$CrLf; + $XML_DEBITOR .= ' '.$CrLf; + return $XML_DEBITOR; + } else { + // SEPA Paiement Information of seller for Credit Transfer + $XML_CREDITOR = ''; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum) + $XML_CREDITOR .= ' '.(($conf->global->PRELEVEMENT_END_TO_END != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('AS-'.dol_trunc($row_ref, 20)).'-'.$Rowing).''.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.round($row_somme, 2).''.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + /* + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$Rum.''.$CrLf; + $XML_CREDITOR .= ' '.$DtOfSgntr.''.$CrLf; + $XML_CREDITOR .= ' false'.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + */ + //$XML_CREDITOR .= ' SLEV'.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$row_bic.''.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.dolEscapeXML(strtoupper(dol_string_unaccent($row_nom))).''.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$row_country_code.''.$CrLf; + $addressline1 = dol_string_unaccent(strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""))); + $addressline2 = dol_string_unaccent(strtr($row_zip.(($row_zip && $row_town) ? ' ' : ''.$row_town), array(CHR(13) => ", ", CHR(10) => ""))); + if (trim($addressline1)) $XML_CREDITOR .= ' '.dolEscapeXML(dol_trunc($addressline1, 70, 'right', 'UTF-8', true)).''.$CrLf; + if (trim($addressline2)) $XML_CREDITOR .= ' '.dolEscapeXML(dol_trunc($addressline2, 70, 'right', 'UTF-8', true)).''.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.preg_replace('/\s/', '', $row_iban).''.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + // A string with some information on payment - 140 max + $XML_CREDITOR .= ' '.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135)).''.$CrLf; // 140 max + $XML_CREDITOR .= ' '.$CrLf; + $XML_CREDITOR .= ' '.$CrLf; + return $XML_CREDITOR; + } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Write sender of request (me) + * Write sender of request (me). * + * @param string $type 'direct-debit' or 'bank-transfer' * @return void + * @see EnregEmetteurSEPA() */ - public function EnregEmetteur() + public function EnregEmetteur($type = 'direct-debit') { // phpcs:enable fputs($this->file, "03"); @@ -1861,9 +2100,11 @@ class BonPrelevement extends CommonObject * @param float $total Total * @param string $CrLf End of line character * @param string $format FRST or RCUR or ALL + * @param string $type 'direct-debit' or 'bank-transfer' * @return string String with SEPA Sender + * @see EnregEmetteur() */ - public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST') + public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit') { // phpcs:enable // SEPA INITIALISATION @@ -1890,7 +2131,7 @@ class BonPrelevement extends CommonObject $this->raison_sociale = $account->proprio; } - // Récupération info demandeur + // Get pending payments $sql = "SELECT rowid, ref"; $sql .= " FROM"; $sql .= " ".MAIN_DB_PREFIX."prelevement_bons as pb"; @@ -1901,72 +2142,134 @@ class BonPrelevement extends CommonObject { $obj = $this->db->fetch_object($resql); - // DONNEES BRUTES : par la suite Rows['XXX'] de la requete au dessus $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY); $IdBon = sprintf("%05d", $obj->rowid); $RefBon = $obj->ref; - // SEPA Paiement Information - $XML_SEPA_INFO = ''; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.('PREL'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).''.$CrLf; - $XML_SEPA_INFO .= ' DD'.$CrLf; - $XML_SEPA_INFO .= ' '.$nombre.''.$CrLf; - $XML_SEPA_INFO .= ' '.$total.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' SEPA'.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' CORE'.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$format.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$dateTime_ETAD.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.strtoupper(dol_string_unaccent($this->raison_sociale)).''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; - $addressline1 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""))); - $addressline2 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP.(($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' '.$configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '').$configuration->global->MAIN_INFO_SOCIETE_TOWN, array(CHR(13) => ", ", CHR(10) => ""))); - if ($addressline1) $XML_SEPA_INFO .= ' '.$addressline1.''.$CrLf; - if ($addressline2) $XML_SEPA_INFO .= ' '.$addressline2.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.preg_replace('/\s/', '', $this->emetteur_iban).''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$this->emetteur_bic.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - /* $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$this->raison_sociale.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; - $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ADDRESS.''.$CrLf; - $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf;*/ - $XML_SEPA_INFO .= ' SLEV'.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$this->emetteur_ics.''.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' SEPA'.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; - $XML_SEPA_INFO .= ' '.$CrLf; + if ($type != 'bank-transfer') { + // SEPA Paiement Information of my company for Direct debit + $XML_SEPA_INFO = ''; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.('DD/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).''.$CrLf; + $XML_SEPA_INFO .= ' DD'.$CrLf; + $XML_SEPA_INFO .= ' '.$nombre.''.$CrLf; + $XML_SEPA_INFO .= ' '.$total.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' SEPA'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' CORE'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$format.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$dateTime_ETAD.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.strtoupper(dol_string_unaccent($this->raison_sociale)).''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; + $addressline1 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""))); + $addressline2 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP.(($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' '.$configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '').$configuration->global->MAIN_INFO_SOCIETE_TOWN, array(CHR(13) => ", ", CHR(10) => ""))); + if ($addressline1) $XML_SEPA_INFO .= ' '.$addressline1.''.$CrLf; + if ($addressline2) $XML_SEPA_INFO .= ' '.$addressline2.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.preg_replace('/\s/', '', $this->emetteur_iban).''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->emetteur_bic.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + /* $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->raison_sociale.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; + $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ADDRESS.''.$CrLf; + $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf;*/ + $XML_SEPA_INFO .= ' SLEV'.$CrLf; // Field "Responsible of fees". Must be SLEV + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->emetteur_ics.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' SEPA'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + } else { + // SEPA Paiement Information of my company for Credit Transfer + $XML_SEPA_INFO = ''; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.('TRF/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).''.$CrLf; + $XML_SEPA_INFO .= ' TRF'.$CrLf; + //$XML_SEPA_INFO .= ' False'.$CrLf; + $XML_SEPA_INFO .= ' '.$nombre.''.$CrLf; + $XML_SEPA_INFO .= ' '.$total.''.$CrLf; + /* + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' SEPA'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' TRF'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' SECU'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + */ + $XML_SEPA_INFO .= ' '.dol_print_date($dateTime_ETAD, 'dayrfc').''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.strtoupper(dol_string_unaccent($this->raison_sociale)).''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; + $addressline1 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""))); + $addressline2 = dol_string_unaccent(strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP.(($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' '.$configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '').$configuration->global->MAIN_INFO_SOCIETE_TOWN, array(CHR(13) => ", ", CHR(10) => ""))); + if ($addressline1) $XML_SEPA_INFO .= ' '.$addressline1.''.$CrLf; + if ($addressline2) $XML_SEPA_INFO .= ' '.$addressline2.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.preg_replace('/\s/', '', $this->emetteur_iban).''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->emetteur_bic.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + /* $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->raison_sociale.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$country[1].''.$CrLf; + $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ADDRESS.''.$CrLf; + $XML_SEPA_INFO .= ' '.$conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf;*/ + $XML_SEPA_INFO .= ' SLEV'.$CrLf; // Field "Responsible of fees". Must be SLEV + /*$XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$this->emetteur_ics.''.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' SEPA'.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf; + $XML_SEPA_INFO .= ' '.$CrLf;*/ + } } else { fputs($this->file, 'INCORRECT EMETTEUR '.$XML_SEPA_INFO.$CrLf); - $result = -2; } return $XML_SEPA_INFO; } diff --git a/htdocs/compta/prelevement/class/ligneprelevement.class.php b/htdocs/compta/prelevement/class/ligneprelevement.class.php index 78e364c1abc..a645d2bb078 100644 --- a/htdocs/compta/prelevement/class/ligneprelevement.class.php +++ b/htdocs/compta/prelevement/class/ligneprelevement.class.php @@ -59,7 +59,7 @@ class LignePrelevement $langs->load("withdrawals"); $this->statuts[0] = $langs->trans("StatusWaiting"); - $this->statuts[2] = $langs->trans("StatusCredited"); + $this->statuts[2] = $langs->trans("StatusPaid"); $this->statuts[3] = $langs->trans("StatusRefused"); } diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index ed08c5b4575..f8d67de48c2 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -88,11 +88,9 @@ if (empty($reshook)) // $conf->global->PRELEVEMENT_CODE_BANQUE and $conf->global->PRELEVEMENT_CODE_GUICHET should be empty (we don't use them anymore) $result = $bprev->create($conf->global->PRELEVEMENT_CODE_BANQUE, $conf->global->PRELEVEMENT_CODE_GUICHET, $mode, $format, $executiondate, 0, $type); - if ($result < 0) - { + if ($result < 0) { setEventMessages($bprev->error, $bprev->errors, 'errors'); - } elseif ($result == 0) - { + } elseif ($result == 0) { $mesg = $langs->trans("NoInvoiceCouldBeWithdrawed", $format); setEventMessages($mesg, null, 'errors'); $mesg .= '
'."\n"; @@ -101,7 +99,11 @@ if (empty($reshook)) $mesg .= ''.$val."
\n"; } } else { - setEventMessages($langs->trans("DirectDebitOrderCreated", $bprev->getNomUrl(1)), null); + if ($type != 'bank-transfer') { + setEventMessages($langs->trans("DirectDebitOrderCreated", $bprev->getNomUrl(1)), null); + } else { + setEventMessages($langs->trans("CreditTransferOrderCreated", $bprev->getNomUrl(1)), null); + } header("Location: ".DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$bprev->id); exit; @@ -366,10 +368,15 @@ if ($resql) // RUM print ''; - print $thirdpartystatic->display_rib('rum'); - $format = $thirdpartystatic->display_rib('format'); - if ($type != 'bank-transfer') { - if ($format) print ' ('.$format.')'; + $rumtoshow = $thirdpartystatic->display_rib('rum'); + if ($rumtoshow) { + print $rumtoshow; + $format = $thirdpartystatic->display_rib('format'); + if ($type != 'bank-transfer') { + if ($format) print ' ('.$format.')'; + } + } else { + print img_warning($langs->trans("NoBankAccount")); } print ''; // Amount diff --git a/htdocs/compta/prelevement/demandes.php b/htdocs/compta/prelevement/demandes.php index 3bbc5c8b2bc..53934deaac1 100644 --- a/htdocs/compta/prelevement/demandes.php +++ b/htdocs/compta/prelevement/demandes.php @@ -105,14 +105,17 @@ if ($type != 'bank-transfer') { llxHeader('', $title); $thirdpartystatic = new Societe($db); -$invoicestatic = new Facture($db); +if ($type == 'bank-transfer') { + $invoicestatic = new FactureFournisseur($db); +} else { + $invoicestatic = new Facture($db); +} // List of requests $sql = "SELECT f.ref, f.rowid, f.total_ttc,"; $sql .= " s.nom as name, s.rowid as socid,"; -$sql .= " pfd.date_demande as date_demande,"; -$sql .= " pfd.fk_user_demande"; +$sql .= " pfd.date_demande as date_demande, pfd.amount, pfd.fk_user_demande"; if ($type != 'bank-transfer') { $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,"; } else { @@ -126,6 +129,7 @@ $sql .= " AND f.entity IN (".getEntity('invoice').")"; if (!$user->rights->societe->client->voir && !$socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if ($socid) $sql .= " AND f.fk_soc = ".$socid; if (!$status) $sql .= " AND pfd.traite = 0"; +$sql .= " AND pfd.ext_payment_id IS NULL"; if ($status) $sql .= " AND pfd.traite = ".$status; $sql .= " AND f.total_ttc > 0"; if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) @@ -141,7 +145,6 @@ if ($search_facture) $sql .= natural_search("f.ref", $search_facture); if ($search_societe) $sql .= natural_search("s.nom", $search_societe); $sql .= $db->order($sortfield, $sortorder); - // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) @@ -173,9 +176,9 @@ if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) -$newcardbutton = ''.$langs->trans("Back").''; +$newcardbutton = ''.$langs->trans("Back").''; if ($type == 'bank-transfer') { - $newcardbutton = ''.$langs->trans("Back").''; + $newcardbutton = ''.$langs->trans("Back").''; } print '
'; @@ -190,6 +193,14 @@ print ''; $param = ''; +$label = 'NewStandingOrder'; +$typefilter = ''; +if ($type == 'bank-transfer') { + $label = 'NewPaymentByBankTransfer'; + $typefilter = 'type='.$type; +} +$newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/prelevement/create.php'.($typefilter ? '?'.$typefilter : '')); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'generic', 0, $newcardbutton, '', $limit); print ''; @@ -197,7 +208,7 @@ print '
'; print ''; print_liste_field_titre("Bill", $_SERVER["PHP_SELF"]); print_liste_field_titre("Company", $_SERVER["PHP_SELF"]); -print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'right '); +print_liste_field_titre("AmountRequested", $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'right '); print_liste_field_titre("DateRequest", $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'center '); print_liste_field_titre(''); print ''; @@ -220,12 +231,12 @@ while ($i < min($num, $limit)) $obj = $db->fetch_object($resql); if (empty($obj)) break; // Should not happen + $invoicestatic->fetch($obj->rowid); + print ''; // Ref facture print ''; @@ -235,7 +246,9 @@ while ($i < min($num, $limit)) print $thirdpartystatic->getNomUrl(1, 'customer'); print ''; - print ''; + print ''; print ''; diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 452e1bf8be7..fcdb2f01404 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -32,21 +32,21 @@ require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Load translation files required by the page -$langs->loadLangs(array('banks', 'categories', 'companies', 'withdrawals', 'bills')); +$langs->loadLangs(array('banks', 'categories', 'bills', 'companies', 'withdrawals')); // Securite acces client if ($user->socid > 0) accessforbidden(); // Get supervariables $id = GETPOST('id', 'int'); -$socid = GETPOST('socid', 'int'); $ref = GETPOST('ref', 'alpha'); - +$socid = GETPOST('socid', 'int'); $type = GETPOST('type', 'aZ09'); +// Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$sortfield = GETPOST("sortfield", 'alpha'); -$sortorder = GETPOST("sortorder", 'alpha'); +$sortfield = GETPOST('sortfield', 'alpha'); +$sortorder = GETPOST('sortorder', 'alpha'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $offset = $limit * $page; @@ -57,6 +57,17 @@ if (!$sortorder) $sortorder = 'DESC'; $object = new BonPrelevement($db); +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +$hookmanager->initHooks(array('directdebitprevcard', 'globalcard', 'directdebitprevlist')); + +if (!$user->rights->prelevement->bons->lire && $object->type != 'bank-transfer') { + accessforbidden(); +} +if (!$user->rights->paymentbybanktransfer->read && $object->type == 'bank-transfer') { + accessforbidden(); +} /* @@ -75,19 +86,17 @@ if ($id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'invoices', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); print '
'; print '
'; - print '
'; - $invoicestatic->id = $obj->rowid; - $invoicestatic->ref = $obj->ref; print $invoicestatic->getNomUrl(1, 'withdraw'); print ''.price($obj->total_ttc).''; + print price($obj->amount, 1, $langs, 1, -1, -1, $conf->currency).' / '.price($obj->total_ttc, 1, $langs, 1, -1, -1, $conf->currency); + print ''.dol_print_date($db->jdate($obj->date_demande), 'day').'
'; + print '
'."\n"; //print ''; print ''; print ''; - // Status - //print ''; if ($object->date_trans <> 0) { @@ -96,7 +105,7 @@ if ($id > 0 || $ref) print ''; + print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; print ''; @@ -119,7 +128,9 @@ if ($id > 0 || $ref) $result = $acc->fetch($conf->global->PRELEVEMENT_ID_BANKACCOUNT); print ''; print ''; print '
'.$langs->trans("Ref").''.$object->getNomUrl(1).'
'.$langs->trans("Date").''.dol_print_date($object->datec, 'day').'
'.$langs->trans("Amount").''.price($object->amount).'
'.$langs->trans('Status').''.$object->getLibStatut(1).'
'.$langs->trans("TransData").''; print dol_print_date($object->date_trans, 'day'); - print ' '.$langs->trans("By").' '.$muser->getFullName($langs).'
'.$langs->trans("TransMetod").''; print $object->methodes_trans[$object->method_trans]; print '
'; - print $langs->trans("BankToReceiveWithdraw"); + $labelofbankfield = "BankToReceiveWithdraw"; + if ($object->type == 'bank-transfer') $labelofbankfield = 'BankToPayCreditTransfer'; + print $langs->trans($labelofbankfield); print ''; if ($acc->id > 0) @@ -128,9 +139,13 @@ if ($id > 0 || $ref) print '
'; - print $langs->trans("WithdrawalFile").''; + $labelfororderfield = 'WithdrawalFile'; + if ($object->type == 'bank-transfer') $labelfororderfield = 'CreditTransferFile'; + print $langs->trans($labelfororderfield).''; $relativepath = 'receipts/'.$object->ref.'.xml'; - print ''.$relativepath.''; + $modulepart = 'prelevement'; + if ($object->type == 'bank-transfer') $modulepart = 'paymentbybanktransfer'; + print ''.$relativepath.''; print '
'; print ''; @@ -143,19 +158,31 @@ if ($id > 0 || $ref) // List of invoices -$sql = "SELECT pf.rowid,"; +$sql = "SELECT pf.rowid, p.type,"; $sql .= " f.rowid as facid, f.ref as ref, f.total_ttc,"; $sql .= " s.rowid as socid, s.nom as name, pl.statut, pl.amount as amount_requested"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_facture as pf"; -$sql .= ", ".MAIN_DB_PREFIX."facture as f"; +if ($object->type != 'bank-transfer') { + $sql .= ", ".MAIN_DB_PREFIX."facture as f"; +} else { + $sql .= ", ".MAIN_DB_PREFIX."facture_fourn as f"; +} $sql .= ", ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE pf.fk_prelevement_lignes = pl.rowid"; $sql .= " AND pl.fk_prelevement_bons = p.rowid"; $sql .= " AND f.fk_soc = s.rowid"; -$sql .= " AND pf.fk_facture = f.rowid"; -$sql .= " AND f.entity IN (".getEntity('invoice').")"; +if ($object->type != 'bank-transfer') { + $sql .= " AND pf.fk_facture = f.rowid"; +} else { + $sql .= " AND pf.fk_facture_fourn = f.rowid"; +} +if ($object->type != 'bank-transfer') { + $sql .= " AND f.entity IN (".getEntity('invoice').")"; +} else { + $sql .= " AND f.entity IN (".getEntity('supplier_invoice').")"; +} if ($object->id > 0) $sql .= " AND p.rowid=".$object->id; if ($socid) $sql .= " AND s.rowid = ".$socid; $sql .= $db->order($sortfield, $sortorder); @@ -164,8 +191,8 @@ $sql .= $db->order($sortfield, $sortorder); $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $result = $db->query($sql); - $nbtotalofrecords = $db->num_rows($result); + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0 { $page = 0; @@ -175,10 +202,10 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) $sql .= $db->plimit($limit + 1, $offset); -$result = $db->query($sql); -if ($result) +$resql = $db->query($sql); +if ($resql) { - $num = $db->num_rows($result); + $num = $db->num_rows($resql); $i = 0; $param = "&id=".$id; @@ -207,22 +234,28 @@ if ($result) print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("AmountInvoice", $_SERVER["PHP_SELF"], "f.total_ttc", "", $param, 'class="right"', $sortfield, $sortorder); print_liste_field_titre("AmountRequested", $_SERVER["PHP_SELF"], "pl.amount", "", $param, 'class="right"', $sortfield, $sortorder); - print_liste_field_titre("StatusDebitCredit", $_SERVER["PHP_SELF"], "", "", $param, 'align="center"', $sortfield, $sortorder); + print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "", "", $param, 'align="center"', $sortfield, $sortorder); print_liste_field_titre(''); print "\n"; $totalinvoices = 0; $totalamount_requested = 0; + $invoicetmpcustomer = new Facture($db); + $invoicetmpsupplier = new FactureFournisseur($db); + while ($i < min($num, $limit)) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); - $invoicetmp->id = $obj->facid; - $invoicetmp->ref = $obj->ref; + if ($obj->type == 'bank-transfer') { + $invoicetmp = $invoicetmpsupplier; + } else { + $invoicetmp = $invoicetmpcustomer; + } + $invoicetmp->fetch($obj->facid); - $thirdpartytmp->id = $obj->socid; - $thirdpartytmp->name = $obj->name; + $thirdpartytmp->fetch($obj->socid); print ''; @@ -243,14 +276,15 @@ if ($result) // Status of requests print ''; - if ($obj->statut == 0) - { + if ($obj->statut == 0) { print '-'; - } elseif ($obj->statut == 2) - { - print $langs->trans("StatusCredited"); - } elseif ($obj->statut == 3) - { + } elseif ($obj->statut == 2) { + if ($obj->type == 'bank-transfer') { + print $langs->trans("StatusDebited"); + } else { + print $langs->trans("StatusCredited"); + } + } elseif ($obj->statut == 3) { print ''.$langs->trans("StatusRefused").''; } diff --git a/htdocs/compta/prelevement/fiche-rejet.php b/htdocs/compta/prelevement/fiche-rejet.php index b8665e822cf..bddebaedda5 100644 --- a/htdocs/compta/prelevement/fiche-rejet.php +++ b/htdocs/compta/prelevement/fiche-rejet.php @@ -21,7 +21,7 @@ /** * \file htdocs/compta/prelevement/fiche-rejet.php * \ingroup prelevement - * \brief Withdraw reject + * \brief Debit order or credit transfer reject */ require '../../main.inc.php'; @@ -34,7 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Load translation files required by the page $langs->loadLangs(array("banks", "categories", 'withdrawals', 'bills')); -// Securite acces client +// Security check if ($user->socid > 0) accessforbidden(); // Get supervariables @@ -55,6 +55,15 @@ $pagenext = $page + 1; $object = new BonPrelevement($db); +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if (!$user->rights->prelevement->bons->lire && $object->type != 'bank-transfer') { + accessforbidden(); +} +if (!$user->rights->paymentbybanktransfer->read && $object->type == 'bank-transfer') { + accessforbidden(); +} @@ -71,7 +80,7 @@ if ($prev_id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'rejects', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); @@ -83,13 +92,6 @@ if ($prev_id > 0 || $ref) print ''.$langs->trans("Date").''.dol_print_date($object->datec, 'day').''; print ''.$langs->trans("Amount").''.price($object->amount).''; - // Status - /* - print ''.$langs->trans('Status').''; - print ''.$object->getLibStatut(1).''; - print ''; - */ - if ($object->date_trans <> 0) { $muser = new User($db); @@ -97,7 +99,7 @@ if ($prev_id > 0 || $ref) print ''.$langs->trans("TransData").''; print dol_print_date($object->date_trans, 'day'); - print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; + print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; print ''.$langs->trans("TransMetod").''; print $object->methodes_trans[$object->method_trans]; print ''; @@ -120,7 +122,9 @@ if ($prev_id > 0 || $ref) $result = $acc->fetch($conf->global->PRELEVEMENT_ID_BANKACCOUNT); print ''; - print $langs->trans("BankToReceiveWithdraw"); + $labelofbankfield = "BankToReceiveWithdraw"; + if ($object->type == 'bank-transfer') $labelofbankfield = 'BankToPayCreditTransfer'; + print $langs->trans($labelofbankfield); print ''; print ''; if ($acc->id > 0) @@ -129,9 +133,13 @@ if ($prev_id > 0 || $ref) print ''; print ''; - print $langs->trans("WithdrawalFile").''; + $labelfororderfield = 'WithdrawalFile'; + if ($object->type == 'bank-transfer') $labelfororderfield = 'CreditTransferFile'; + print $langs->trans($labelfororderfield).''; $relativepath = 'receipts/'.$object->ref.'.xml'; - print ''.$relativepath.''; + $modulepart = 'prelevement'; + if ($object->type == 'bank-transfer') $modulepart = 'paymentbybanktransfer'; + print ''.$relativepath.''; print ''; print ''; @@ -142,6 +150,7 @@ if ($prev_id > 0 || $ref) } } + $rej = new RejetPrelevement($db, $user); /* @@ -221,7 +230,7 @@ if ($resql) $i++; } } else { - print ''.$langs->trans("None").''; + print ''.$langs->trans("None").''; } if ($num > 0) diff --git a/htdocs/compta/prelevement/fiche-stat.php b/htdocs/compta/prelevement/fiche-stat.php index 0b1d9744b20..c59ed2d4232 100644 --- a/htdocs/compta/prelevement/fiche-stat.php +++ b/htdocs/compta/prelevement/fiche-stat.php @@ -20,7 +20,7 @@ /** * \file htdocs/compta/prelevement/fiche-stat.php * \ingroup prelevement - * \brief Prelevement statistics + * \brief Debit order or credit transfer statistics */ require '../../main.inc.php'; @@ -54,6 +54,17 @@ $pagenext = $page + 1; $object = new BonPrelevement($db); +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if (!$user->rights->prelevement->bons->lire && $object->type != 'bank-transfer') { + accessforbidden(); +} +if (!$user->rights->paymentbybanktransfer->read && $object->type == 'bank-transfer') { + accessforbidden(); +} + + /* * View @@ -68,7 +79,7 @@ if ($prev_id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'statistics', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); @@ -80,13 +91,6 @@ if ($prev_id > 0 || $ref) print ''.$langs->trans("Date").''.dol_print_date($object->datec, 'day').''; print ''.$langs->trans("Amount").''.price($object->amount).''; - // Status - /* - print ''.$langs->trans('Status').''; - print ''.$object->getLibStatut(1).''; - print ''; - */ - if ($object->date_trans <> 0) { $muser = new User($db); @@ -94,7 +98,7 @@ if ($prev_id > 0 || $ref) print ''.$langs->trans("TransData").''; print dol_print_date($object->date_trans, 'day'); - print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; + print ' '.$langs->trans("By").' '.$muser->getFullName($langs).''; print ''.$langs->trans("TransMetod").''; print $object->methodes_trans[$object->method_trans]; print ''; @@ -117,7 +121,9 @@ if ($prev_id > 0 || $ref) $result = $acc->fetch($conf->global->PRELEVEMENT_ID_BANKACCOUNT); print ''; - print $langs->trans("BankToReceiveWithdraw"); + $labelofbankfield = "BankToReceiveWithdraw"; + if ($object->type == 'bank-transfer') $labelofbankfield = 'BankToPayCreditTransfer'; + print $langs->trans($labelofbankfield); print ''; print ''; if ($acc->id > 0) @@ -126,23 +132,26 @@ if ($prev_id > 0 || $ref) print ''; print ''; - print $langs->trans("WithdrawalFile").''; + $labelfororderfield = 'WithdrawalFile'; + if ($object->type == 'bank-transfer') $labelfororderfield = 'CreditTransferFile'; + print $langs->trans($labelfororderfield).''; $relativepath = 'receipts/'.$object->ref.'.xml'; - print ''.$relativepath.''; + $modulepart = 'prelevement'; + if ($object->type == 'bank-transfer') $modulepart = 'paymentbybanktransfer'; + print ''.$relativepath.''; print ''; print ''; dol_fiche_end(); } else { - $langs->load("errors"); - print $langs->trans("Error"); + dol_print_error($db); } /* * Stats */ - $ligne = new LignePrelevement($db); + $line = new LignePrelevement($db); $sql = "SELECT sum(pl.amount), pl.statut"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl"; @@ -168,7 +177,7 @@ if ($prev_id > 0 || $ref) print ''; - print $ligne->LibStatut($row[1], 1); + print $line->LibStatut($row[1], 1); print ''; print price($row[0]); diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index e8c61c8b67c..eeb51e65442 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -10,6 +10,7 @@ * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2018-2019 Frédéric France * Copyright (C) 2019 Josep Lluís Amador + * Copyright (C) 2020 Open-Dsi * * 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 @@ -458,6 +459,23 @@ if (empty($reshook)) } } + if ($action == 'setprospectcontactlevel' && $user->rights->societe->contact->creer) + { + $object->fetch($id); + $object->fk_prospectlevel = GETPOST('prospect_contact_level_id', 'alpha'); + $result = $object->update($object->id, $user); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + } + + // set communication status + if ($action == 'setstcomm') + { + $object->fetch($id); + $object->stcomm_id = dol_getIdFromCode($db, GETPOST('stcomm', 'alpha'), 'c_stcommcontact'); + $result = $object->update($object->id, $user); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + } + // Actions to send emails $triggersendname = 'CONTACT_SENTBYMAIL'; $paramname = 'id'; @@ -1333,8 +1351,51 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''; print ''; - print ''; + + $object->fetch_thirdparty(); + + if (! empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { + if ($object->thirdparty->client == 2 || $object->thirdparty->client == 3) + { + print '
'; + + print '
'; + print ''; + + // Level of prospect + print '"; + print ''; + + // Status of prospection + $object->loadCacheOfProspStatus(); + print ''; + + print "
'; + print ''; + print '
'; + print $langs->trans('ProspectLevel'); + print ''; + if ($action != 'editlevel' && $user->rights->societe->contact->creer) print 'id . '">' . img_edit($langs->trans('Modify'), 1) . '
'; + print '
'; + if ($action == 'editlevel') { + $formcompany->formProspectContactLevel($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_prospectlevel, 'prospect_contact_level_id', 1); + } else { + print $object->getLibProspLevel(); + } + print "
' . $langs->trans("StatusProsp") . '' . $object->getLibProspCommStatut(4, $object->cacheprospectstatus[$object->stcomm_id]['label']); + print '     '; + print '
'; + foreach ($object->cacheprospectstatus as $key => $val) { + $titlealt = 'default'; + if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label']; + if ($object->stcomm_id != $val['id']) print '' . img_action($titlealt, $val['code'], $val['picto']) . ''; + } + print '
"; + print ''; + } + } + print '
'; print '
'; diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 0fd80dbdac9..c475c1b439d 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -10,6 +10,7 @@ * Copyright (C) 2013 Juanjo Menent * Copyright (C) 2015 Marcos García * Copyright (C) 2019 Nicolas ZABOURI + * Copyright (C) 2020 Open-Dsi * * 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 @@ -89,6 +90,8 @@ class Contact extends CommonObject 'socialnetworks' =>array('type'=>'text', 'label'=>'SocialNetworks', 'enabled'=>1, 'visible'=>-1, 'position'=>115), 'photo' =>array('type'=>'varchar(255)', 'label'=>'Photo', 'enabled'=>1, 'visible'=>-1, 'position'=>170), 'priv' =>array('type'=>'smallint(6)', 'label'=>'Private', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>175), + 'fk_stcomm' =>array('type'=>'integer', 'label'=>'Fk stcommcontact', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>220), + 'fk_prospectlevel' =>array('type'=>'varchar(12)', 'label'=>'ProspectLevel', 'enabled'=>1, 'visible'=>-1, 'position'=>255), 'no_email' =>array('type'=>'smallint(6)', 'label'=>'No email', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>180), 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'position'=>185), 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-1, 'position'=>190), @@ -209,6 +212,11 @@ class Contact extends CommonObject public $roles = array(); + public $cacheprospectstatus = array(); + public $fk_prospectlevel; + public $stcomm_id; + public $statut_commercial; + public $stcomm_picto; /** * Constructor @@ -224,6 +232,10 @@ class Contact extends CommonObject if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; if (empty($conf->mailing->enabled)) $this->fields['no_email']['enabled'] = 0; if (!empty($conf->global->SOCIETE_DISABLE_CONTACTS)) $this->fields['thirdparty']['enabled'] = 0; + if (empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { // Default behaviour + $this->field['fk_stcomm']['enabled'] = 0; + $this->field['fk_prospectlevel']['enabled'] = 0; + } $this->statut = 1; // By default, status is enabled // Unset fields that are disabled @@ -328,6 +340,7 @@ class Contact extends CommonObject $sql .= ", firstname"; $sql .= ", fk_user_creat"; $sql .= ", priv"; + $sql.= ", fk_stcommcontact"; $sql .= ", statut"; $sql .= ", canvas"; $sql .= ", entity"; @@ -341,6 +354,7 @@ class Contact extends CommonObject $sql .= "'".$this->db->escape($this->firstname)."',"; $sql .= " ".($user->id > 0 ? "'".$this->db->escape($user->id)."'" : "null").","; $sql .= " ".$this->db->escape($this->priv).","; + $sql.= " 0,"; $sql .= " ".$this->db->escape($this->statut).","; $sql .= " ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null").","; $sql .= " ".$this->db->escape($this->entity).","; @@ -465,6 +479,11 @@ class Contact extends CommonObject $sql .= ", phone_perso = ".(isset($this->phone_perso) ? "'".$this->db->escape($this->phone_perso)."'" : "null"); $sql .= ", phone_mobile = ".(isset($this->phone_mobile) ? "'".$this->db->escape($this->phone_mobile)."'" : "null"); $sql .= ", priv = '".$this->db->escape($this->priv)."'"; + $sql .= ", fk_prospectcontactlevel = '".$this->db->escape($this->fk_prospectlevel)."'"; + if (isset($this->stcomm_id)) + { + $sql .= ", fk_stcommcontact = ".($this->stcomm_id > 0 || $this->stcomm_id == -1 ? $this->stcomm_id : "0"); + } $sql .= ", statut = ".$this->db->escape($this->statut); $sql .= ", fk_user_modif=".($user->id > 0 ? "'".$this->db->escape($user->id)."'" : "NULL"); $sql .= ", default_lang=".($this->default_lang ? "'".$this->db->escape($this->default_lang)."'" : "NULL"); @@ -818,6 +837,7 @@ class Contact extends CommonObject $sql .= " c.socialnetworks,"; $sql .= " c.photo,"; $sql .= " c.priv, c.note_private, c.note_public, c.default_lang, c.canvas,"; + $sql.= " c.fk_prospectcontactlevel, c.fk_stcommcontact, st.libelle as stcomm, st.picto as stcomm_picto,"; $sql .= " c.import_key,"; $sql .= " c.datec as date_creation, c.tms as date_modification,"; $sql .= " co.label as country, co.code as country_code,"; @@ -829,6 +849,7 @@ class Contact extends CommonObject $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON c.fk_departement = d.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON c.rowid = u.fk_socpeople"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid"; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_stcommcontact as st ON c.fk_stcommcontact = st.id'; if ($id) $sql .= " WHERE c.rowid = ".$id; else { $sql .= " WHERE c.entity IN (".getEntity($this->element).")"; @@ -884,6 +905,14 @@ class Contact extends CommonObject $this->poste = $obj->poste; $this->statut = $obj->statut; + $this->fk_prospectlevel = $obj->fk_prospectcontactlevel; + + $transcode=$langs->trans('StatusProspect'.$obj->fk_stcommcontact); + $libelle=($transcode!='StatusProspect'.$obj->fk_stcommcontact?$transcode:$obj->stcomm); + $this->stcomm_id = $obj->fk_stcommcontact; // id statut commercial + $this->statut_commercial = $libelle; // libelle statut commercial + $this->stcomm_picto = $obj->stcomm_picto; // Picto statut commercial + $this->phone_pro = trim($obj->phone); $this->fax = trim($obj->fax); $this->phone_perso = trim($obj->phone_perso); @@ -1701,4 +1730,137 @@ class Contact extends CommonObject return $error * -1; } } + + /** + * Load array of prospect status + * + * @param int $active 1=Active only, 0=Not active only, -1=All + * @return int <0 if KO, >0 if OK + */ + public function loadCacheOfProspStatus($active = 1) + { + global $langs; + + $sql = "SELECT id, code, libelle as label, picto FROM " . MAIN_DB_PREFIX . "c_stcommcontact"; + if ($active >= 0) $sql .= " WHERE active = " . $active; + $resql = $this->db->query($sql); + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + $this->cacheprospectstatus[$obj->id] = array('id' => $obj->id, 'code' => $obj->code, 'label' => ($langs->trans("ST_" . strtoupper($obj->code)) == "ST_" . strtoupper($obj->code)) ? $obj->label : $langs->trans("ST_" . strtoupper($obj->code)), 'picto' => $obj->picto); + $i++; + } + return 1; + } + + /** + * Return prostect level + * + * @return string Libelle + */ + public function getLibProspLevel() + { + return $this->libProspLevel($this->fk_prospectlevel); + } + + /** + * Return label of prospect level + * + * @param int $fk_prospectlevel Prospect level + * @return string label of level + */ + public function libProspLevel($fk_prospectlevel) + { + global $langs; + + $lib = $langs->trans("ProspectLevel" . $fk_prospectlevel); + // If lib not found in language file, we get label from cache/databse + if ($lib == $langs->trans("ProspectLevel" . $fk_prospectlevel)) + { + $lib = $langs->getLabelFromKey($this->db, $fk_prospectlevel, 'c_prospectlevel', 'code', 'label'); + } + return $lib; + } + + + /** + * Set prospect level + * + * @param User $user Utilisateur qui definie la remise + * @return int <0 if KO, >0 if OK + * @deprecated Use update function instead + */ + public function setProspectLevel(User $user) + { + return $this->update($this->id, $user); + } + + /** + * Return status of prospect + * + * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long + * @param string $label Label to use for status for added status + * @return string Libelle + */ + public function getLibProspCommStatut($mode = 0, $label = '') + { + return $this->libProspCommStatut($this->stcomm_id, $mode, $label, $this->stcomm_picto); + } + + /** + * Return label of a given status + * + * @param int|string $statut Id or code for prospection status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @param string $label Label to use for status for added status + * @param string $picto Name of image file to show ('filenew', ...) + * If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory. + * Example: picto.png if picto.png is stored into htdocs/theme/mytheme/img + * Example: picto.png@mymodule if picto.png is stored into htdocs/mymodule/img + * Example: /mydir/mysubdir/picto.png if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1) + * @return string Libelle du statut + */ + public function libProspCommStatut($statut, $mode = 0, $label = '', $picto = '') + { + global $langs; + $langs->load('customers'); + + if ($mode == 2) + { + if ($statut == '-1' || $statut == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto) . ' ' . $langs->trans("StatusProspect-1"); + elseif ($statut == '0' || $statut == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto) . ' ' . $langs->trans("StatusProspect0"); + elseif ($statut == '1' || $statut == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto) . ' ' . $langs->trans("StatusProspect1"); + elseif ($statut == '2' || $statut == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto) . ' ' . $langs->trans("StatusProspect2"); + elseif ($statut == '3' || $statut == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto) . ' ' . $langs->trans("StatusProspect3"); + else { + return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto) . ' ' . (($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label); + } + } + if ($mode == 3) + { + if ($statut == '-1' || $statut == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto); + elseif ($statut == '0' || $statut == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto); + elseif ($statut == '1' || $statut == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto); + elseif ($statut == '2' || $statut == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto); + elseif ($statut == '3' || $statut == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto); + else { + return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto); + } + } + if ($mode == 4) + { + if ($statut == '-1' || $statut == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto) . ' ' . $langs->trans("StatusProspect-1"); + elseif ($statut == '0' || $statut == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto) . ' ' . $langs->trans("StatusProspect0"); + elseif ($statut == '1' || $statut == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto) . ' ' . $langs->trans("StatusProspect1"); + elseif ($statut == '2' || $statut == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto) . ' ' . $langs->trans("StatusProspect2"); + elseif ($statut == '3' || $statut == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto) . ' ' . $langs->trans("StatusProspect3"); + else { + return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto) . ' ' . (($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label); + } + } + + return "Error, mode/status not found"; + } } diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 3f7791019ec..9eeae17280f 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -11,6 +11,7 @@ * Copyright (C) 2018 Juanjo Menent * Copyright (C) 2019 Frédéric France * Copyright (C) 2019 Josep Lluís Amador + * Copyright (C) 2020 Open-Dsi * * 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 @@ -91,6 +92,8 @@ $search_town = GETPOST('search_town', 'alpha'); $search_import_key = GETPOST("search_import_key", "alpha"); $search_country = GETPOST("search_country", 'intcomma'); $search_roles = GETPOST("search_roles", 'array'); +$search_level = GETPOST("search_level", "array"); +$search_stcomm = GETPOST('search_stcomm', 'int'); if ($search_status == '') $search_status = 1; // always display active customer first @@ -141,7 +144,7 @@ $hookmanager->initHooks(array('contactlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('contact'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); @@ -181,6 +184,11 @@ $arrayfields = array( 'p.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000), 'p.import_key'=>array('label'=>"ImportId", 'checked'=>0, 'position'=>1100), ); +if (! empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { + $arrayfields['p.fk_prospectcontactlevel'] = array('label'=>"ProspectLevelShort", 'checked'=>1, 'position'=>210); + $arrayfields['p.fk_stcommcontact'] = array('label'=>"StatusProsp", 'checked'=>1, 'position'=>215); +} + if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { if ($value['active']) { @@ -198,7 +206,13 @@ if (is_array($extrafields->attributes[$object->table_element]['label']) && count foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) - $arrayfields["ef.".$key] = array('label'=>$extrafields->attributes[$object->table_element]['label'][$key], 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key])); + $arrayfields["ef.".$key] = array( + 'label'=>$extrafields->attributes[$object->table_element]['label'][$key], + 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), + 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], + 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]), + 'langfile'=>$extrafields->attributes[$object->table_element]['langfile'][$key], + ); } } $object->fields = dol_sort_array($object->fields, 'position'); @@ -256,6 +270,8 @@ if (empty($reshook)) } } $search_priv = ""; + $search_stcomm=''; + $search_level=''; $search_status = -1; $search_categ = ''; $search_categ_thirdparty = ''; @@ -273,6 +289,17 @@ if (empty($reshook)) $permissiontodelete = $user->rights->societe->supprimer; $uploaddir = $conf->societe->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if ($action == 'setstcomm') + { + $object = new Contact($db); + $result = $object->fetch(GETPOST('stcommcontactid')); + $object->stcomm_id = dol_getIdFromCode($db, GETPOST('stcomm', 'alpha'), 'c_stcommcontact'); + $result = $object->update($object->id, $user); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + + $action = ''; + } } if ($search_priv < 0) $search_priv = ''; @@ -287,12 +314,36 @@ $formother = new FormOther($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); +if (! empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { + $contactstatic->loadCacheOfProspStatus(); +} + $title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); +// Select every potentiels, and note each potentiels which fit in search parameters +$tab_level = array(); +$sql = "SELECT code, label, sortorder"; +$sql.= " FROM ".MAIN_DB_PREFIX."c_prospectcontactlevel"; +$sql.= " WHERE active > 0"; +$sql.= " ORDER BY sortorder"; +$resql = $db->query($sql); +if ($resql) +{ + while ($obj = $db->fetch_object($resql)) + { + // Compute level text + $level=$langs->trans($obj->code); + if ($level == $obj->code) $level=$langs->trans($obj->label); + $tab_level[$obj->code] = $level; + } +} +else dol_print_error($db); + $sql = "SELECT s.rowid as socid, s.nom as name,"; $sql .= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.zip, p.town, p.poste, p.email, p.no_email,"; $sql .= " p.socialnetworks, p.photo,"; $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,"; +$sql.= " st.libelle as stcomm, st.picto as stcomm_picto, p.fk_stcommcontact as stcomm_id, p.fk_prospectcontactlevel,"; $sql .= " co.label as country, co.code as country_code"; // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { @@ -306,6 +357,7 @@ $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as p"; if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (p.rowid = ef.fk_object)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = p.fk_pays"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc"; +$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_stcommcontact as st ON st.id = p.fk_stcommcontact"; if (!empty($search_categ)) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_contact as cc ON p.rowid = cc.fk_socpeople"; // We need this table joined to the select in order to filter by categ if (!empty($search_categ_thirdparty)) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cs ON s.rowid = cs.fk_soc"; // We need this table joined to the select in order to filter by categ if (!empty($search_categ_supplier)) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_fournisseur as cs2 ON s.rowid = cs2.fk_soc"; // We need this table joined to the select in order to filter by categ @@ -319,6 +371,8 @@ if (!empty($userid)) // propre au commercial { $sql .= " AND p.fk_user_creat=".$db->escape($userid); } +if ($search_level) $sql .= natural_search("p.fk_prospectcontactlevel", join(',', $search_level), 3); +if ($search_stcomm != '' && $search_stcomm != -2) $sql .= natural_search("p.fk_stcommcontact", $search_stcomm, 2); // Filter to exclude not owned private contacts if ($search_priv != '0' && $search_priv != '1') @@ -403,8 +457,8 @@ if ($view == "recent") $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $result = $db->query($sql); - $nbtotalofrecords = $db->num_rows($result); + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0 { $page = 0; @@ -414,14 +468,14 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) $sql .= $db->plimit($limit + 1, $offset); -$result = $db->query($sql); -if (!$result) +$resql = $db->query($sql); +if (! $resql) { dol_print_error($db); exit; } -$num = $db->num_rows($result); +$num = $db->num_rows($resql); $arrayofselected = is_array($toselect) ? $toselect : array(); @@ -461,8 +515,14 @@ if ($search_email != '') $param .= '&search_email='.urlencode($search_email) if ($search_no_email != '') $param .= '&search_no_email='.urlencode($search_no_email); if ($search_status != '') $param .= '&search_status='.urlencode($search_status); if ($search_priv == '0' || $search_priv == '1') $param .= "&search_priv=".urlencode($search_priv); +if ($search_stcomm != '') $param.='&search_stcomm='.urlencode($search_stcomm); +if (is_array($search_level) && count($search_level)) { + foreach ($search_level as $slevel) { + $param.='&search_level[]='.urlencode($slevel); + } +} if ($search_import_key != '') $param .= '&search_import_key='.urlencode($search_import_key); -if ($optioncss != '') $param .= '&optioncss='.$optioncss; +if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); if (count($search_roles) > 0) $param .= implode('&search_roles[]=', $search_roles); // Add $param from extra fields @@ -678,6 +738,25 @@ if (!empty($arrayfields['p.priv']['checked'])) print $form->selectarray('search_priv', $selectarray, $search_priv, 1); print ''; } +// Prospect level +if (! empty($arrayfields['p.fk_prospectcontactlevel']['checked'])) +{ + print ''; + print $form->multiselectarray('search_level', $tab_level, $search_level, 0, 0, 'width75', 0, 0, '', '', '', 2); + print ''; +} +// Prospect status +if (! empty($arrayfields['p.fk_stcommcontact']['checked'])) +{ + print ''; + $arraystcomm=array(); + foreach ($contactstatic->cacheprospectstatus as $key => $val) + { + $arraystcomm[$val['id']]=($langs->trans("StatusProspect".$val['id']) != "StatusProspect".$val['id'] ? $langs->trans("StatusProspect".$val['id']) : $val['label']); + } + print $form->selectarray('search_stcomm', $arraystcomm, $search_stcomm, -2, 0, 0, '', 0, 0, 0, '', 'nowrap '); + print ''; +} // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -746,6 +825,8 @@ if (!empty($conf->socialnetworks->enabled)) { } if (!empty($arrayfields['p.thirdparty']['checked'])) print_liste_field_titre($arrayfields['p.thirdparty']['label'], $_SERVER["PHP_SELF"], "s.nom", $begin, $param, '', $sortfield, $sortorder); if (!empty($arrayfields['p.priv']['checked'])) print_liste_field_titre($arrayfields['p.priv']['label'], $_SERVER["PHP_SELF"], "p.priv", $begin, $param, '', $sortfield, $sortorder, 'center '); +if (!empty($arrayfields['p.fk_prospectcontactlevel']['checked'])) print_liste_field_titre($arrayfields['p.fk_prospectcontactlevel']['label'], $_SERVER["PHP_SELF"], "p.fk_prospectcontactlevel", "", $param, '', $sortfield, $sortorder, 'center '); +if (!empty($arrayfields['p.fk_stcommcontact']['checked'])) print_liste_field_titre($arrayfields['p.fk_stcommcontact']['label'], $_SERVER["PHP_SELF"], "p.fk_stcommcontact", "", $param, '', $sortfield, $sortorder, 'center '); // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields @@ -777,7 +858,7 @@ $i = 0; $totalarray = array(); while ($i < min($num, $limit)) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); $arraysocialnetworks = (array) json_decode($obj->socialnetworks, true); $contactstatic->lastname = $obj->lastname; @@ -796,6 +877,8 @@ while ($i < min($num, $limit)) $contactstatic->country_code = $obj->country_code; $contactstatic->photo = $obj->photo; + $contactstatic->fk_prospectlevel=$obj->fk_prospectcontactlevel; + print ''; // ID @@ -924,6 +1007,30 @@ while ($i < min($num, $limit)) if (!$i) $totalarray['nbfield']++; } + if (! empty($arrayfields['p.fk_prospectcontactlevel']['checked'])) + { + // Prospect level + print ''; + print $contactstatic->getLibProspLevel(); + print ""; + if (!$i) $totalarray['nbfield']++; + } + + if (! empty($arrayfields['p.fk_stcommcontact']['checked'])) + { + // Prospect status + print '
'; + print '
' . $contactstatic->libProspCommStatut($obj->stcomm_id, 2, $contactstatic->cacheprospectstatus[$obj->stcomm_id]['label'], $obj->stcomm_picto); + print '
-
'; + foreach ($contactstatic->cacheprospectstatus as $key => $val) { + $titlealt = 'default'; + if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label']; + if ($obj->stcomm_id != $val['id']) print '' . img_action($titlealt, $val['code'], $val['picto']) . ''; + } + print '
'; + if (!$i) $totalarray['nbfield']++; + } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook @@ -975,7 +1082,7 @@ while ($i < min($num, $limit)) $i++; } -$db->free($result); +$db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 12ad603ea14..ac5f8146a8d 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -726,6 +726,7 @@ class Contrat extends CommonObject $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->fk_projet = $obj->fk_project; // deprecated @@ -2309,6 +2310,8 @@ class Contrat extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; $sql .= " AND tosell = 1"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -2393,6 +2396,7 @@ class Contrat extends CommonObject global $conf, $langs; $langs->load("contracts"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'strato'; diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index 3627661c727..8afc2f0e335 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -100,7 +100,7 @@ $hookmanager->initHooks(array('contractlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('contrat'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // List of fields to search into when doing a "search in all" diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 18a5b561387..38aae136b39 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -84,7 +84,7 @@ $hookmanager->initHooks(array('contractservicelist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('contratdet'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 6f9144330e1..a9c3fb713c5 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -156,7 +156,7 @@ if ($action == 'update' && !empty($permissiontoadd)) } elseif (preg_match('/^(integer|price|real|double)/', $object->fields[$key]['type'])) { $value = price2num(GETPOST($key, 'none')); // To fix decimal separator according to lang setup } elseif ($object->fields[$key]['type'] == 'boolean') { - $value = (GETPOST($key) == 'on' ? 1 : 0); + $value = ((GETPOST($key, 'aZ09') == 'on' || GETPOST($key, 'aZ09') == '1') ? 1 : 0); } else { $value = GETPOST($key, 'alpha'); } @@ -206,7 +206,7 @@ if ($action == "update_extras" && !empty($permissiontoadd)) $object->array_options['options_'.$attributekey] = dol_mktime(GETPOST($attributekeylong.'hour', 'int'), GETPOST($attributekeylong.'min', 'int'), GETPOST($attributekeylong.'sec', 'int'), GETPOST($attributekeylong.'month', 'int'), GETPOST($attributekeylong.'day', 'int'), GETPOST($attributekeylong.'year', 'int')); //var_dump(dol_print_date($object->array_options['options_'.$attributekey]));exit; } else { - $object->array_options['options_'.$attributekey] = GETPOST($attributekeylong, ' alpha'); + $object->array_options['options_'.$attributekey] = GETPOST($attributekeylong, 'alpha'); } $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user); @@ -245,7 +245,11 @@ if ($action == 'confirm_delete' && !empty($permissiontodelete)) // Remove a line if ($action == 'confirm_deleteline' && $confirm == 'yes' && !empty($permissiontoadd)) { - $result = $object->deleteline($user, $lineid); + if (method_exists('deleteline', $object)) { + $result = $object->deleteline($user, $lineid); // For backward compatibility + } else { + $result = $object->deleteLine($user, $lineid); + } if ($result > 0) { // Define output language @@ -264,8 +268,10 @@ if ($action == 'confirm_deleteline' && $confirm == 'yes' && !empty($permissionto $outputlangs->setDefaultLang($newlang); } if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { - $ret = $object->fetch($object->id); // Reload to get new records - $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + if (method_exists($object, 'generateDocument')) { + $ret = $object->fetch($object->id); // Reload to get new records + $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + } } setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs'); @@ -283,20 +289,21 @@ if ($action == 'confirm_validate' && $confirm == 'yes' && $permissiontoadd) if ($result >= 0) { // Define output language - if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) - { - $outputlangs = $langs; - $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; - if (!empty($newlang)) { - $outputlangs = new Translate("", $conf); - $outputlangs->setDefaultLang($newlang); - } - $model = $object->modelpdf; - $ret = $object->fetch($id); // Reload to get new records + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + if (method_exists($object, 'generateDocument')) { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model = $object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records - $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } } } else { setEventMessages($object->error, $object->errors, 'errors'); @@ -310,20 +317,21 @@ if ($action == 'confirm_close' && $confirm == 'yes' && $permissiontoadd) if ($result >= 0) { // Define output language - if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) - { - $outputlangs = $langs; - $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; - if (!empty($newlang)) { - $outputlangs = new Translate("", $conf); - $outputlangs->setDefaultLang($newlang); - } - $model = $object->modelpdf; - $ret = $object->fetch($id); // Reload to get new records + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + if (method_exists($object, 'generateDocument')) { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model = $object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records - $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } } } else { setEventMessages($object->error, $object->errors, 'errors'); @@ -349,20 +357,21 @@ if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) if ($result >= 0) { // Define output language - if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) - { - $outputlangs = $langs; - $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; - if (!empty($newlang)) { - $outputlangs = new Translate("", $conf); - $outputlangs->setDefaultLang($newlang); - } - $model = $object->modelpdf; - $ret = $object->fetch($id); // Reload to get new records + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + if (method_exists($object, 'generateDocument')) { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model = $object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records - $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } } } else { setEventMessages($object->error, $object->errors, 'errors'); diff --git a/htdocs/core/boxes/box_contacts.php b/htdocs/core/boxes/box_contacts.php index caea252c571..7141728c23d 100644 --- a/htdocs/core/boxes/box_contacts.php +++ b/htdocs/core/boxes/box_contacts.php @@ -94,7 +94,7 @@ class box_contacts extends ModeleBoxes $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON sp.fk_soc = s.rowid"; if (!$user->rights->societe->client->voir && !$user->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql .= " WHERE sp.entity IN (".getEntity('socpeople').")"; - if (!$user->rights->societe->client->voir && !$user->socid) $sql .= " AND sp.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; + if (!$user->rights->societe->client->voir && !$user->socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if ($user->socid) $sql .= " AND sp.fk_soc = ".$user->socid; $sql .= " ORDER BY sp.tms DESC"; $sql .= $this->db->plimit($max, 0); diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 9ec895926a0..bca09cb967e 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -268,6 +268,28 @@ class CMailFile } } + $this->addr_to = $to; + $this->addr_cc = $addr_cc; + $this->addr_bcc = $addr_bcc; + $this->reply_to = $replyto; + $this->addr_from = $from; + $this->subject = $subject; + $this->errors_to = $errors_to; + $this->deliveryreceipt = $deliveryreceipt; + $this->trackid = $trackid; + + if (!empty($conf->global->MAIN_MAIL_FORCE_SENDTO)) + { + $this->addr_to = $conf->global->MAIN_MAIL_FORCE_SENDTO; + $this->addr_cc = ''; + $this->addr_bcc = ''; + } + + // Add autocopy to (Note: Adding bcc for specific modules are also done from pages) + if (!empty($conf->global->MAIN_MAIL_AUTOCOPY_TO)) { + $addr_bcc.=($addr_bcc?', ':'').$conf->global->MAIN_MAIL_AUTOCOPY_TO; + } + // We set all data according to choosed sending method. // We also set a value for ->msgid if ($this->sendmode == 'mail') @@ -327,16 +349,16 @@ class CMailFile $smtps->setCharSet($conf->file->character_set_client); // Encode subject if required. - $subjecttouse = $subject; + $subjecttouse = $this->subject; if (!ascii_check($subjecttouse)) { $subjecttouse = $this->encodetorfc2822($subjecttouse); } $smtps->setSubject($subjecttouse); - $smtps->setTO($this->getValidAddress($to, 0, 1)); - $smtps->setFrom($this->getValidAddress($from, 0, 1)); - $smtps->setTrackId($trackid); - $smtps->setReplyTo($this->getValidAddress($replyto, 0, 1)); + $smtps->setTO($this->getValidAddress($this->addr_to, 0, 1)); + $smtps->setFrom($this->getValidAddress($this->addr_from, 0, 1)); + $smtps->setTrackId($this->trackid); + $smtps->setReplyTo($this->getValidAddress($this->replyto, 0, 1)); if (!empty($moreinheader)) $smtps->setMoreInHeader($moreinheader); @@ -374,17 +396,16 @@ class CMailFile } } - $smtps->setCC($addr_cc); - $smtps->setBCC($addr_bcc); - $smtps->setErrorsTo($errors_to); - $smtps->setDeliveryReceipt($deliveryreceipt); + $smtps->setCC($this->addr_cc); + $smtps->setBCC($this->addr_bcc); + $smtps->setErrorsTo($this->errors_to); + $smtps->setDeliveryReceipt($this->deliveryreceipt); $host = dol_getprefix('email'); - $this->msgid = time().'.SMTPs-dolibarr-'.$trackid.'@'.$host; + $this->msgid = time().'.SMTPs-dolibarr-'.$this->trackid.'@'.$host; $this->smtps = $smtps; - } elseif ($this->sendmode == 'swiftmailer') - { + } elseif ($this->sendmode == 'swiftmailer') { // Use Swift Mailer library $host = dol_getprefix('email'); @@ -401,8 +422,8 @@ class CMailFile //$this->message = new Swift_SignedMessage(); // Adding a trackid header to a message $headers = $this->message->getHeaders(); - $headers->addTextHeader('X-Dolibarr-TRACKID', $trackid.'@'.$host); - $this->msgid = time().'.swiftmailer-dolibarr-'.$trackid.'@'.$host; + $headers->addTextHeader('X-Dolibarr-TRACKID', $this->trackid.'@'.$host); + $this->msgid = time().'.swiftmailer-dolibarr-'.$this->trackid.'@'.$host; $headerID = $this->msgid; $msgid = $headers->get('Message-ID'); $msgid->setId($headerID); @@ -411,14 +432,14 @@ class CMailFile // Give the message a subject try { - $result = $this->message->setSubject($subject); + $result = $this->message->setSubject($this->subject); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } // Set the From address with an associative array //$this->message->setFrom(array('john@doe.com' => 'John Doe')); - if (!empty($from)) { + if (! empty($this->addr_from)) { try { if (! empty($conf->global->MAIN_FORCE_DISABLE_MAIL_SPOOFING)) { // Prevent email spoofing for smtp server with a strict configuration @@ -429,10 +450,10 @@ class CMailFile { $result = $this->message->setFrom($conf->global->MAIN_MAIL_SMTPS_ID); } else { - $result = $this->message->setFrom($this->getArrayAddress($from)); + $result = $this->message->setFrom($this->getArrayAddress($this->addr_from)); } } else { - $result = $this->message->setFrom($this->getArrayAddress($from)); + $result = $this->message->setFrom($this->getArrayAddress($this->addr_from)); } } catch (Exception $e) { $this->errors[] = $e->getMessage(); @@ -440,17 +461,17 @@ class CMailFile } // Set the To addresses with an associative array - if (!empty($to)) { + if (! empty($this->addr_to)) { try { - $result = $this->message->setTo($this->getArrayAddress($to)); + $result = $this->message->setTo($this->getArrayAddress($this->addr_to)); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } } - if (!empty($replyto)) { + if (! empty($this->reply_to)) { try { - $result = $this->message->SetReplyTo($this->getArrayAddress($replyto)); + $result = $this->message->SetReplyTo($this->getArrayAddress($this->reply_to)); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } @@ -504,10 +525,10 @@ class CMailFile } } - if (!empty($addr_cc)) $this->message->setCc($this->getArrayAddress($addr_cc)); - if (!empty($addr_bcc)) $this->message->setBcc($this->getArrayAddress($addr_bcc)); + if (! empty($this->addr_cc)) $this->message->setCc($this->getArrayAddress($this->addr_cc)); + if (! empty($this->addr_bcc)) $this->message->setBcc($this->getArrayAddress($this->addr_bcc)); //if (! empty($errors_to)) $this->message->setErrorsTo($this->getArrayAddress($errors_to); - if (isset($deliveryreceipt) && $deliveryreceipt == 1) $this->message->setReadReceiptTo($this->getArrayAddress($from)); + if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) $this->message->setReadReceiptTo($this->getArrayAddress($this->addr_from)); } else { // Send mail method not correctly defined // -------------------------------------- @@ -624,13 +645,6 @@ class CMailFile $keyforstarttls = 'MAIN_MAIL_EMAIL_STARTTLS_EMAILING'; } - if (!empty($conf->global->MAIN_MAIL_FORCE_SENDTO)) - { - $this->addr_to = $conf->global->MAIN_MAIL_FORCE_SENDTO; - $this->addr_cc = ''; - $this->addr_bcc = ''; - } - // Action according to choosed sending method if ($this->sendmode == 'mail') { @@ -772,14 +786,14 @@ class CMailFile $from = $this->smtps->getFrom('org'); if ($res && !$from) { - $this->error = "Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
Sender address '$from' invalid"; + $this->error = "Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport." - Sender address '$from' invalid"; dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); $res = false; } $dest = $this->smtps->getTo(); if ($res && !$dest) { - $this->error = "Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
Recipient address '$dest' invalid"; + $this->error = "Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport." - Recipient address '$dest' invalid"; dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); $res = false; } @@ -800,7 +814,7 @@ class CMailFile $res = true; } else { if (empty($this->error)) $this->error = $result; - dol_syslog("CMailFile::sendfile: mail end error with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
".$this->error, LOG_ERR); + dol_syslog("CMailFile::sendfile: mail end error with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport." - ".$this->error, LOG_ERR); $res = false; } } diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 0b8b99bd395..f610e6bb952 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1072,7 +1072,8 @@ abstract class CommonDocGenerator $parameters = array( 'curY' => &$curY, 'columnText' => $columnText, - 'colKey' => $colKey + 'colKey' => $colKey, + 'pdf' => &$pdf, ); $reshook = $hookmanager->executeHooks('printStdColumnContent', $parameters, $this); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 885dcb5c490..366b1b038e2 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -314,7 +314,7 @@ abstract class CommonObject * @var string * @see SetDocModel() */ - public $modelpdf; + public $model_pdf; /** * @var string @@ -1858,14 +1858,15 @@ abstract class CommonObject $row = $this->db->fetch_row($result); $this->ref_previous = $row[0]; - $sql = "SELECT MIN(te.".$fieldid.")"; $sql .= " FROM ".(empty($nodbprefix) ?MAIN_DB_PREFIX:'').$this->table_element." as te"; if ($this->element == 'user' && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { $sql .= ",".MAIN_DB_PREFIX."usergroup_user as ug"; } - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 'fk_soc@societe') $sql .= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to entity - elseif ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to socid + if (isset($this->ismultientitymanaged) && !is_numeric($this->ismultientitymanaged)) { + $tmparray = explode('@', $this->ismultientitymanaged); + $sql .= ", ".MAIN_DB_PREFIX.$tmparray[1]." as ".($tmparray[1] == 'societe' ? 's' : 'parenttable'); // If we need to link to this table to limit select to entity + } elseif ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to socid elseif ($this->restrictiononfksoc == 2 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON te.fk_soc = s.rowid"; // If we need to link to societe to limit select to socid if ($this->restrictiononfksoc && !$user->rights->societe->client->voir && !$socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$aliastablesociete.".rowid = sc.fk_soc"; $sql .= " WHERE te.".$fieldid." > '".$this->db->escape($fieldid=='rowid' ? $this->id : $this->ref)."'"; // ->ref must always be defined (set to id if field does not exists) @@ -1876,8 +1877,10 @@ abstract class CommonObject if (!preg_match('/^\s*AND/i', $filter)) $sql .= " AND "; // For backward compatibility $sql .= $filter; } - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 'fk_soc@societe') $sql .= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to entity - elseif ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql .= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to socid + if (isset($this->ismultientitymanaged) && !is_numeric($this->ismultientitymanaged)) { + $tmparray = explode('@', $this->ismultientitymanaged); + $sql .= ' AND te.'.$tmparray[0].' = '.($tmparray[1] == 'societe' ? 's' : 'parenttable').'.rowid'; // If we need to link to this table to limit select to entity + } elseif ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql .= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to socid if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { if ($this->element == 'user' && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { if (!empty($user->admin) && empty($user->entity) && $conf->entity == 1) { @@ -1890,6 +1893,10 @@ abstract class CommonObject $sql .= ' AND te.entity IN ('.getEntity($this->element).')'; } } + if (isset($this->ismultientitymanaged) && !is_numeric($this->ismultientitymanaged) && $this->element != 'societe') { + $tmparray = explode('@', $this->ismultientitymanaged); + $sql .= ' AND parenttable.entity IN ('.getEntity($tmparray[1]).')'; + } if ($this->restrictiononfksoc == 1 && $socid && $this->element != 'societe') $sql .= ' AND te.fk_soc = '.$socid; if ($this->restrictiononfksoc == 2 && $socid && $this->element != 'societe') $sql .= ' AND (te.fk_soc = '.$socid.' OR te.fk_soc IS NULL)'; if ($this->restrictiononfksoc && $socid && $this->element == 'societe') $sql .= ' AND te.rowid = '.$socid; @@ -2368,7 +2375,8 @@ abstract class CommonObject $resql = $this->db->query($sql); if ($resql) { - $this->modelpdf = $modelpdf; + $this->model_pdf = $modelpdf; + $this->modelpdf = $modelpdf; // For bakward compatibility return 1; } else { dol_print_error($this->db); @@ -2840,12 +2848,14 @@ abstract class CommonObject dol_syslog(get_class($this)."::update_note Parameter suffix must be empty, '_private' or '_public'", LOG_ERR); return -2; } + + $newsuffix = $suffix; + // Special cas - //var_dump($this->table_element);exit; - if ($this->table_element == 'product') $suffix = ''; + if ($this->table_element == 'product' && $newsuffix == '_private') $newsuffix = ''; $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql .= " SET note".$suffix." = ".(!empty($note) ? ("'".$this->db->escape($note)."'") : "NULL"); + $sql .= " SET note".$newsuffix." = ".(!empty($note) ? ("'".$this->db->escape($note)."'") : "NULL"); $sql .= " ,".(in_array($this->table_element, array('actioncomm', 'adherent', 'advtargetemailing', 'cronjob', 'establishment')) ? "fk_user_mod" : "fk_user_modif")." = ".$user->id; $sql .= " WHERE rowid =".$this->id; @@ -4529,7 +4539,7 @@ abstract class CommonObject * Common function for all objects extending CommonObject for generating documents * * @param string $modelspath Relative folder where generators are placed - * @param string $modele Generator to use. Caller must set it to obj->modelpdf or GETPOST('modelpdf','alpha') for example. + * @param string $modele Generator to use. Caller must set it to obj->model_pdf or GETPOST('model_pdf','alpha') for example. * @param Translate $outputlangs Output language to use * @param int $hidedetails 1 to hide details. 0 by default * @param int $hidedesc 1 to hide product description. 0 by default @@ -5132,7 +5142,7 @@ abstract class CommonObject } } $sql .= " FROM ".MAIN_DB_PREFIX.$table_element."_extrafields"; - $sql .= " WHERE fk_object = ".$rowid; + $sql .= " WHERE fk_object = ".((int) $rowid); //dol_syslog(get_class($this)."::fetch_optionals get extrafields data for ".$this->table_element, LOG_DEBUG); // Too verbose $resql = $this->db->query($sql); @@ -5302,11 +5312,12 @@ abstract class CommonObject $new_array_options[$key] = null; } break; - case 'double': + case 'price': + case 'double': $value = price2num($value); if (!is_numeric($value) && $value != '') { - dol_syslog($langs->trans("ExtraFieldHasWrongValue")." sur ".$attributeLabel."(".$value."is not '".$attributeType."')", LOG_DEBUG); + dol_syslog($langs->trans("ExtraFieldHasWrongValue")." for ".$attributeLabel."(".$value."is not '".$attributeType."')", LOG_DEBUG); $this->errors[] = $langs->trans("ExtraFieldHasWrongValue", $attributeLabel); return -1; } elseif ($value == '') @@ -5354,9 +5365,6 @@ abstract class CommonObject $new_array_options[$key] = $this->array_options[$key]; } break; - case 'price': - $new_array_options[$key] = price2num($this->array_options[$key]); - break; case 'date': case 'datetime': // If data is a string instead of a timestamp, we convert it @@ -5448,7 +5456,7 @@ abstract class CommonObject { if (!isset($extrafields->attributes[$this->table_element]['type'][$tmpkey])) // If field not already added previously { - if (in_array($tmpval, array('int', 'double'))) $sql .= ", 0"; + if (in_array($tmpval, array('int', 'double', 'price'))) $sql .= ", 0"; else $sql .= ", ''"; } } @@ -6724,7 +6732,7 @@ abstract class CommonObject if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label']) > 0) { $out .= "\n"; - $out .= ' '; + $out .= ' '; $out .= "\n"; $extrafields_collapse_num = ''; @@ -6858,7 +6866,7 @@ abstract class CommonObject // HTML, select, integer and text add default value if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('html', 'text', 'select', 'int'))) { - if ($action == 'create') $value = $extrafields->attributes[$this->table_element]['default'][$key]; + if ($action == 'create') $value = GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix) ? GETPOST($keyprefix.'options_'.$key.$keysuffix, 'none', 3) : $extrafields->attributes[$this->table_element]['default'][$key]; else $value = $this->array_options['options_'.$key]; } @@ -6944,7 +6952,7 @@ abstract class CommonObject '."\n"; } - $out .= ' '."\n"; + $out .= ' '."\n"; } } @@ -7611,11 +7619,11 @@ abstract class CommonObject if (array_key_exists('ref', $fieldvalues)) $fieldvalues['ref'] = dol_string_nospecial($fieldvalues['ref']); // If field is a ref, we sanitize data $keys = array(); - $values = array(); + $values = array(); // Array to store string forged for SQL syntax foreach ($fieldvalues as $k => $v) { $keys[$k] = $k; $value = $this->fields[$k]; - $values[$k] = $this->quote($v, $value); + $values[$k] = $this->quote($v, $value); // May return string 'NULL' if $value is null } // Clean and check mandatory @@ -7625,8 +7633,7 @@ abstract class CommonObject if (preg_match('/^integer:/i', $this->fields[$key]['type']) && $values[$key] == '-1') $values[$key] = ''; if (!empty($this->fields[$key]['foreignkey']) && $values[$key] == '-1') $values[$key] = ''; - //var_dump($key.'-'.$values[$key].'-'.($this->fields[$key]['notnull'] == 1)); - if (isset($this->fields[$key]['notnull']) && $this->fields[$key]['notnull'] == 1 && !isset($values[$key]) && is_null($this->fields[$key]['default'])) + if (isset($this->fields[$key]['notnull']) && $this->fields[$key]['notnull'] == 1 && (!isset($values[$key]) || $values[$key] === 'NULL') && is_null($this->fields[$key]['default'])) { $error++; $this->errors[] = $langs->trans("ErrorFieldRequired", $this->fields[$key]['label']); @@ -8140,9 +8147,8 @@ abstract class CommonObject if (empty($error)) { // Remove extrafields - if (!$error) - { - $tmpobjectline = new $tmpforobjectlineclass($this->db); + $tmpobjectline = new $tmpforobjectlineclass($this->db); + if (!isset($tmpobjectline->isextrafieldmanaged) || !empty($tmpobjectline->isextrafieldmanaged)) { $tmpobjectline->id = $idline; $result = $tmpobjectline->deleteExtraFields(); if ($result < 0) diff --git a/htdocs/core/class/commonobjectline.class.php b/htdocs/core/class/commonobjectline.class.php index f92004120ff..148c9baa67e 100644 --- a/htdocs/core/class/commonobjectline.class.php +++ b/htdocs/core/class/commonobjectline.class.php @@ -50,6 +50,16 @@ abstract class CommonObjectLine extends CommonObject public $fk_unit; + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + $this->db = $db; + } + /** * Returns the translation key from units dictionary. * A langs->trans() must be called on result to get translated value. @@ -74,12 +84,12 @@ abstract class CommonObjectLine extends CommonObject $label_type = 'short_label'; } - $sql = 'select '.$label_type.' from '.MAIN_DB_PREFIX.'c_units where rowid='.$this->fk_unit; + $sql = 'select '.$label_type.',code from '.MAIN_DB_PREFIX.'c_units where rowid='.$this->fk_unit; $resql = $this->db->query($sql); if ($resql && $this->db->num_rows($resql) > 0) { $res = $this->db->fetch_array($resql); - $label = $res[$label_type]; + $label = ($label_type == 'short' ? $res[$label_type] : 'unit'.$res['code']); $this->db->free($resql); return $label; } else { diff --git a/htdocs/core/class/dolreceiptprinter.class.php b/htdocs/core/class/dolreceiptprinter.class.php index f54b25731d8..3234b1900f2 100644 --- a/htdocs/core/class/dolreceiptprinter.class.php +++ b/htdocs/core/class/dolreceiptprinter.class.php @@ -467,6 +467,26 @@ class dolReceiptPrinter extends Printer return $error; } + /** + * Function to delete a printer template in db + * + * @param int $templateid Template ID + * @return int 0 if OK; >0 if KO + */ + public function deleteTemplate($templateid) + { + global $conf; + $error = 0; + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'printer_receipt_template'; + $sql .= " WHERE rowid = ".((int) $this->db->escape($templateid)); + $sql .= " AND entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = $this->db->lasterror; + } + return $error; + } /** * Function to Update a printer template in db diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 3189485ff6c..b2f8905aba9 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -154,8 +154,8 @@ class ExtraFields public static $type2label = array( - 'varchar'=>'String', - 'text'=>'TextLong', + 'varchar'=>'String1Line', + 'text'=>'TextLongNLines', 'html'=>'HtmlText', 'int'=>'Int', 'double'=>'Float', @@ -807,7 +807,7 @@ class ExtraFields /** * Load array this->attributes, or old this->attribute_xxx like attribute_label, attribute_type, ... * - * @param string $elementtype Type of element ('' = all, 'adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...). + * @param string $elementtype Type of element ('' = all or $object->table_element like 'adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...). * @param boolean $forceload Force load of extra fields whatever is status of cache. * @return array Array of attributes keys+label for all extra fields. */ @@ -821,6 +821,7 @@ class ExtraFields if ($elementtype == 'thirdparty') $elementtype = 'societe'; if ($elementtype == 'contact') $elementtype = 'socpeople'; if ($elementtype == 'order_supplier') $elementtype = 'commande_fournisseur'; + if ($elementtype == 'stock_mouvement') $elementtype = 'movement'; $array_name_label = array(); @@ -2025,6 +2026,8 @@ class ExtraFields $value_key = price2num($value_arr); } elseif (in_array($key_type, array('html'))) { $value_key = GETPOST("options_".$key, 'alpha'); + } elseif (in_array($key_type, array('text'))) { + $value_key = GETPOST("options_".$key, 'alphanohtml'); } else { $value_key = GETPOST("options_".$key); if (in_array($key_type, array('link')) && $value_key == '-1') $value_key = ''; diff --git a/htdocs/core/class/fiscalyear.class.php b/htdocs/core/class/fiscalyear.class.php index 0686b68115a..c0216f16a19 100644 --- a/htdocs/core/class/fiscalyear.class.php +++ b/htdocs/core/class/fiscalyear.class.php @@ -35,6 +35,8 @@ class Fiscalyear extends CommonObject */ public $element = 'fiscalyear'; + public $picto = 'technic'; + /** * @var string Name of table without prefix where object is stored */ @@ -97,6 +99,7 @@ class Fiscalyear extends CommonObject public $statuts = array(); public $statuts_short = array(); + /** * Constructor * @@ -267,6 +270,78 @@ class Fiscalyear extends CommonObject } } + /** + * Return clicable link of object (with eventually picto) + * + * @param int $withpicto Add picto into link + * @param int $notooltip 1=Disable tooltip + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $notooltip = 0, $save_lastsearch_value = -1) + { + global $conf, $langs, $user; + + if (empty($this->ref)) $this->ref = $this->id; + + if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + + $result = ''; + + $url = DOL_URL_ROOT.'/accountancy/admin/fiscalyear_card.php?id='.$this->id; + + if (!$user->rights->accounting->fiscalyear->write) + $option = 'nolink'; + + if ($option !== 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; + if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; + } + + if ($short) return $url; + + $label = ''; + + if ($user->rights->accounting->fiscalyear->write) { + $label = ''.$langs->trans("FiscalPeriod").''; + $label .= '
'.$langs->trans('Ref').': '.$this->id; + if (isset($this->statut)) { + $label .= '
'.$langs->trans("Status").": ".$this->getLibStatut(5); + } + } + + $linkclose = ''; + if (empty($notooltip) && $user->rights->accounting->fiscalyear->write) + { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label = $langs->trans("FiscalYear"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip"'; + } + + $linkstart = ''; + $linkend = ''; + + if ($option === 'nolink') { + $linkstart = ''; + $linkend = ''; + } + + $result .= $linkstart; + if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + if ($withpicto != 2) $result .= $this->ref; + $result .= $linkend; + + return $result; + } + /** * Give a label from a status * diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 762a22cc37a..31898025c94 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2641,9 +2641,9 @@ class Form $outval .= ' - '.$langs->transnoentities("VirtualStock").':'; if ($virtualstock > 0) { - $outval .= ' - '; + $outval .= ''; } elseif ($virtualstock <= 0) { - $outval .= ' - '; + $outval .= ''; } $outval .= $virtualstock; $outval .= ''; @@ -5280,7 +5280,7 @@ class Form * @param int $d 1=Show days, month, years * @param int $addnowlink Add a link "Now", 1 with server time, 2 with local computer time * @param int $disabled Disable input fields - * @param int $fullday When a checkbox with id #fullday is cheked, hours are set with 00:00 (if value if 'fulldaystart') or 23:59 (if value is 'fulldayend') + * @param int $fullday When a checkbox with id #fullday is checked, hours are set with 00:00 (if value if 'fulldaystart') or 23:59 (if value is 'fulldayend') * @param string $addplusone Add a link "+1 hour". Value must be name of another selectDate field. * @param datetime $adddateof Add a link "Date of ..." using the following date. See also $labeladddateof for the label used. * @param string $openinghours Specify hour start and hour end for the select ex 8,20 @@ -5830,7 +5830,7 @@ class Form $urlforajaxcall = DOL_URL_ROOT.'/core/ajax/selectobject.php'; // No immediate load of all database - $urloption = 'htmlname='.$htmlname.'&outjson=1&objectdesc='.$objectdesc.'&filter='.urlencode($objecttmp->filter).($moreparams ? $moreparams : ''); + $urloption = 'htmlname='.$htmlname.'&outjson=1&objectdesc='.$objectdesc.'&filter='.urlencode($objecttmp->filter); // Activate the auto complete using ajax call. $out .= ajax_autocompleter($preselectedvalue, $htmlname, $urlforajaxcall, $urloption, $conf->global->$confkeyforautocompletemode, 0, array()); $out .= ''; @@ -6496,11 +6496,11 @@ class Form */ public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage) { - global $conf, $langs, $user; + global $conf, $langs, $user, $extrafields; if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) return ''; - $tmpvar = "MAIN_SELECTEDFIELDS_".$varpage; + $tmpvar = "MAIN_SELECTEDFIELDS_".$varpage; // To get list of saved seleteced properties if (!empty($user->conf->$tmpvar)) { $tmparray = explode(',', $user->conf->$tmpvar); @@ -6528,6 +6528,10 @@ class Form } if ($val['label']) { + if (! empty($val['langfile']) && is_object($langs)) { + $langs->load($val['langfile']); + } + $lis .= '
  • '; $listcheckedstring .= (empty($val['checked']) ? '' : $key.','); } diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 6969066629c..290bf30b0f7 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -3,6 +3,7 @@ * Copyright (C) 2008-2012 Regis Houssin * Copyright (C) 2014 Juanjo Menent * Copyright (C) 2017 Rui Strecht + * Copyright (C) 2020 Open-Dsi * * 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 @@ -172,6 +173,58 @@ class FormCompany extends Form print ''; } + /** + * Affiche formulaire de selection des niveau de prospection pour les contacts + * + * @param int $page Page + * @param int $selected Id or code preselected + * @param string $htmlname Nom du formulaire select + * @param int $empty Add empty value in list + * @return void + */ + public function formProspectContactLevel($page, $selected = '', $htmlname = 'prospect_contact_level_id', $empty = 0) + { + global $user, $langs; + + print '
    '; + print ''; + print ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + $sql = "SELECT code, label"; + $sql .= " FROM " . MAIN_DB_PREFIX . "c_prospectcontactlevel"; + $sql .= " WHERE active > 0"; + $sql .= " ORDER BY sortorder"; + $resql = $this->db->query($sql); + if ($resql) + { + $options = array(); + + if ($empty) + { + $options[''] = ''; + } + + while ($obj = $this->db->fetch_object($resql)) + { + $level = $langs->trans($obj->code); + + if ($level == $obj->code) + { + $level = $langs->trans($obj->label); + } + + $options[$obj->code] = $level; + } + + print Form::selectarray($htmlname, $options, $selected); + } + else dol_print_error($this->db); + if (!empty($htmlname) && $user->admin) print ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + print ''; + print '
    '; + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Returns the drop-down list of departments/provinces/cantons for all countries or for a given country. @@ -366,9 +419,10 @@ class FormCompany extends Form * @param string $selected Civility/Title code preselected * @param string $htmlname Name of HTML select combo field * @param string $morecss Add more css on SELECT element + * @param int $addjscombo Add js combo * @return string String with HTML select */ - public function select_civility($selected = '', $htmlname = 'civility_id', $morecss = 'maxwidth100') + public function select_civility($selected = '', $htmlname = 'civility_id', $morecss = 'maxwidth150', $addjscombo = 0) { // phpcs:enable global $conf, $langs, $user; @@ -398,7 +452,7 @@ class FormCompany extends Form } else { $out .= ''; $i++; @@ -406,6 +460,12 @@ class FormCompany extends Form } $out .= ''; if ($user->admin) $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + + if ($addjscombo) { + // Enhance with select2 + include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; + $out .= ajax_combobox($htmlname); + } } else { dol_print_error($this->db); } diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 574c8aea812..cc1ceaff70f 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -356,7 +356,7 @@ class FormFile // Add entity in $param if not already exists if (!preg_match('/entity\=[0-9]+/', $param)) { - $param .= 'entity='.(!empty($object->entity) ? $object->entity : $conf->entity); + $param .= ($param ? '&' : '').'entity='.(!empty($object->entity) ? $object->entity : $conf->entity); } $printer = 0; diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index c37a7cfc6ab..549c82a9033 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -539,7 +539,10 @@ class Translate { global $conf, $db; - if (!is_string($key)) return 'ErrorBadValueForParamNotAString'; // Avoid multiple errors with code not using function correctly. + if (!is_string($key)) { + //xdebug_print_function_stack('ErrorBadValueForParamNotAString'); + return 'ErrorBadValueForParamNotAString'; // Avoid multiple errors with code not using function correctly. + } $newstr = $key; if (preg_match('/^Civility([0-9A-Z]+)$/i', $key, $reg)) diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 9ab2e1807bd..3f33016d7e5 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -177,6 +177,8 @@ class DoliDBPgsql extends DoliDB if ($type == 'dml') { + $reg = array(); + $line = preg_replace('/\s/', ' ', $line); // Replace tabulation with space // we are inside create table statement so lets process datatypes diff --git a/htdocs/core/lib/accounting.lib.php b/htdocs/core/lib/accounting.lib.php index 317c639ad91..16b124443da 100644 --- a/htdocs/core/lib/accounting.lib.php +++ b/htdocs/core/lib/accounting.lib.php @@ -96,7 +96,7 @@ function length_accountg($account) if ($account < 0 || is_empty($account)) return ''; - if (!is_empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $account; + if (!empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $account; $g = $conf->global->ACCOUNTING_LENGTH_GACCOUNT; if (!is_empty($g)) { @@ -131,7 +131,7 @@ function length_accounta($accounta) if ($accounta < 0 || is_empty($accounta)) return ''; - if (!is_empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $accounta; + if (!empty($conf->global->ACCOUNTING_MANAGE_ZERO)) return $accounta; $a = $conf->global->ACCOUNTING_LENGTH_AACCOUNT; if (!is_empty($a)) { diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index c0e6c84ea54..f146de256da 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -25,25 +25,26 @@ /** - * Generic function that return javascript to add to a page to transform a common input field into an autocomplete field by calling an Ajax page (ex: /societe/ajaxcompanies.php). - * The HTML field must be an input text with id=search_$htmlname. - * This use the jQuery "autocomplete" function. If we want to use the select2, we must also convert the input into select on funcntions that call this method. + * Generic function that return javascript to add to a page to transform a common input field into an autocomplete field by calling an Ajax page (ex: /societe/ajaxcompanies.php). + * The HTML field must be an input text with id=search_$htmlname. + * This use the jQuery "autocomplete" function. If we want to use the select2, we must also convert the input into select on funcntions that call this method. * - * @param string $selected Preselected value - * @param string $htmlname HTML name of input field - * @param string $url Ajax Url to call for request: /path/page.php. Must return a json array ('key'=>id, 'value'=>String shown into input field once selected, 'label'=>String shown into combo list) - * @param string $urloption More parameters on URL request - * @param int $minLength Minimum number of chars to trigger that Ajax search - * @param int $autoselect Automatic selection if just one value - * @param array $ajaxoptions Multiple options array + * @param string $selected Preselected value + * @param string $htmlname HTML name of input field + * @param string $url Ajax Url to call for request: /path/page.php. Must return a json array ('key'=>id, 'value'=>String shown into input field once selected, 'label'=>String shown into combo list) + * @param string $urloption More parameters on URL request + * @param int $minLength Minimum number of chars to trigger that Ajax search + * @param int $autoselect Automatic selection if just one value + * @param array $ajaxoptions Multiple options array * - Ex: array('update'=>array('field1','field2'...)) will reset field1 and field2 once select done * - Ex: array('disabled'=> ) * - Ex: array('show'=> ) * - Ex: array('update_textarea'=> ) * - Ex: array('option_disabled'=> id to disable and warning to show if we select a disabled value (this is possible when using autocomplete ajax) - * @return string Script + * @param string $moreparams More params provided to ajax call + * @return string Script */ -function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLength = 2, $autoselect = 0, $ajaxoptions = array()) +function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLength = 2, $autoselect = 0, $ajaxoptions = array(), $moreparams = '') { if (empty($minLength)) $minLength = 1; @@ -55,7 +56,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen // Input search_htmlname is original field // Input htmlname is a second input field used when using ajax autocomplete. - $script = ''; + $script = ''; $script .= ''."\n"; $script .= ' - +
    '."\n"; print '
    '."\n"; -if ($module != 'product') { - // No public note yet on products - print '
    '."\n"; - print '
    '."\n"; - print $form->editfieldkey("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, $moreparam, '', 0); - print '
    '."\n"; - print '
    '."\n"; - print $form->editfieldval("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, '', null, null, $moreparam, 1)."\n"; - print '
    '."\n"; - print '
    '."\n"; -} +print '
    '."\n"; +print '
    '."\n"; +print $form->editfieldkey("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, $moreparam, '', 0); +print '
    '."\n"; +print '
    '."\n"; +print $form->editfieldval("NotePublic", $note_public, $value_public, $object, $permission, $typeofdata, '', null, null, $moreparam, 1)."\n"; +print '
    '."\n"; +print '
    '."\n"; if (empty($user->socid)) { // Private notes (always hidden to external users) print '
    '."\n"; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 9bb792afbc7..3b345dfa1a1 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -224,7 +224,7 @@ if ($nolinesbefore) { if (!empty($conf->global->MAIN_AUTO_OPEN_SELECT2_ON_FOCUS_FOR_CUSTOMER_PRODUCTS)) { ?> - - +
    amount = $obj->amount; $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; // Retreive all extrafield diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 12503c36869..929e7ecafd0 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -1865,7 +1865,7 @@ if ($action == 'create') print '
    '; print '
    '; - print ''; + print '
    '; // Sending method print ''; $out .= ''; foreach ($productFournLogList as $productFournLog) { - $out .= ''; + $out .= ''; $out .= ''; //$out.= ''; $out .= ''; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 0a288644d7e..7a50a189e44 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -463,11 +463,26 @@ if (empty($reshook)) if ($idprod > 0) { $label = $productsupplier->label; - + // Define output language + if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { + $outputlangs = $langs; + $newlang = ''; + if (empty($newlang) && GETPOST('lang_id', 'aZ09')) + $newlang = GETPOST('lang_id', 'aZ09'); + if (empty($newlang)) + $newlang = $object->thirdparty->default_lang; + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $desc = (!empty($productsupplier->multilangs [$outputlangs->defaultlang] ["description"])) ? $productsupplier->multilangs [$outputlangs->defaultlang] ["description"] : $productsupplier->description; + } else { + $desc = $productsupplier->description; + } // if we use supplier description of the products if (!empty($productsupplier->desc_supplier) && !empty($conf->global->PRODUIT_FOURN_TEXTS)) { $desc = $productsupplier->desc_supplier; - } else $desc = $productsupplier->description; + } if (trim($product_desc) != trim($desc)) $desc = dol_concatdesc($desc, $product_desc, '', !empty($conf->global->MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION)); @@ -2315,7 +2330,7 @@ if ($action == 'create') { if ($usercanapprove) { - if (!empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) && $conf->global->MAIN_FEATURES_LEVEL > 0 && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED && !empty($object->user_approve_id)) + if (!empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED && !empty($object->user_approve_id)) { print ''.$langs->trans("ApproveOrder").''; } else { @@ -2327,7 +2342,7 @@ if ($action == 'create') } // Second approval (if option SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED is set) - if (!empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) && $conf->global->MAIN_FEATURES_LEVEL > 0 && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) + if (!empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) && $object->total_ht >= $conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED) { if ($object->statut == CommandeFournisseur::STATUS_VALIDATED) { diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 6f665a381df..c64d158ac2c 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -743,7 +743,8 @@ if ($id > 0 || !empty($ref)) { print ''; print ''; print ''; - print ''; + print ' '; print ''; if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { @@ -971,7 +972,7 @@ if ($id > 0 || !empty($ref)) { // Discount print ''; // Save price @@ -1068,7 +1069,16 @@ if ($id > 0 || !empty($ref)) { $("select[name=fk_default_warehouse]").change(function() { var fk_default_warehouse = $("option:selected", this).val(); $("select[name^=entrepot_]").val(fk_default_warehouse).change(); - }); + }); + + jQuery("#autoreset").click(function() {'; + $i = 0; + while ($i < $nbproduct) { + print ' jQuery("#qty_0_'.$i.'").val("");'; + $i++; + } + print ' + }); }); '; diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 8ffc6be6c05..a792d68fc6b 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -120,7 +120,7 @@ $hookmanager->initHooks(array('supplierorderlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('commande_fournisseur'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 384359ae92f..7e8796e44f6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2004-2020 Laurent Destailleur * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005 Marc Barilley * Copyright (C) 2005-2013 Regis Houssin @@ -1724,6 +1724,9 @@ if ($action == 'create') $mode_reglement_id = GETPOST("mode_reglement_id"); } + $note_public = $object->getDefaultCreateValueFor('note_public', ((! empty($origin) && ! empty($originid) && is_object($objectsrc) && !empty($conf->global->FACTUREFOURN_REUSE_NOTES_ON_CREATE_FROM))?$objectsrc->note_public:null)); + $note_private = $object->getDefaultCreateValueFor('note_private', ((! empty($origin) && ! empty($originid) && is_object($objectsrc) && !empty($conf->global->FACTUREFOURN_REUSE_NOTES_ON_CREATE_FROM))?$objectsrc->note_private:null)); + print '
    '; print ''; print ''; @@ -2048,8 +2051,6 @@ if ($action == 'create') // Public note print '
    '; print ''; @@ -2059,9 +2060,6 @@ if ($action == 'create') // Private note print ''; print ''; diff --git a/htdocs/fourn/paiement/card.php b/htdocs/fourn/paiement/card.php index 8801d400afc..28020e40811 100644 --- a/htdocs/fourn/paiement/card.php +++ b/htdocs/fourn/paiement/card.php @@ -27,10 +27,10 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -require DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php'; -require DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; -require DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; -require DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; $langs->loadLangs(array('bills', 'banks', 'companies', 'suppliers')); diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 6e639370aa9..fe315f9c7b7 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -1299,7 +1299,7 @@ if ((empty($id) && empty($ref)) || $action == 'add' || $action == 'request' || $ print ''; } - // Validator + // Approver if (!$edit && $action != 'editvalidator') { print ''; print ''; print ''; diff --git a/htdocs/holiday/define_holiday.php b/htdocs/holiday/define_holiday.php index 51145fb1f42..0e83d68509d 100644 --- a/htdocs/holiday/define_holiday.php +++ b/htdocs/holiday/define_holiday.php @@ -264,7 +264,7 @@ if (count($typeleaves) == 0) print ''; // Action column - print ''; diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php index 7cc72c1792e..0cdc539bf0c 100644 --- a/htdocs/hrm/index.php +++ b/htdocs/hrm/index.php @@ -77,7 +77,7 @@ $childids[] = $user->id; llxHeader('', $langs->trans('HRMArea')); -print load_fiche_titre($langs->trans("HRMArea"), '', 'user'); +print load_fiche_titre($langs->trans("HRMArea"), '', 'hrm'); if (!empty($setupcompanynotcomplete)) diff --git a/htdocs/includes/DebugBar/Resources/debugbar.js b/htdocs/includes/DebugBar/Resources/debugbar.js index faf567e37c1..1dcbec2146f 100644 --- a/htdocs/includes/DebugBar/Resources/debugbar.js +++ b/htdocs/includes/DebugBar/Resources/debugbar.js @@ -409,12 +409,11 @@ if (typeof(PhpDebugBar) == 'undefined') { className: "phpdebugbar " + csscls('minimized'), - options: { - bodyMarginBottom: true, - bodyMarginBottomHeight: parseInt($('body').css('margin-bottom')) - }, - initialize: function() { + this.options = { + bodyMarginBottom: true, + bodyMarginBottomHeight: parseInt($('body').css('margin-bottom')), + }; this.controls = {}; this.dataMap = {}; this.datasets = {}; diff --git a/htdocs/includes/jquery/js/jquery.js b/htdocs/includes/jquery/js/jquery.js index 5b16efa11d4..f2fa5e85896 100644 --- a/htdocs/includes/jquery/js/jquery.js +++ b/htdocs/includes/jquery/js/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v3.4.1 + * jQuery JavaScript Library v3.5.1 * https://jquery.com/ * * Includes Sizzle.js @@ -9,7 +9,7 @@ * Released under the MIT license * https://jquery.org/license * - * Date: 2019-05-01T21:04Z + * Date: 2020-05-04T22:49Z */ ( function( global, factory ) { @@ -47,13 +47,16 @@ var arr = []; -var document = window.document; - var getProto = Object.getPrototypeOf; var slice = arr.slice; -var concat = arr.concat; +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + var push = arr.push; @@ -86,6 +89,8 @@ var isWindow = function isWindow( obj ) { }; +var document = window.document; + var preservedScriptAttributes = { @@ -142,7 +147,7 @@ function toType( obj ) { var - version = "3.4.1", + version = "3.5.1", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -150,11 +155,7 @@ var // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + }; jQuery.fn = jQuery.prototype = { @@ -220,6 +221,18 @@ jQuery.fn = jQuery.prototype = { return this.eq( -1 ); }, + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); @@ -353,9 +366,10 @@ jQuery.extend( { return true; }, - // Evaluates a script in a global context - globalEval: function( code, options ) { - DOMEval( code, { nonce: options && options.nonce } ); + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); }, each: function( obj, callback ) { @@ -379,13 +393,6 @@ jQuery.extend( { return obj; }, - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; @@ -472,7 +479,7 @@ jQuery.extend( { } // Flatten any nested arrays - return concat.apply( [], ret ); + return flat( ret ); }, // A global GUID counter for objects @@ -489,7 +496,7 @@ if ( typeof Symbol === "function" ) { // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { +function( _i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); @@ -511,17 +518,16 @@ function isArrayLike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v2.3.4 + * Sizzle CSS Selector Engine v2.3.5 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * - * Date: 2019-04-08 + * Date: 2020-03-14 */ -(function( window ) { - +( function( window ) { var i, support, Expr, @@ -561,59 +567,70 @@ var i, }, // Instance methods - hasOwn = ({}).hasOwnProperty, + hasOwn = ( {} ).hasOwnProperty, arr = [], pop = arr.pop, - push_native = arr.push, + pushNative = arr.push, push = arr.push, slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { - if ( list[i] === elem ) { + if ( list[ i ] === elem ) { return i; } } return -1; }, - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), rdescend = new RegExp( whitespace + "|>" ), rpseudo = new RegExp( pseudos ), @@ -625,14 +642,16 @@ var i, "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rhtml = /HTML$/i, @@ -648,18 +667,21 @@ var i, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair high < 0 ? - // BMP codepoint String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, @@ -675,7 +697,8 @@ var i, } // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped @@ -700,18 +723,20 @@ var i, // Optimize for push.apply( _, NodeList ) try { push.apply( - (arr = slice.call( preferredDoc.childNodes )), + ( arr = slice.call( preferredDoc.childNodes ) ), preferredDoc.childNodes ); + // Support: Android<4.0 // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { - push_native.apply( target, slice.call(els) ); + pushNative.apply( target, slice.call( els ) ); } : // Support: IE<9 @@ -719,8 +744,9 @@ try { function( target, els ) { var j = target.length, i = 0; + // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} + while ( ( target[ j++ ] = els[ i++ ] ) ) {} target.length = j - 1; } }; @@ -744,24 +770,21 @@ function Sizzle( selector, context, results, seed ) { // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } + setDocument( context ); context = context || document; if ( documentIsHTML ) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { // ID selector - if ( (m = match[1]) ) { + if ( ( m = match[ 1 ] ) ) { // Document context if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { + if ( ( elem = context.getElementById( m ) ) ) { // Support: IE, Opera, Webkit // TODO: identify versions @@ -780,7 +803,7 @@ function Sizzle( selector, context, results, seed ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && + if ( newContext && ( elem = newContext.getElementById( m ) ) && contains( context, elem ) && elem.id === m ) { @@ -790,12 +813,12 @@ function Sizzle( selector, context, results, seed ) { } // Type selector - } else if ( match[2] ) { + } else if ( match[ 2 ] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); @@ -806,11 +829,11 @@ function Sizzle( selector, context, results, seed ) { // Take advantage of querySelectorAll if ( support.qsa && !nonnativeSelectorCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && // Support: IE 8 only // Exclude object elements - (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) { + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { newSelector = selector; newContext = context; @@ -819,27 +842,36 @@ function Sizzle( selector, context, results, seed ) { // descendant combinators, which is not what we want. // In such cases, we work around the behavior by prefixing every selector in the // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. // Thanks to Andrew Dupont for this technique. - if ( nodeType === 1 && rdescend.test( selector ) ) { + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } } // Prefix every selector in the list groups = tokenize( selector ); i = groups.length; while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); } newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; } try { @@ -872,12 +904,14 @@ function createCache() { var keys = []; function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries delete cache[ keys.shift() ]; } - return (cache[ key + " " ] = value); + return ( cache[ key + " " ] = value ); } return cache; } @@ -896,17 +930,19 @@ function markFunction( fn ) { * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { - var el = document.createElement("fieldset"); + var el = document.createElement( "fieldset" ); try { return !!fn( el ); - } catch (e) { + } catch ( e ) { return false; } finally { + // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } + // release memory in IE el = null; } @@ -918,11 +954,11 @@ function assert( fn ) { * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { - var arr = attrs.split("|"), + var arr = attrs.split( "|" ), i = arr.length; while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; + Expr.attrHandle[ arr[ i ] ] = handler; } } @@ -944,7 +980,7 @@ function siblingCheck( a, b ) { // Check if b follows a if ( cur ) { - while ( (cur = cur.nextSibling) ) { + while ( ( cur = cur.nextSibling ) ) { if ( cur === b ) { return -1; } @@ -972,7 +1008,7 @@ function createInputPseudo( type ) { function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; + return ( name === "input" || name === "button" ) && elem.type === type; }; } @@ -1015,7 +1051,7 @@ function createDisabledPseudo( disabled ) { // Where there is no isDisabled, check manually /* jshint -W018 */ elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; + inDisabledFieldset( elem ) === disabled; } return elem.disabled === disabled; @@ -1037,21 +1073,21 @@ function createDisabledPseudo( disabled ) { * @param {Function} fn */ function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { + return markFunction( function( argument ) { argument = +argument; - return markFunction(function( seed, matches ) { + return markFunction( function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); } } - }); - }); + } ); + } ); } /** @@ -1073,7 +1109,7 @@ support = Sizzle.support = {}; */ isXML = Sizzle.isXML = function( elem ) { var namespace = elem.namespaceURI, - docElem = (elem.ownerDocument || elem).documentElement; + docElem = ( elem.ownerDocument || elem ).documentElement; // Support: IE <=8 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes @@ -1091,7 +1127,11 @@ setDocument = Sizzle.setDocument = function( node ) { doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } @@ -1100,10 +1140,14 @@ setDocument = Sizzle.setDocument = function( node ) { docElem = document.documentElement; documentIsHTML = !isXML( document ); - // Support: IE 9-11, Edge + // Support: IE 9 - 11+, Edge 12 - 18+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { // Support: IE 11, Edge if ( subWindow.addEventListener ) { @@ -1115,25 +1159,36 @@ setDocument = Sizzle.setDocument = function( node ) { } } + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) - support.attributes = assert(function( el ) { + support.attributes = assert( function( el ) { el.className = "i"; - return !el.getAttribute("className"); - }); + return !el.getAttribute( "className" ); + } ); /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( el ) { - el.appendChild( document.createComment("") ); - return !el.getElementsByTagName("*").length; - }); + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); // Support: IE<9 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); @@ -1142,38 +1197,38 @@ setDocument = Sizzle.setDocument = function( node ) { // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programmatically-set names, // so use a roundabout getElementsByName test - support.getById = assert(function( el ) { + support.getById = assert( function( el ) { docElem.appendChild( el ).id = expando; return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); + } ); // ID filter and find if ( support.getById ) { - Expr.filter["ID"] = function( id ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - return elem.getAttribute("id") === attrId; + return elem.getAttribute( "id" ) === attrId; }; }; - Expr.find["ID"] = function( id, context ) { + Expr.find[ "ID" ] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var elem = context.getElementById( id ); return elem ? [ elem ] : []; } }; } else { - Expr.filter["ID"] = function( id ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); + elem.getAttributeNode( "id" ); return node && node.value === attrId; }; }; // Support: IE 6 - 7 only // getElementById is not reliable as a find shortcut - Expr.find["ID"] = function( id, context ) { + Expr.find[ "ID" ] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var node, i, elems, elem = context.getElementById( id ); @@ -1181,7 +1236,7 @@ setDocument = Sizzle.setDocument = function( node ) { if ( elem ) { // Verify the id attribute - node = elem.getAttributeNode("id"); + node = elem.getAttributeNode( "id" ); if ( node && node.value === id ) { return [ elem ]; } @@ -1189,8 +1244,8 @@ setDocument = Sizzle.setDocument = function( node ) { // Fall back on getElementsByName elems = context.getElementsByName( id ); i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); if ( node && node.value === id ) { return [ elem ]; } @@ -1203,7 +1258,7 @@ setDocument = Sizzle.setDocument = function( node ) { } // Tag - Expr.find["TAG"] = support.getElementsByTagName ? + Expr.find[ "TAG" ] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); @@ -1218,12 +1273,13 @@ setDocument = Sizzle.setDocument = function( node ) { var elem, tmp = [], i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { - while ( (elem = results[i++]) ) { + while ( ( elem = results[ i++ ] ) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } @@ -1235,7 +1291,7 @@ setDocument = Sizzle.setDocument = function( node ) { }; // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { return context.getElementsByClassName( className ); } @@ -1256,10 +1312,14 @@ setDocument = Sizzle.setDocument = function( node ) { // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = []; - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + // Build QSA regex // Regex strategy adopted from Diego Perini - assert(function( el ) { + assert( function( el ) { + + var input; + // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, @@ -1273,78 +1333,98 @@ setDocument = Sizzle.setDocument = function( node ) { // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll("[msallowcapture^='']").length ) { + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { + if ( !el.querySelectorAll( "[selected]" ).length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); } // Support: Safari 8+, iOS 8+ // https://bugs.webkit.org/show_bug.cgi?id=136851 // In-page `selector#id sibling-combinator selector` fails if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); + rbuggyQSA.push( ".#.+[+~]" ); } - }); - assert(function( el ) { + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { el.innerHTML = "" + ""; // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); + var input = document.createElement( "input" ); input.setAttribute( "type", "hidden" ); el.appendChild( input ).setAttribute( "name", "D" ); // Support: IE8 // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll("[name=d]").length ) { + if ( el.querySelectorAll( "[name=d]" ).length ) { rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests - if ( el.querySelectorAll(":enabled").length !== 2 ) { + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Support: IE9-11+ // IE's :disabled selector does not pick up the children of disabled fieldsets docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll(":disabled").length !== 2 ) { + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } + // Support: Opera 10 - 11 only // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); } - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { - assert(function( el ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( el, "*" ); @@ -1353,11 +1433,11 @@ setDocument = Sizzle.setDocument = function( node ) { // Gecko does not error, returns false instead matches.call( el, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); - }); + } ); } - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); /* Contains ---------------------------------------------------------------------- */ @@ -1374,11 +1454,11 @@ setDocument = Sizzle.setDocument = function( node ) { adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); + ) ); } : function( a, b ) { if ( b ) { - while ( (b = b.parentNode) ) { + while ( ( b = b.parentNode ) ) { if ( b === a ) { return true; } @@ -1407,7 +1487,11 @@ setDocument = Sizzle.setDocument = function( node ) { } // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected @@ -1415,13 +1499,24 @@ setDocument = Sizzle.setDocument = function( node ) { // Disconnected nodes if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { return -1; } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { return 1; } @@ -1434,6 +1529,7 @@ setDocument = Sizzle.setDocument = function( node ) { return compare & 4 ? -1 : 1; } : function( a, b ) { + // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; @@ -1449,8 +1545,14 @@ setDocument = Sizzle.setDocument = function( node ) { // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ aup ? -1 : bup ? 1 : sortInput ? @@ -1464,26 +1566,32 @@ setDocument = Sizzle.setDocument = function( node ) { // Otherwise we need full lists of their ancestors for comparison cur = a; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { ap.unshift( cur ); } cur = b; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { + while ( ap[ i ] === bp[ i ] ) { i++; } return i ? + // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : + siblingCheck( ap[ i ], bp[ i ] ) : // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ 0; }; @@ -1495,10 +1603,7 @@ Sizzle.matches = function( expr, elements ) { }; Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } + setDocument( elem ); if ( support.matchesSelector && documentIsHTML && !nonnativeSelectorCache[ expr + " " ] && @@ -1510,12 +1615,13 @@ Sizzle.matchesSelector = function( elem, expr ) { // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { return ret; } - } catch (e) { + } catch ( e ) { nonnativeSelectorCache( expr, true ); } } @@ -1524,20 +1630,31 @@ Sizzle.matchesSelector = function( elem, expr ) { }; Sizzle.contains = function( context, elem ) { + // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { + // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : @@ -1547,13 +1664,13 @@ Sizzle.attr = function( elem, name ) { val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? + ( val = elem.getAttributeNode( name ) ) && val.specified ? val.value : null; }; Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); + return ( sel + "" ).replace( rcssescape, fcssescape ); }; Sizzle.error = function( msg ) { @@ -1576,7 +1693,7 @@ Sizzle.uniqueSort = function( results ) { results.sort( sortOrder ); if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { + while ( ( elem = results[ i++ ] ) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } @@ -1604,17 +1721,21 @@ getText = Sizzle.getText = function( elem ) { nodeType = elem.nodeType; if ( !nodeType ) { + // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { + while ( ( node = elem[ i++ ] ) ) { + // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { + // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); @@ -1623,6 +1744,7 @@ getText = Sizzle.getText = function( elem ) { } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } + // Do not include comment or processing instruction nodes return ret; @@ -1650,19 +1772,21 @@ Expr = Sizzle.selectors = { preFilter: { "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) @@ -1673,22 +1797,25 @@ Expr = Sizzle.selectors = { 7 sign of y-component 8 y of y-component */ - match[1] = match[1].toLowerCase(); + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); } return match; @@ -1696,26 +1823,28 @@ Expr = Sizzle.selectors = { "PSEUDO": function( match ) { var excess, - unquoted = !match[6] && match[2]; + unquoted = !match[ 6 ] && match[ 2 ]; - if ( matchExpr["CHILD"].test( match[0] ) ) { + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { return null; } // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && + ( excess = tokenize( unquoted, true ) ) && + // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) @@ -1728,7 +1857,9 @@ Expr = Sizzle.selectors = { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? - function() { return true; } : + function() { + return true; + } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; @@ -1738,10 +1869,16 @@ Expr = Sizzle.selectors = { var pattern = classCache[ className + " " ]; return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); }, "ATTR": function( name, operator, check ) { @@ -1757,6 +1894,8 @@ Expr = Sizzle.selectors = { result += ""; + /* eslint-disable max-len */ + return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : @@ -1765,10 +1904,12 @@ Expr = Sizzle.selectors = { operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; + /* eslint-enable max-len */ + }; }, - "CHILD": function( type, what, argument, first, last ) { + "CHILD": function( type, what, _argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; @@ -1780,7 +1921,7 @@ Expr = Sizzle.selectors = { return !!elem.parentNode; } : - function( elem, context, xml ) { + function( elem, _context, xml ) { var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, @@ -1794,7 +1935,7 @@ Expr = Sizzle.selectors = { if ( simple ) { while ( dir ) { node = elem; - while ( (node = node[ dir ]) ) { + while ( ( node = node[ dir ] ) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { @@ -1802,6 +1943,7 @@ Expr = Sizzle.selectors = { return false; } } + // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } @@ -1817,22 +1959,22 @@ Expr = Sizzle.selectors = { // ...in a gzip-friendly way node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; - while ( (node = ++nodeIndex && node && node[ dir ] || + while ( ( node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { + ( diff = nodeIndex = 0 ) || start.pop() ) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { @@ -1842,16 +1984,18 @@ Expr = Sizzle.selectors = { } } else { + // Use previously-cached element index if available if ( useCache ) { + // ...in a gzip-friendly way node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; @@ -1861,9 +2005,10 @@ Expr = Sizzle.selectors = { // xml :nth-child(...) // or :nth-last-child(...) or :nth(-last)?-of-type(...) if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : @@ -1872,12 +2017,13 @@ Expr = Sizzle.selectors = { // Cache the index of each encountered element if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || + ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); uniqueCache[ type ] = [ dirruns, diff ]; } @@ -1898,6 +2044,7 @@ Expr = Sizzle.selectors = { }, "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters @@ -1917,15 +2064,15 @@ Expr = Sizzle.selectors = { if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { + markFunction( function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); } - }) : + } ) : function( elem ) { return fn( elem, 0, args ); }; @@ -1936,8 +2083,10 @@ Expr = Sizzle.selectors = { }, pseudos: { + // Potentially complex pseudos - "not": markFunction(function( selector ) { + "not": markFunction( function( selector ) { + // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators @@ -1946,39 +2095,40 @@ Expr = Sizzle.selectors = { matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { + markFunction( function( seed, matches, _context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); } } - }) : - function( elem, context, xml ) { - input[0] = elem; + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; matcher( input, null, xml, results ); + // Don't keep the element (issue #299) - input[0] = null; + input[ 0 ] = null; return !results.pop(); }; - }), + } ), - "has": markFunction(function( selector ) { + "has": markFunction( function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; - }), + } ), - "contains": markFunction(function( text ) { + "contains": markFunction( function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; }; - }), + } ), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value @@ -1988,25 +2138,26 @@ Expr = Sizzle.selectors = { // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { + // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { + if ( !ridentifier.test( lang || "" ) ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { - if ( (elemLang = documentIsHTML ? + if ( ( elemLang = documentIsHTML ? elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); return false; }; - }), + } ), // Miscellaneous "target": function( elem ) { @@ -2019,7 +2170,9 @@ Expr = Sizzle.selectors = { }, "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); }, // Boolean properties @@ -2027,16 +2180,20 @@ Expr = Sizzle.selectors = { "disabled": createDisabledPseudo( true ), "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); }, "selected": function( elem ) { + // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions elem.parentNode.selectedIndex; } @@ -2045,6 +2202,7 @@ Expr = Sizzle.selectors = { // Contents "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) @@ -2058,7 +2216,7 @@ Expr = Sizzle.selectors = { }, "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); + return !Expr.pseudos[ "empty" ]( elem ); }, // Element/input types @@ -2082,39 +2240,40 @@ Expr = Sizzle.selectors = { // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); }, // Position-in-collection - "first": createPositionalPseudo(function() { + "first": createPositionalPseudo( function() { return [ 0 ]; - }), + } ), - "last": createPositionalPseudo(function( matchIndexes, length ) { + "last": createPositionalPseudo( function( _matchIndexes, length ) { return [ length - 1 ]; - }), + } ), - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; - }), + } ), - "even": createPositionalPseudo(function( matchIndexes, length ) { + "even": createPositionalPseudo( function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "odd": createPositionalPseudo(function( matchIndexes, length ) { + "odd": createPositionalPseudo( function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument > length ? @@ -2124,19 +2283,19 @@ Expr = Sizzle.selectors = { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; - }) + } ) } }; -Expr.pseudos["nth"] = Expr.pseudos["eq"]; +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { @@ -2167,37 +2326,39 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { while ( soFar ) { // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { if ( match ) { + // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; + soFar = soFar.slice( match[ 0 ].length ) || soFar; } - groups.push( (tokens = []) ); + groups.push( ( tokens = [] ) ); } matched = false; // Combinators - if ( (match = rcombinators.exec( soFar )) ) { + if ( ( match = rcombinators.exec( soFar ) ) ) { matched = match.shift(); - tokens.push({ + tokens.push( { value: matched, + // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); + type: match[ 0 ].replace( rtrim, " " ) + } ); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { matched = match.shift(); - tokens.push({ + tokens.push( { value: matched, type: type, matches: match - }); + } ); soFar = soFar.slice( matched.length ); } } @@ -2214,6 +2375,7 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { soFar.length : soFar ? Sizzle.error( selector ) : + // Cache the tokens tokenCache( selector, groups ).slice( 0 ); }; @@ -2223,7 +2385,7 @@ function toSelector( tokens ) { len = tokens.length, selector = ""; for ( ; i < len; i++ ) { - selector += tokens[i].value; + selector += tokens[ i ].value; } return selector; } @@ -2236,9 +2398,10 @@ function addCombinator( matcher, combinator, base ) { doneName = done++; return combinator.first ? + // Check against closest ancestor/preceding element function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } @@ -2253,7 +2416,7 @@ function addCombinator( matcher, combinator, base ) { // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if ( xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; @@ -2261,27 +2424,29 @@ function addCombinator( matcher, combinator, base ) { } } } else { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); if ( skip && skip === elem.nodeName.toLowerCase() ) { elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && + } else if ( ( oldCache = uniqueCache[ key ] ) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); + return ( newCache[ 2 ] = oldCache[ 2 ] ); } else { + // Reuse newcache so results back-propagate to previous elements uniqueCache[ key ] = newCache; // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { return true; } } @@ -2297,20 +2462,20 @@ function elementMatcher( matchers ) { function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { + if ( !matchers[ i ]( elem, context, xml ) ) { return false; } } return true; } : - matchers[0]; + matchers[ 0 ]; } function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); + Sizzle( selector, contexts[ i ], results ); } return results; } @@ -2323,7 +2488,7 @@ function condense( unmatched, map, filter, context, xml ) { mapped = map != null; for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { + if ( ( elem = unmatched[ i ] ) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { @@ -2343,14 +2508,18 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } - return markFunction(function( seed, results, context, xml ) { + return markFunction( function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? @@ -2358,6 +2527,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS elems, matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? @@ -2381,8 +2551,8 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); } } } @@ -2390,25 +2560,27 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { - if ( (elem = matcherOut[i]) ) { + if ( ( elem = matcherOut[ i ] ) ) { + // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); + temp.push( ( matcherIn[ i ] = elem ) ); } } - postFinder( null, (matcherOut = []), temp, xml ); + postFinder( null, ( matcherOut = [] ), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - seed[temp] = !(results[temp] = elem); + seed[ temp ] = !( results[ temp ] = elem ); } } } @@ -2426,14 +2598,14 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS push.apply( results, matcherOut ); } } - }); + } ); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) @@ -2445,38 +2617,43 @@ function matcherFromTokens( tokens ) { }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? + ( checkContext = context ).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) checkContext = null; return ret; } ]; for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { + if ( Expr.relative[ tokens[ j ].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), j < len && toSelector( tokens ) ); } @@ -2497,28 +2674,40 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { unmatched = seed && [], setMatched = [], contextBackup = outermostContext, + // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), len = elems.length; if ( outermost ) { - outermostContext = context === document || context || outermost; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; } // Add elements passing elementMatchers directly to results // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { if ( byElement && elem ) { j = 0; - if ( !context && elem.ownerDocument !== document ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { setDocument( elem ); xml = !documentIsHTML; } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { results.push( elem ); break; } @@ -2530,8 +2719,9 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { // Track unmatched elements for set filters if ( bySet ) { + // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { + if ( ( elem = !matcher && elem ) ) { matchedCount--; } @@ -2555,16 +2745,17 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { // numerically zero. if ( bySet && i !== matchedCount ) { j = 0; - while ( (matcher = setMatchers[j++]) ) { + while ( ( matcher = setMatchers[ j++ ] ) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); } } } @@ -2605,13 +2796,14 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { cached = compilerCache[ selector + " " ]; if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element if ( !match ) { match = tokenize( selector ); } i = match.length; while ( i-- ) { - cached = matcherFromTokens( match[i] ); + cached = matcherFromTokens( match[ i ] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { @@ -2620,7 +2812,10 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { } // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); // Save selector and tokenization cached.selector = selector; @@ -2640,7 +2835,7 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { select = Sizzle.select = function( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); results = results || []; @@ -2649,11 +2844,12 @@ select = Sizzle.select = function( selector, context, results, seed ) { if ( match.length === 1 ) { // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; if ( !context ) { return results; @@ -2666,20 +2862,22 @@ select = Sizzle.select = function( selector, context, results, seed ) { } // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; while ( i-- ) { - token = tokens[i]; + token = tokens[ i ]; // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { + if ( Expr.relative[ ( type = token.type ) ] ) { break; } - if ( (find = Expr.find[ type ]) ) { + if ( ( find = Expr.find[ type ] ) ) { + // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); @@ -2710,7 +2908,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { // One-time assignments // Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function @@ -2721,58 +2919,59 @@ setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { +support.sortDetached = assert( function( el ) { + // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; -}); + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); // Support: IE<8 // Prevent attribute/property "interpolation" // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { +if ( !assert( function( el ) { el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { addHandle( "type|href|height|width", function( elem, name, isXML ) { if ( !isXML ) { return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); } - }); + } ); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { +if ( !support.attributes || !assert( function( el ) { el.innerHTML = ""; el.firstChild.setAttribute( "value", "" ); return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { return elem.defaultValue; } - }); + } ); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { addHandle( booleans, function( elem, name, isXML ) { var val; if ( !isXML ) { return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? + ( val = elem.getAttributeNode( name ) ) && val.specified ? val.value : - null; + null; } - }); + } ); } return Sizzle; -})( window ); +} )( window ); @@ -3141,7 +3340,7 @@ jQuery.each( { parents: function( elem ) { return dir( elem, "parentNode" ); }, - parentsUntil: function( elem, i, until ) { + parentsUntil: function( elem, _i, until ) { return dir( elem, "parentNode", until ); }, next: function( elem ) { @@ -3156,10 +3355,10 @@ jQuery.each( { prevAll: function( elem ) { return dir( elem, "previousSibling" ); }, - nextUntil: function( elem, i, until ) { + nextUntil: function( elem, _i, until ) { return dir( elem, "nextSibling", until ); }, - prevUntil: function( elem, i, until ) { + prevUntil: function( elem, _i, until ) { return dir( elem, "previousSibling", until ); }, siblings: function( elem ) { @@ -3169,7 +3368,13 @@ jQuery.each( { return siblings( elem.firstChild ); }, contents: function( elem ) { - if ( typeof elem.contentDocument !== "undefined" ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + return elem.contentDocument; } @@ -3512,7 +3717,7 @@ jQuery.extend( { var fns = arguments; return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { + jQuery.each( tuples, function( _i, tuple ) { // Map tuples (progress, done, fail) to arguments (done, fail, progress) var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; @@ -3965,7 +4170,7 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { // ...except when executing function values } else { bulk = fn; - fn = function( elem, key, value ) { + fn = function( elem, _key, value ) { return bulk.call( jQuery( elem ), value ); }; } @@ -4000,7 +4205,7 @@ var rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace() -function fcamelCase( all, letter ) { +function fcamelCase( _all, letter ) { return letter.toUpperCase(); } @@ -4528,27 +4733,6 @@ var isHiddenWithinTree = function( elem, el ) { jQuery.css( elem, "display" ) === "none"; }; -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - function adjustCSS( elem, prop, valueParts, tween ) { @@ -4719,11 +4903,40 @@ var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); -// We have to close these tags to support XHTML (#13200) -var wrapMap = { +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; // Support: IE <=9 only - option: [ 1, "" ], + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { // XHTML parsers do not magically insert elements in the // same way that tag soup parsers do. So we cannot shorten @@ -4736,12 +4949,14 @@ var wrapMap = { _default: [ 0, "", "" ] }; -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + function getAll( context, tag ) { @@ -4874,32 +5089,6 @@ function buildFragment( elems, context, scripts, selection, ignored ) { } -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); - - var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, @@ -5008,8 +5197,8 @@ jQuery.event = { special, handlers, type, namespaces, origType, elemData = dataPriv.get( elem ); - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { return; } @@ -5033,7 +5222,7 @@ jQuery.event = { // Init the element's event structure and main handler, if this is the first if ( !( events = elemData.events ) ) { - events = elemData.events = {}; + events = elemData.events = Object.create( null ); } if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { @@ -5191,12 +5380,15 @@ jQuery.event = { dispatch: function( nativeEvent ) { - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); - var i, j, ret, matched, handleObj, handlerQueue, args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event @@ -5771,13 +5963,6 @@ jQuery.fn.extend( { var - /* eslint-disable max-len */ - - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - - /* eslint-enable */ - // Support: IE <=10 - 11, Edge 12 - 13 only // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ @@ -5814,7 +5999,7 @@ function restoreScript( elem ) { } function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + var i, l, type, pdataOld, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; @@ -5822,13 +6007,11 @@ function cloneCopyEvent( src, dest ) { // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); + pdataOld = dataPriv.get( src ); events = pdataOld.events; if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; + dataPriv.remove( dest, "handle events" ); for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { @@ -5864,7 +6047,7 @@ function fixInput( src, dest ) { function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays - args = concat.apply( [], args ); + args = flat( args ); var fragment, first, scripts, hasScripts, node, doc, i = 0, @@ -5939,7 +6122,7 @@ function domManip( collection, args, callback, ignored ) { if ( jQuery._evalUrl && !node.noModule ) { jQuery._evalUrl( node.src, { nonce: node.nonce || node.getAttribute( "nonce" ) - } ); + }, doc ); } } else { DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); @@ -5976,7 +6159,7 @@ function remove( elem, selector, keepData ) { jQuery.extend( { htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); + return html; }, clone: function( elem, dataAndEvents, deepDataAndEvents ) { @@ -6238,6 +6421,27 @@ var getStyles = function( elem ) { return view.getComputedStyle( elem ); }; +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); @@ -6295,7 +6499,7 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); } var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, + reliableTrDimensionsVal, reliableMarginLeftVal, container = document.createElement( "div" ), div = document.createElement( "div" ); @@ -6330,6 +6534,35 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); scrollboxSize: function() { computeStyleTests(); return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; } } ); } )(); @@ -6454,7 +6687,7 @@ var fontWeight: "400" }; -function setPositiveNumber( elem, value, subtract ) { +function setPositiveNumber( _elem, value, subtract ) { // Any relative (+/-) values have already been // normalized at this point @@ -6559,17 +6792,26 @@ function getWidthOrHeight( elem, dimension, extra ) { } - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - // Support: IE 9-11 only - // Also use offsetWidth/offsetHeight for when box sizing is unreliable - // We use getClientRects() to check for hidden/disconnected. - // In those cases, the computed value can be trusted to be border-box + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected elem.getClientRects().length ) { isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; @@ -6764,7 +7006,7 @@ jQuery.extend( { } } ); -jQuery.each( [ "height", "width" ], function( i, dimension ) { +jQuery.each( [ "height", "width" ], function( _i, dimension ) { jQuery.cssHooks[ dimension ] = { get: function( elem, computed, extra ) { if ( computed ) { @@ -7537,7 +7779,7 @@ jQuery.fn.extend( { clearQueue = type; type = undefined; } - if ( clearQueue && type !== false ) { + if ( clearQueue ) { this.queue( type || "fx", [] ); } @@ -7620,7 +7862,7 @@ jQuery.fn.extend( { } } ); -jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { return speed == null || typeof speed === "boolean" ? @@ -7841,7 +8083,7 @@ boolHook = { } }; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { var getter = attrHandle[ name ] || jQuery.find.attr; attrHandle[ name ] = function( elem, name, isXML ) { @@ -8465,7 +8707,9 @@ jQuery.extend( jQuery.event, { special.bindType || type; // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); @@ -8576,7 +8820,10 @@ if ( !support.focusin ) { jQuery.event.special[ fix ] = { setup: function() { - var doc = this.ownerDocument || this, + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access( doc, fix ); if ( !attaches ) { @@ -8585,7 +8832,7 @@ if ( !support.focusin ) { dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); }, teardown: function() { - var doc = this.ownerDocument || this, + var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access( doc, fix ) - 1; if ( !attaches ) { @@ -8601,7 +8848,7 @@ if ( !support.focusin ) { } var location = window.location; -var nonce = Date.now(); +var nonce = { guid: Date.now() }; var rquery = ( /\?/ ); @@ -8733,7 +8980,7 @@ jQuery.fn.extend( { rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); } ) - .map( function( i, elem ) { + .map( function( _i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { @@ -9346,7 +9593,8 @@ jQuery.extend( { // Add or update anti-cache param if needed if ( s.cache === false ) { cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; } // Put hash and anti-cache on the URL that will be requested (gh-1732) @@ -9479,6 +9727,11 @@ jQuery.extend( { response = ajaxHandleResponses( s, jqXHR, responses ); } + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); @@ -9569,7 +9822,7 @@ jQuery.extend( { } } ); -jQuery.each( [ "get", "post" ], function( i, method ) { +jQuery.each( [ "get", "post" ], function( _i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // Shift arguments if data argument was omitted @@ -9590,8 +9843,17 @@ jQuery.each( [ "get", "post" ], function( i, method ) { }; } ); +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); -jQuery._evalUrl = function( url, options ) { + +jQuery._evalUrl = function( url, options, doc ) { return jQuery.ajax( { url: url, @@ -9609,7 +9871,7 @@ jQuery._evalUrl = function( url, options ) { "text script": function() {} }, dataFilter: function( response ) { - jQuery.globalEval( response, options ); + jQuery.globalEval( response, options, doc ); } } ); }; @@ -9931,7 +10193,7 @@ var oldCallbacks = [], jQuery.ajaxSetup( { jsonp: "callback", jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) ); this[ callback ] = true; return callback; } @@ -10148,23 +10410,6 @@ jQuery.fn.load = function( url, params, callback ) { -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ - "ajaxStart", - "ajaxStop", - "ajaxComplete", - "ajaxError", - "ajaxSuccess", - "ajaxSend" -], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -} ); - - - - jQuery.expr.pseudos.animated = function( elem ) { return jQuery.grep( jQuery.timers, function( fn ) { return elem === fn.elem; @@ -10221,6 +10466,12 @@ jQuery.offset = { options.using.call( elem, props ); } else { + if ( typeof props.top === "number" ) { + props.top += "px"; + } + if ( typeof props.left === "number" ) { + props.left += "px"; + } curElem.css( props ); } } @@ -10371,7 +10622,7 @@ jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 // getComputedStyle returns percent when specified for top/left/bottom/right; // rather than make the css module depend on the offset module, just check for it here -jQuery.each( [ "top", "left" ], function( i, prop ) { +jQuery.each( [ "top", "left" ], function( _i, prop ) { jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, function( elem, computed ) { if ( computed ) { @@ -10434,25 +10685,19 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { } ); -jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup contextmenu" ).split( " " ), - function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); +jQuery.each( [ + "ajaxStart", + "ajaxStop", + "ajaxComplete", + "ajaxError", + "ajaxSuccess", + "ajaxSend" +], function( _i, type ) { + jQuery.fn[ type ] = function( fn ) { + return this.on( type, fn ); }; } ); -jQuery.fn.extend( { - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -} ); - @@ -10474,9 +10719,33 @@ jQuery.fn.extend( { return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } } ); +jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup contextmenu" ).split( " " ), + function( _i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + } ); + + + + +// Support: Android <=4.0 only +// Make sure we trim BOM and NBSP +var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + // Bind a function to a context, optionally partially applying any // arguments. // jQuery.proxy is deprecated to promote standards (specifically Function#bind) @@ -10539,6 +10808,11 @@ jQuery.isNumeric = function( obj ) { !isNaN( obj - parseFloat( obj ) ); }; +jQuery.trim = function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); +}; @@ -10587,7 +10861,7 @@ jQuery.noConflict = function( deep ) { // Expose jQuery and $ identifiers, even in AMD // (#7102#comment:10, https://github.com/jquery/jquery/pull/557) // and CommonJS for browser emulators (#13566) -if ( !noGlobal ) { +if ( typeof noGlobal === "undefined" ) { window.jQuery = window.$ = jQuery; } diff --git a/htdocs/includes/jquery/js/jquery.min.js b/htdocs/includes/jquery/js/jquery.min.js index 07c00cd227d..d467083b62c 100644 --- a/htdocs/includes/jquery/js/jquery.min.js +++ b/htdocs/includes/jquery/js/jquery.min.js @@ -1,2 +1,2 @@ -/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"
    '; diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 6b08d4db5e6..46d964756ff 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -288,6 +288,7 @@ class Expedition extends CommonObject $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."expedition ("; + $sql .= "ref"; $sql .= ", entity"; $sql .= ", ref_customer"; @@ -327,10 +328,10 @@ class Expedition extends CommonObject $sql .= ", ".($this->fk_delivery_address > 0 ? $this->fk_delivery_address : "null"); $sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : "null"); $sql .= ", '".$this->db->escape($this->tracking_number)."'"; - $sql .= ", ".$this->weight; - $sql .= ", ".$this->sizeS; // TODO Should use this->trueDepth - $sql .= ", ".$this->sizeW; // TODO Should use this->trueWidth - $sql .= ", ".$this->sizeH; // TODO Should use this->trueHeight + $sql.= ", ".(is_numeric($this->weight)?$this->weight:'NULL'); + $sql.= ", ".(is_numeric($this->sizeS)?$this->sizeS:'NULL'); // TODO Should use this->trueDepth + $sql.= ", ".(is_numeric($this->sizeW)?$this->sizeW:'NULL'); // TODO Should use this->trueWidth + $sql.= ", ".(is_numeric($this->sizeH)?$this->sizeH:'NULL'); // TODO Should use this->trueHeight $sql .= ", ".($this->weight_units != '' ? (int) $this->weight_units : 'NULL'); $sql .= ", ".($this->size_units != '' ? (int) $this->size_units : 'NULL'); $sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null"); @@ -569,6 +570,7 @@ class Expedition extends CommonObject $this->date_shipping = $this->db->jdate($obj->date_expedition); // Date real $this->date_delivery = $this->db->jdate($obj->date_delivery); // Date planed $this->fk_delivery_address = $obj->fk_address; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->shipping_method_id = $obj->fk_shipping_method; $this->shipping_method = $obj->shipping_method; @@ -2462,6 +2464,7 @@ class Expedition extends CommonObject global $conf, $langs; $langs->load("sendings"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'rouget'; diff --git a/htdocs/expedition/list.php b/htdocs/expedition/list.php index 74efaaeb27a..b28bc7d062c 100644 --- a/htdocs/expedition/list.php +++ b/htdocs/expedition/list.php @@ -800,7 +800,7 @@ if ($resql) } $db->free($resql); - $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); + $parameters = array('arrayfields'=>$arrayfields, 'totalarray' => $totalarray, 'sql'=>$sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index 6b165c1042e..a21ed4d6612 100644 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -109,7 +109,7 @@ $hookmanager->initHooks(array('expensereportlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('expensereport'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index ed01164b3df..a4fa1fff132 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -2,7 +2,7 @@ /* Copyright (C) 2002-2007 Rodolphe Quiedeville * Copyright (C) 2004-2016 Laurent Destailleur * Copyright (C) 2005-2018 Regis Houssin - * Copyright (C) 2011-2017 Juanjo Menent + * Copyright (C) 2011-2020 Juanjo Menent * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2018 Ferran Marcet * Copyright (C) 2014-2018 Charlene Benke @@ -573,7 +573,7 @@ if (empty($reshook)) } $object->fetch_thirdparty(); - $desc = GETPOST('np_desc'); + $desc = GETPOST('np_desc','alpha'); $date_inter = dol_mktime(GETPOST('dihour', 'int'), GETPOST('dimin', 'int'), 0, GETPOST('dimonth', 'int'), GETPOST('diday', 'int'), GETPOST('diyear', 'int')); $duration = convertTime2Seconds(GETPOST('durationhour', 'int'), GETPOST('durationmin', 'int')); diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 754fc8dd507..c6c5fd587e6 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -448,7 +448,8 @@ class Fichinter extends CommonObject $this->fk_project = $obj->fk_project; $this->note_public = $obj->note_public; $this->note_private = $obj->note_private; - $this->modelpdf = $obj->model_pdf; + $this->model_pdf = $obj->model_pdf; + $this->modelpdf = $obj->model_pdf; $this->fk_contrat = $obj->fk_contrat; $this->user_creation = $obj->fk_user_author; diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php index 679d231d6a8..183f3609c40 100644 --- a/htdocs/fichinter/class/fichinterrec.class.php +++ b/htdocs/fichinter/class/fichinterrec.class.php @@ -197,8 +197,6 @@ class FichinterRec extends Fichinter */ $num = count($fichintsrc->lines); for ($i = 0; $i < $num; $i++) { - //$result=$fichintlignesrc->fetch($fichintsrc->lines[$i]->id); - //var_dump($fichintsrc->lines[$i]); $result_insert = $this->addline( $fichintsrc->lines[$i]->desc, @@ -243,7 +241,7 @@ class FichinterRec extends Fichinter /** - * Recupere l'objet facture et ses lignes de factures + * Get the template of intervention object and lines * * @param int $rowid Id of object to load * @param string $ref Reference of fichinter @@ -282,6 +280,7 @@ class FichinterRec extends Fichinter $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; $this->user_author = $obj->fk_user_author; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->rang = $obj->rang; $this->special_code = $obj->special_code; @@ -295,9 +294,7 @@ class FichinterRec extends Fichinter $this->brouillon = 1; - /* - * Lines - */ + // Lines $result = $this->fetch_lines(); if ($result < 0) { $this->error = $this->db->error(); @@ -318,9 +315,9 @@ class FichinterRec extends Fichinter // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Recupere les lignes de factures predefinies dans this->lines - * @param int $sall sall + * Load all lines of template of intervention into this->lines * + * @param int $sall sall * @return int 1 if OK, < 0 if KO */ public function fetch_lines($sall = 0) @@ -441,15 +438,15 @@ class FichinterRec extends Fichinter * @param integer $duration Durée * @param string $datei Date * @param int $rang Position of line - * @param double $pu_ht Prix unitaire HT (> 0 even for credit note) - * @param double $qty Quantite - * @param double $txtva Taux de tva force, sinon -1 - * @param int $fk_product Id du produit/service predefini - * @param double $remise_percent Pourcentage de remise de la ligne + * @param double $pu_ht Unit price without tax (> 0 even for credit note) + * @param double $qty Quantity + * @param double $txtva Forced VAT rate, otherwise -1 + * @param int $fk_product Id of predefined product/service + * @param double $remise_percent Percentage of discount on line * @param string $price_base_type HT or TTC - * @param int $info_bits Bits de type de lignes - * @param int $fk_remise_except Id remise - * @param double $pu_ttc Prix unitaire TTC (> 0 even for credit note) + * @param int $info_bits Bits for type of lines + * @param int $fk_remise_except Id discount + * @param double $pu_ttc Unit price with tax (> 0 even for credit note) * @param int $type Type of line (0=product, 1=service) * @param int $special_code Special code * @param string $label Label of the line diff --git a/htdocs/fichinter/list.php b/htdocs/fichinter/list.php index 993dd0f3fa4..0204689b9b0 100644 --- a/htdocs/fichinter/list.php +++ b/htdocs/fichinter/list.php @@ -85,7 +85,7 @@ $hookmanager->initHooks(array('interventionlist')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -$extrafields->fetch_name_optionals_label('fichinter'); +$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 5ec2b6f49a6..501f0c48977 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -293,9 +293,9 @@ class SupplierInvoices extends DolibarrApi } /** - * Validate an order + * Validate an invoice * - * @param int $id Order ID + * @param int $id Invoice ID * @param int $idwarehouse Warehouse ID * @param int $notrigger 1=Does not execute triggers, 0= execute triggers * @@ -325,7 +325,7 @@ class SupplierInvoices extends DolibarrApi $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger); if ($result == 0) { - throw new RestException(304, 'Error nothing done. May be object is already validated'); + throw new RestException(304, 'Error nothing done. The invoice is already validated'); } if ($result < 0) { throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error); @@ -454,6 +454,7 @@ class SupplierInvoices extends DolibarrApi $paiement->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching $paiement->paiementid = $paiementid; $paiement->paiementcode = dol_getIdFromCode($this->db, $paiementid, 'c_paiement', 'id', 'code', 1); + $paiement->oper = $paiement->paiementcode; // For backward compatibility $paiement->num_payment = $num_payment; $paiement->note_public = $comment; diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index bee6346386b..b180016bdd9 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -187,6 +187,8 @@ class SupplierOrders extends DolibarrApi /** * Create supplier order object * + * Example: {"ref": "auto", "ref_supplier": "1234", "socid": "1", "multicurrency_code": "SEK", "multicurrency_tx": 1, "tva_tx": 25, "note": "Imported via the REST API"} + * * @param array $request_data Request datas * @return int ID of supplier order */ diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index c7cb8025d62..4657b49899d 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -332,9 +332,11 @@ class CommandeFournisseur extends CommonOrder $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as p ON c.fk_mode_reglement = p.id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_input_method as cm ON cm.rowid = c.fk_input_method"; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON c.fk_incoterms = i.rowid'; - $sql .= " WHERE c.entity IN (".getEntity('supplier_order').")"; + + if (empty($id)) $sql .= " WHERE c.entity IN (".getEntity('supplier_order').")"; + else $sql .= " WHERE c.rowid=".$id; + if ($ref) $sql .= " AND c.ref='".$this->db->escape($ref)."'"; - else $sql .= " AND c.rowid=".$id; dol_syslog(get_class($this)."::fetch", LOG_DEBUG); $resql = $this->db->query($sql); @@ -390,6 +392,7 @@ class CommandeFournisseur extends CommonOrder $this->note = $obj->note_private; // deprecated $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; //Incoterms @@ -1244,11 +1247,15 @@ class CommandeFournisseur extends CommonOrder $error = 0; $now = dol_now(); + // $date_commande is deprecated + $date = ($this->date_commande ? $this->date_commande : $this->date); // in case of date is set + if (empty($date)) $date = $now; + // Clean parameters if (empty($this->source)) $this->source = 0; // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) - if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code); + if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $date); else $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); if (empty($this->fk_multicurrency)) { @@ -2960,6 +2967,7 @@ class CommandeFournisseur extends CommonOrder global $conf, $langs; $langs->load("suppliers"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'muscadet'; diff --git a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php index 518c6885411..d85a4e0941a 100644 --- a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php +++ b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php @@ -290,7 +290,9 @@ class CommandeFournisseurDispatch extends CommonObject $this->batch = $obj->batch; $this->eatby = $this->db->jdate($obj->eatby); $this->sellby = $this->db->jdate($obj->sellby); - $this->fetch_optionals(); + $this->fk_reception = $obj->fk_reception; + + $this->fetch_optionals(); } $this->db->free($resql); diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 9949c4d3253..ab5fe1a3e5b 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -359,7 +359,7 @@ class FactureFournisseur extends CommonInvoice $remise = $this->remise; // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) - if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code); + if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date); else $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); if (empty($this->fk_multicurrency)) { @@ -485,7 +485,7 @@ class FactureFournisseur extends CommonInvoice $idligne, $this->lines[$i]->description, $this->lines[$i]->pu_ht, - $this->lines[$i]->tva_tx, + $this->lines[$i]->tva_tx.($this->lines[$i]->vat_src_code ? ' ('.$this->lines[$i]->vat_src_code.')' : ''), $this->lines[$i]->localtax1_tx, $this->lines[$i]->localtax2_tx, $this->lines[$i]->qty, @@ -710,7 +710,7 @@ class FactureFournisseur extends CommonInvoice $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; $this->model_pdf = $obj->model_pdf; - $this->modelpdf = $obj->model_pdf; + $this->modelpdf = $obj->model_pdf; $this->import_key = $obj->import_key; //Incoterms @@ -1259,7 +1259,7 @@ class FactureFournisseur extends CommonInvoice $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture_fourn'; - $sql .= ' SET paye = 1, fk_statut=2'; + $sql .= ' SET paye = 1, fk_statut = '.self::STATUS_CLOSED; $sql .= ' WHERE rowid = '.$this->id; dol_syslog("FactureFournisseur::set_paid", LOG_DEBUG); @@ -1885,6 +1885,8 @@ class FactureFournisseur extends CommonInvoice $localtaxes_type = getLocalTaxesFromRate($vatrate, 0, $mysoc, $this->thirdparty); + $reg = array(); + // Clean vat code $vat_src_code = ''; if (preg_match('/\((.*)\)/', $vatrate, $reg)) @@ -2265,7 +2267,8 @@ class FactureFournisseur extends CommonInvoice $result = ''; - if ($option == 'document') $url = DOL_URL_ROOT.'/fourn/facture/document.php?facid='.$this->id; + if ($option == 'withdraw') $url = DOL_URL_ROOT.'/compta/facture/prelevement.php?facid='.$this->id.'&type=bank-transfer'; + elseif ($option == 'document') $url = DOL_URL_ROOT.'/fourn/facture/document.php?facid='.$this->id; else $url = DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$this->id; if ($short) return $url; @@ -2422,6 +2425,7 @@ class FactureFournisseur extends CommonInvoice $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); $resql = $this->db->query($sql); if ($resql) @@ -2570,6 +2574,8 @@ class FactureFournisseur extends CommonInvoice $object->id = 0; $object->statut = self::STATUS_DRAFT; + $object->fetch_thirdparty(); // We need it to recalculate VAT localtaxes according to main sale taxes and vendor + // Clear fields $object->ref_supplier = (empty($this->ref_supplier) ? $langs->trans("CopyOf").' '.$object->ref_supplier : $this->ref_supplier); $object->author = $user->id; @@ -2637,6 +2643,7 @@ class FactureFournisseur extends CommonInvoice global $conf, $user, $langs; $langs->load("suppliers"); + $outputlangs->load("products"); // Set the model on the model name to use if (empty($modele)) diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index a2ed4b6c0aa..b3c4514f5ff 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -995,7 +995,7 @@ class ProductFournisseur extends Product //$out .= ''.$langs->trans("QtyMin").''.$langs->trans("User").'
    '.dol_print_date($this->db->jdate($productFournLog['datec']), 'dayhour', 'tzuser').'
    '.dol_print_date($productFournLog['datec'], 'dayhour', 'tzuser').''.price($productFournLog['price']).''.$productFournLog['quantity'].''.$productFournLog['lastname'].'
    '.$langs->trans("SupplierRef").''.$langs->trans("QtyOrdered").''.$langs->trans("QtyDispatchedShort").''.$langs->trans("QtyToDispatchShort").''.$langs->trans("QtyToDispatchShort"); + print '
    '.$langs->trans("Reset").'
    '; - print ''; + print ''; print '
    '.$langs->trans('NotePublic').''; - $note_public = $object->getDefaultCreateValueFor('note_public'); - if (empty($note_public))$note_public = $objectsrc->note_public; $doleditor = new DolEditor('note_public', (GETPOSTISSET('note_public') ?GETPOST('note_public', 'none') : $note_public), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); print $doleditor->Create(1); print '
    '.$langs->trans('NotePrivate').''; - $note_private = $object->getDefaultCreateValueFor('note_private'); - if (empty($note_private))$note_private = $objectsrc->note_private; - $doleditor = new DolEditor('note_private', (GETPOSTISSET('note_private') ?GETPOST('note_private', 'none') : $note_private), '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%'); print $doleditor->Create(1); print '
    '; @@ -1310,7 +1310,7 @@ if ((empty($id) && empty($ref)) || $action == 'add' || $action == 'request' || $ $include_users = $object->fetch_users_approver_holiday(); if (is_array($include_users) && in_array($user->id, $include_users) && $object->statut == Holiday::STATUS_VALIDATED) { - print ''.img_edit($langs->trans("Edit")).''; + print ''.img_edit($langs->trans("Edit")).''; } print '
    '; + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print '
    ","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $dashboardlines[$board->element] = $board->load_board($user); } - // Number of commercial proposals opened (expired) + // Number of commercial proposals open (expired) if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; $board = new Propal($db); @@ -365,7 +365,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $dashboardlines[$board->element.'_signed'] = $board->load_board($user, "signed"); } - // Number of commercial proposals opened (expired) + // Number of commercial proposals open (expired) if (!empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->lire) { include_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php'; $board = new SupplierProposal($db); @@ -407,14 +407,14 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { //$dashboardlines[$board->element.'_active'] = $board->load_board($user, "active"); } - // Number of invoices customers (has paid) + // Number of invoices customers (paid) if (!empty($conf->facture->enabled) && $user->rights->facture->lire) { include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $board = new Facture($db); $dashboardlines[$board->element] = $board->load_board($user); } - // Number of supplier invoices (has paid) + // Number of supplier invoices (paid) if (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->fournisseur->facture->lire)) { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $board = new FactureFournisseur($db); @@ -715,21 +715,35 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $textLate = ''; if ($board->nbtodolate > 0) { - $textLate .= ' '; + $textLate .= ''; $textLate .= ' '.$board->nbtodolate; $textLate .= ''; } + $openedDashBoard .= '
    '; + $nbtodClass = ''; if ($board->nbtodo > 0) { $nbtodClass = 'badge badge-info'; } - $openedDashBoard .= ' '.$infoName.' : '.$board->nbtodo.''.$textLate.''."\n"; + $openedDashBoard .= ' '.$infoName.' : '.$board->nbtodo.''; + if ($textLate) { + if ($board->url_late) { + $openedDashBoard .= ''; + $openedDashBoard .= ' '; + } else { + $openedDashBoard .= ' '; + } + $openedDashBoard .= $textLate; + } + $openedDashBoard .= ''."\n"; if ($board->total > 0 && !empty($conf->global->MAIN_WORKBOARD_SHOW_TOTAL_WO_TAX)) { $openedDashBoard .= ''.$langs->trans('Total').' : '.price($board->total).''; } + + $openedDashBoard .= '
    '; } $openedDashBoard .= '
    '."\n"; diff --git a/htdocs/install/doctemplates/products/template_product.odt b/htdocs/install/doctemplates/products/template_product.odt index 344fcfa391a..c73fa69d92d 100644 Binary files a/htdocs/install/doctemplates/products/template_product.odt and b/htdocs/install/doctemplates/products/template_product.odt differ diff --git a/htdocs/install/doctemplates/stocks/template_warehouse.odt b/htdocs/install/doctemplates/stocks/template_warehouse.odt new file mode 100644 index 00000000000..5d4340230a1 Binary files /dev/null and b/htdocs/install/doctemplates/stocks/template_warehouse.odt differ diff --git a/htdocs/install/mysql/data/llx_c_prospectcontactlevel.sql b/htdocs/install/mysql/data/llx_c_prospectcontactlevel.sql new file mode 100644 index 00000000000..b45239ca992 --- /dev/null +++ b/htdocs/install/mysql/data/llx_c_prospectcontactlevel.sql @@ -0,0 +1,31 @@ +-- Copyright (C) 2020 Open-Dsi +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- + +-- +-- Ne pas placer de commentaire en fin de ligne, ce fichier est parsé lors +-- de l'install et tous les sigles '--' sont supprimés. +-- + +-- +-- Prospect level for contacts +-- + +--delete from llx_c_prospectcontactlevel; +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_NONE', 'None', 1); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_LOW', 'Low', 2); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_MEDIUM', 'Medium', 3); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_HIGH', 'High', 4); diff --git a/htdocs/install/mysql/data/llx_c_stcommcontact.sql b/htdocs/install/mysql/data/llx_c_stcommcontact.sql new file mode 100644 index 00000000000..53e6aad1cca --- /dev/null +++ b/htdocs/install/mysql/data/llx_c_stcommcontact.sql @@ -0,0 +1,32 @@ +-- Copyright (C) 2020 Open-Dsi +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- + +-- +-- Ne pas placer de commentaire en fin de ligne, ce fichier est parsé lors +-- de l'install et tous les sigles '--' sont supprimés. +-- + +-- +-- Types action st for contacts +-- + +delete from llx_c_stcommcontact; +insert into llx_c_stcommcontact (id,code,libelle) values (-1, 'ST_NO', 'Do not contact'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 0, 'ST_NEVER', 'Never contacted'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 1, 'ST_TODO', 'To contact'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 2, 'ST_PEND', 'Contact in progress'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 3, 'ST_DONE', 'Contacted'); diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 2a7a8963e9f..83a502dbbff 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -98,7 +98,7 @@ ALTER TABLE llx_bom_bomline ADD COLUMN position integer NOT NULL DEFAULT 0; ALTER TABLE llx_bom_bomline ADD COLUMN qty_frozen smallint DEFAULT 0; ALTER TABLE llx_bom_bomline ADD COLUMN disable_stock_change smallint DEFAULT 0; -ALTER TABLE llx_bom_bomline DROP COLUMN rank; +ALTER TABLE llx_bom_bomline DROP COLUMN `rank`; create table llx_categorie_warehouse ( diff --git a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql index 7f2cc35451c..df4a3e45c75 100644 --- a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql +++ b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql @@ -305,7 +305,6 @@ ALTER TABLE llx_categorie ADD COLUMN fk_user_modif integer; ALTER TABLE llx_commandedet ADD CONSTRAINT fk_commandedet_fk_commandefourndet FOREIGN KEY (fk_commandefourndet) REFERENCES llx_commande_fournisseurdet (rowid); - -- VMYSQL4.3 ALTER TABLE llx_prelevement_facture_demande MODIFY COLUMN fk_facture INTEGER NULL; -- VPGSQL8.2 ALTER TABLE llx_prelevement_facture_demande ALTER COLUMN fk_facture DROP NOT NULL; ALTER TABLE llx_prelevement_facture_demande ADD COLUMN fk_facture_fourn INTEGER NULL; diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index 24b6fd687e1..cea52090aac 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -40,6 +40,10 @@ ALTER TABLE llx_bom_bom MODIFY COLUMN duration double(24,8); -- For v13 +UPDATE llx_document_model set nom = 'standard' where nom = 'Standard' and type ='stock'; +UPDATE llx_document_model set nom = 'stdmovement', type = 'movement' where nom = 'StdMouvement' and type ='mouvement'; + + UPDATE llx_const SET value = 0 WHERE name = 'FACTURE_TVAOPTION' and value = 'franchise'; UPDATE llx_const SET value = 1 WHERE name = 'FACTURE_TVAOPTION' and value <> 'franchise' AND value <> '0' AND value <> '1'; @@ -81,6 +85,7 @@ ALTER TABLE llx_c_incoterms ADD COLUMN label varchar(100) NULL; CREATE TABLE llx_recruitment_recruitmentjobposition( rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, ref varchar(128) DEFAULT '(PROV)' NOT NULL, + entity INTEGER DEFAULT 1 NOT NULL, label varchar(255) NOT NULL, qty integer DEFAULT 1 NOT NULL, fk_soc integer, @@ -89,6 +94,7 @@ CREATE TABLE llx_recruitment_recruitmentjobposition( fk_user_supervisor integer, fk_establishment integer, date_planned date, + remuneration_suggested varchar(255), description text, note_public text, note_private text, @@ -112,6 +118,10 @@ ALTER TABLE llx_recruitment_recruitmentjobposition ADD CONSTRAINT llx_recruitmen ALTER TABLE llx_recruitment_recruitmentjobposition ADD CONSTRAINT llx_recruitment_recruitmentjobposition_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); ALTER TABLE llx_recruitment_recruitmentjobposition ADD INDEX idx_recruitment_recruitmentjobposition_status (status); +ALTER TABLE llx_recruitment_recruitmentjobposition ADD COLUMN email_recruiter varchar(255); +ALTER TABLE llx_recruitment_recruitmentjobposition ADD COLUMN entity INTEGER DEFAULT 1 NOT NULL; +ALTER TABLE llx_recruitment_recruitmentjobposition ADD COLUMN remuneration_suggested varchar(255); + create table llx_recruitment_recruitmentjobposition_extrafields ( rowid integer AUTO_INCREMENT PRIMARY KEY, @@ -124,4 +134,109 @@ ALTER TABLE llx_recruitment_recruitmentjobposition_extrafields ADD INDEX idx_fk_ +CREATE TABLE llx_recruitment_recruitmentcandidature( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_recruitmentjobposition INTEGER NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + description text, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + model_pdf varchar(255), + status smallint NOT NULL, + firstname varchar(128), + lastname varchar(128), + remuneration_requested integer, + remuneration_proposed integer, + fk_recruitment_origin INTEGER NULL + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; +ALTER TABLE llx_recruitment_recruitmentcandidature ADD COLUMN fk_recruitment_origin INTEGER NULL; + +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_rowid (rowid); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_ref (ref); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD CONSTRAINT llx_recruitment_recruitmentcandidature_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_status (status); + + + +create table llx_recruitment_recruitmentcandidature_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + +ALTER TABLE llx_recruitment_recruitmentcandidature_extrafields ADD INDEX idx_fk_object(fk_object); + + + + +CREATE TABLE llx_product_attribute_combination_price_level +( + rowid INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, + fk_product_attribute_combination INTEGER DEFAULT 1 NOT NULL, + fk_price_level INTEGER DEFAULT 1 NOT NULL, + variation_price DOUBLE(24,8) NOT NULL, + variation_price_percentage INTEGER NULL +)ENGINE=innodb; + +ALTER TABLE llx_product_attribute_combination_price_level ADD UNIQUE( fk_product_attribute_combination, fk_price_level); + + + +-- Add dictionary for prospect level and action commercial on contacts (Using this is not recommanded) + +create table llx_c_prospectcontactlevel +( + code varchar(12) PRIMARY KEY, + label varchar(30), + sortorder smallint, + active smallint DEFAULT 1 NOT NULL, + module varchar(32) NULL +) ENGINE=innodb; +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_NONE', 'None', 1); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_LOW', 'Low', 2); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_MEDIUM', 'Medium', 3); +insert into llx_c_prospectcontactlevel (code,label,sortorder) values ('PL_HIGH', 'High', 4); + +create table llx_c_stcommcontact +( + id integer PRIMARY KEY, + code varchar(12) NOT NULL, + libelle varchar(30), + picto varchar(128), + active tinyint default 1 NOT NULL +)ENGINE=innodb; +ALTER TABLE llx_c_stcommcontact ADD UNIQUE INDEX uk_c_stcommcontact(code); + +insert into llx_c_stcommcontact (id,code,libelle) values (-1, 'ST_NO', 'Do not contact'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 0, 'ST_NEVER', 'Never contacted'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 1, 'ST_TODO', 'To contact'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 2, 'ST_PEND', 'Contact in progress'); +insert into llx_c_stcommcontact (id,code,libelle) values ( 3, 'ST_DONE', 'Contacted'); + +ALTER TABLE llx_socpeople ADD COLUMN fk_prospectcontactlevel varchar(12) AFTER priv; +ALTER TABLE llx_socpeople ADD COLUMN fk_stcommcontact integer DEFAULT 0 NOT NULL AFTER fk_prospectcontactlevel; + +create table llx_c_recruitment_origin +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + code varchar(32) NOT NULL, + label varchar(64) NOT NULL, + active tinyint DEFAULT 1 NOT NULL +)ENGINE=innodb; + + + +ALTER TABLE llx_product MODIFY COLUMN seuil_stock_alerte float; +ALTER TABLE llx_product MODIFY COLUMN desiredstock float; +ALTER TABLE llx_product_warehouse_properties MODIFY COLUMN seuil_stock_alerte float; +ALTER TABLE llx_product_warehouse_properties MODIFY COLUMN desiredstock float; diff --git a/htdocs/install/mysql/tables/llx_c_format_cards.sql b/htdocs/install/mysql/tables/llx_c_format_cards.sql index b69b9eb19d1..d3885b5d256 100644 --- a/htdocs/install/mysql/tables/llx_c_format_cards.sql +++ b/htdocs/install/mysql/tables/llx_c_format_cards.sql @@ -36,4 +36,4 @@ CREATE TABLE llx_c_format_cards custom_x double(24,8) NOT NULL, custom_y double(24,8) NOT NULL, active integer NOT NULL -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_c_prospectcontactlevel.sql b/htdocs/install/mysql/tables/llx_c_prospectcontactlevel.sql new file mode 100644 index 00000000000..421b3452371 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_prospectcontactlevel.sql @@ -0,0 +1,27 @@ +-- =================================================================== +-- Copyright (C) 2020 Open-Dsi +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- =================================================================== + +create table llx_c_prospectcontactlevel +( + code varchar(12) PRIMARY KEY, + label varchar(30), + sortorder smallint, + active smallint DEFAULT 1 NOT NULL, + module varchar(32) NULL +) ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_c_recruitment_origin.sql b/htdocs/install/mysql/tables/llx_c_recruitment_origin.sql new file mode 100644 index 00000000000..b18f7eb383c --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_recruitment_origin.sql @@ -0,0 +1,33 @@ +-- ======================================================================== +-- Copyright (C) 2005-2016 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- Defini les types de contact d'un element sert de reference pour +-- la table llx_element_contact +-- +-- element est le nom de la table utilisant le type de contact. +-- i.e. contact, facture, projet, societe (sans le llx_ devant). +-- Libelle est un texte decrivant le type de contact. +-- active precise si cette valeur est 'active' ou 'archive'. +-- +-- ======================================================================== + +create table llx_c_recruitment_origin +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + code varchar(32) NOT NULL, + label varchar(64) NOT NULL, + active tinyint DEFAULT 1 NOT NULL +)ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_c_stcommcontact.key.sql b/htdocs/install/mysql/tables/llx_c_stcommcontact.key.sql new file mode 100644 index 00000000000..12402658a65 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_stcommcontact.key.sql @@ -0,0 +1,19 @@ +-- ======================================================================== +-- Copyright (C) 2020 Open-Dsi +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ======================================================================== + +ALTER TABLE llx_c_stcommcontact ADD UNIQUE INDEX uk_c_stcommcontact(code); diff --git a/htdocs/install/mysql/tables/llx_c_stcommcontact.sql b/htdocs/install/mysql/tables/llx_c_stcommcontact.sql new file mode 100644 index 00000000000..c906e4f5103 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_c_stcommcontact.sql @@ -0,0 +1,27 @@ +-- ======================================================================== +-- Copyright (C) 2020 Open-Dsi +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ======================================================================== + +create table llx_c_stcommcontact +( + id integer PRIMARY KEY, + code varchar(12) NOT NULL, + libelle varchar(30), + picto varchar(128), + active tinyint default 1 NOT NULL +)ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_establishment.sql b/htdocs/install/mysql/tables/llx_establishment.sql index f47d7b4aeae..0d487e94e5f 100644 --- a/htdocs/install/mysql/tables/llx_establishment.sql +++ b/htdocs/install/mysql/tables/llx_establishment.sql @@ -38,5 +38,5 @@ CREATE TABLE llx_establishment ( datec datetime NOT NULL, tms timestamp NOT NULL, status tinyint DEFAULT 1 -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_expeditiondet_batch.sql b/htdocs/install/mysql/tables/llx_expeditiondet_batch.sql index 7a6a3bfd777..43b64451364 100644 --- a/htdocs/install/mysql/tables/llx_expeditiondet_batch.sql +++ b/htdocs/install/mysql/tables/llx_expeditiondet_batch.sql @@ -23,5 +23,5 @@ CREATE TABLE llx_expeditiondet_batch ( batch varchar(128) DEFAULT NULL, qty double NOT NULL DEFAULT '0', fk_origin_stock integer NOT NULL -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_expensereport_rules.sql b/htdocs/install/mysql/tables/llx_expensereport_rules.sql index aa6d7553639..2a10cc24a7d 100644 --- a/htdocs/install/mysql/tables/llx_expensereport_rules.sql +++ b/htdocs/install/mysql/tables/llx_expensereport_rules.sql @@ -31,4 +31,4 @@ CREATE TABLE llx_expensereport_rules ( code_expense_rules_type varchar(50) NOT NULL, is_for_all tinyint DEFAULT 0, entity integer DEFAULT 1 -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_inventory.sql b/htdocs/install/mysql/tables/llx_inventory.sql index 70e409193aa..4ccb234e26e 100644 --- a/htdocs/install/mysql/tables/llx_inventory.sql +++ b/htdocs/install/mysql/tables/llx_inventory.sql @@ -35,4 +35,4 @@ CREATE TABLE llx_inventory date_validation datetime DEFAULT NULL, import_key varchar(14) -- import key ) -ENGINE=InnoDB; +ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_inventorydet.sql b/htdocs/install/mysql/tables/llx_inventorydet.sql index b4df529433e..161e34183a0 100644 --- a/htdocs/install/mysql/tables/llx_inventorydet.sql +++ b/htdocs/install/mysql/tables/llx_inventorydet.sql @@ -30,4 +30,4 @@ qty_stock double DEFAULT NULL, -- The targeted value. can be filled during dra qty_view double DEFAULT NULL, -- must be filled once regulation is done qty_regulated double DEFAULT NULL -- must be filled once regulation is done ) -ENGINE=InnoDB; +ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_oauth_state.sql b/htdocs/install/mysql/tables/llx_oauth_state.sql index 39ade6bc529..77093f6d1b4 100644 --- a/htdocs/install/mysql/tables/llx_oauth_state.sql +++ b/htdocs/install/mysql/tables/llx_oauth_state.sql @@ -22,4 +22,4 @@ CREATE TABLE llx_oauth_state ( fk_user integer, fk_adherent integer, entity integer DEFAULT 1 -)ENGINE=InnoDB; +)ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_oauth_token.sql b/htdocs/install/mysql/tables/llx_oauth_token.sql index bbc236be6c1..145e646230d 100644 --- a/htdocs/install/mysql/tables/llx_oauth_token.sql +++ b/htdocs/install/mysql/tables/llx_oauth_token.sql @@ -24,4 +24,4 @@ CREATE TABLE llx_oauth_token ( fk_user integer, fk_adherent integer, entity integer DEFAULT 1 -)ENGINE=InnoDB; +)ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_opensurvey_comments.sql b/htdocs/install/mysql/tables/llx_opensurvey_comments.sql index 74a9d9ec3cb..3fcc5a0abf9 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_comments.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_comments.sql @@ -21,5 +21,5 @@ CREATE TABLE llx_opensurvey_comments ( comment text NOT NULL, tms timestamp, usercomment text -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_opensurvey_formquestions.sql b/htdocs/install/mysql/tables/llx_opensurvey_formquestions.sql index 044fabc5029..8a15936c86f 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_formquestions.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_formquestions.sql @@ -20,5 +20,5 @@ CREATE TABLE llx_opensurvey_formquestions ( id_sondage VARCHAR(16), question TEXT, available_answers TEXT -- List of available answers -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql index c3f1cdbfee1..0521f533fdd 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_sondage.sql @@ -31,4 +31,4 @@ CREATE TABLE llx_opensurvey_sondage ( allow_spy tinyint NOT NULL DEFAULT 1, tms TIMESTAMP, sujet TEXT -- Not filled if format = 'F'. Question are into table llx_opensurvey_formquestions -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_opensurvey_user_formanswers.sql b/htdocs/install/mysql/tables/llx_opensurvey_user_formanswers.sql index bd55d256a06..957818db4a1 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_user_formanswers.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_user_formanswers.sql @@ -19,4 +19,4 @@ CREATE TABLE llx_opensurvey_user_formanswers ( fk_user_survey INTEGER NOT NULL, fk_question INTEGER NOT NULL, reponses TEXT -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_opensurvey_user_studs.sql b/htdocs/install/mysql/tables/llx_opensurvey_user_studs.sql index 16ef0b2cf7e..a2ddafa1b54 100644 --- a/htdocs/install/mysql/tables/llx_opensurvey_user_studs.sql +++ b/htdocs/install/mysql/tables/llx_opensurvey_user_studs.sql @@ -21,4 +21,4 @@ CREATE TABLE llx_opensurvey_user_studs ( id_sondage VARCHAR(16) NOT NULL, reponses VARCHAR(100) NOT NULL, -- Not used for 'F' surveys tms timestamp -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql index b360b4d7f9d..074012e138c 100644 --- a/htdocs/install/mysql/tables/llx_product.sql +++ b/htdocs/install/mysql/tables/llx_product.sql @@ -60,7 +60,7 @@ create table llx_product tobatch tinyint DEFAULT 0 NOT NULL, -- Is it a product that need a batch management (eat-by or lot management) fk_product_type integer DEFAULT 0, -- Type of product: 0 for regular product, 1 for service, 9 for other (used by external module) duration varchar(6), - seuil_stock_alerte integer DEFAULT NULL, + seuil_stock_alerte float DEFAULT NULL, url varchar(255), barcode varchar(180) DEFAULT NULL, -- barcode fk_barcode_type integer DEFAULT NULL, -- barcode type @@ -96,7 +96,7 @@ create table llx_product import_key varchar(14), -- Import key model_pdf varchar(255), -- model save dodument used fk_price_expression integer, -- Link to the rule for dynamic price calculation - desiredstock integer DEFAULT 0, + desiredstock float DEFAULT 0, fk_unit integer DEFAULT NULL, price_autogen tinyint DEFAULT 0, fk_project integer DEFAULT NULL -- Used when product was generated by a project or is specifif to a project diff --git a/htdocs/install/mysql/tables/llx_product_attribute_combination_price_level.sql b/htdocs/install/mysql/tables/llx_product_attribute_combination_price_level.sql new file mode 100644 index 00000000000..ae068b71ed0 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_product_attribute_combination_price_level.sql @@ -0,0 +1,28 @@ +-- ============================================================================ +-- Copyright (C) 2020 John BOTELLA +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ============================================================================ + +CREATE TABLE llx_product_attribute_combination_price_level +( + rowid INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, + fk_product_attribute_combination INTEGER DEFAULT 1 NOT NULL, + fk_price_level INTEGER DEFAULT 1 NOT NULL, + variation_price DOUBLE(24,8) NOT NULL, + variation_price_percentage INTEGER NULL +)ENGINE=innodb; + +ALTER TABLE llx_product_attribute_combination_price_level ADD UNIQUE( fk_product_attribute_combination, fk_price_level); diff --git a/htdocs/install/mysql/tables/llx_product_batch.sql b/htdocs/install/mysql/tables/llx_product_batch.sql index 7b09d6a0024..9b736278e3a 100644 --- a/htdocs/install/mysql/tables/llx_product_batch.sql +++ b/htdocs/install/mysql/tables/llx_product_batch.sql @@ -27,5 +27,5 @@ CREATE TABLE llx_product_batch ( batch varchar(128) NOT NULL, qty double NOT NULL DEFAULT 0, import_key varchar(14) DEFAULT NULL -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_product_lot.sql b/htdocs/install/mysql/tables/llx_product_lot.sql index 885f699d800..4d59a46c153 100644 --- a/htdocs/install/mysql/tables/llx_product_lot.sql +++ b/htdocs/install/mysql/tables/llx_product_lot.sql @@ -29,4 +29,4 @@ CREATE TABLE llx_product_lot ( fk_user_creat integer, fk_user_modif integer, import_key integer -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql index b5d69defd9e..903bd59b524 100644 --- a/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql +++ b/htdocs/install/mysql/tables/llx_product_stock_entrepot.sql @@ -24,8 +24,8 @@ create table llx_product_warehouse_properties tms timestamp, fk_product integer NOT NULL, fk_entrepot integer NOT NULL, - seuil_stock_alerte integer DEFAULT '0', - desiredstock integer DEFAULT '0', + seuil_stock_alerte float DEFAULT '0', + desiredstock float DEFAULT '0', import_key varchar(14) -- Import key )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_propal_merge_pdf_product.sql b/htdocs/install/mysql/tables/llx_propal_merge_pdf_product.sql index e081b97969f..0c636b2507c 100644 --- a/htdocs/install/mysql/tables/llx_propal_merge_pdf_product.sql +++ b/htdocs/install/mysql/tables/llx_propal_merge_pdf_product.sql @@ -24,5 +24,5 @@ CREATE TABLE llx_propal_merge_pdf_product ( datec datetime NOT NULL, tms timestamp NOT NULL, import_key varchar(14) DEFAULT NULL -) ENGINE=InnoDB; +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.key.sql b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.key.sql new file mode 100644 index 00000000000..8f92832c2a3 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.key.sql @@ -0,0 +1,27 @@ +-- Copyright (C) 2020 Laurent Destailleur +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_rowid (rowid); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_ref (ref); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD CONSTRAINT llx_recruitment_recruitmentcandidature_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); +ALTER TABLE llx_recruitment_recruitmentcandidature ADD INDEX idx_recruitment_recruitmentcandidature_status (status); +-- END MODULEBUILDER INDEXES + +--ALTER TABLE llx_mymodule_myobject ADD UNIQUE INDEX uk_mymodule_myobject_fieldxy(fieldx, fieldy); + +--ALTER TABLE llx_mymodule_myobject ADD CONSTRAINT llx_mymodule_myobject_fk_field FOREIGN KEY (fk_field) REFERENCES llx_mymodule_myotherobject(rowid); + diff --git a/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.sql b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.sql new file mode 100644 index 00000000000..43bdb14e7bd --- /dev/null +++ b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature.sql @@ -0,0 +1,38 @@ +-- Copyright (C) 2020 Laurent Destailleur +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +CREATE TABLE llx_recruitment_recruitmentcandidature( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + fk_recruitmentjobposition INTEGER NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + description text, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + model_pdf varchar(255), + status smallint NOT NULL, + firstname varchar(128), + lastname varchar(128), + remuneration_requested integer, + remuneration_proposed integer, + fk_recruitment_origin INTEGER NULL + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.key.sql b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.key.sql new file mode 100644 index 00000000000..fb1522bf6f1 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.key.sql @@ -0,0 +1,19 @@ +-- Copyright (C) 2020 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +-- BEGIN MODULEBUILDER INDEXES +ALTER TABLE llx_recruitment_recruitmentcandidature_extrafields ADD INDEX idx_fk_object(fk_object); +-- END MODULEBUILDER INDEXES diff --git a/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.sql b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.sql new file mode 100644 index 00000000000..d0fb92fead9 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_recruitment_recruitmentcandidature_extrafields.sql @@ -0,0 +1,23 @@ +-- Copyright (C) 2020 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +create table llx_recruitment_recruitmentcandidature_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_recruitment_recruitmentjobposition.sql b/htdocs/install/mysql/tables/llx_recruitment_recruitmentjobposition.sql index c527409862d..b342156ccd1 100644 --- a/htdocs/install/mysql/tables/llx_recruitment_recruitmentjobposition.sql +++ b/htdocs/install/mysql/tables/llx_recruitment_recruitmentjobposition.sql @@ -17,15 +17,18 @@ CREATE TABLE llx_recruitment_recruitmentjobposition( -- BEGIN MODULEBUILDER FIELDS rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, - ref varchar(128) DEFAULT '(PROV)' NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + entity INTEGER DEFAULT 1 NOT NULL, label varchar(255) NOT NULL, qty integer DEFAULT 1 NOT NULL, fk_soc integer, fk_project integer, - fk_user_recruiter integer, + fk_user_recruiter integer, + email_recruiter varchar(255), fk_user_supervisor integer, fk_establishment integer, - date_planned date, + date_planned date, + remuneration_suggested varchar(255), description text, note_public text, note_private text, diff --git a/htdocs/install/mysql/tables/llx_socpeople.sql b/htdocs/install/mysql/tables/llx_socpeople.sql index fceb2044649..2a1b551beb9 100644 --- a/htdocs/install/mysql/tables/llx_socpeople.sql +++ b/htdocs/install/mysql/tables/llx_socpeople.sql @@ -2,6 +2,7 @@ -- Copyright (C) 2001-2004 Rodolphe Quiedeville -- Copyright (C) 2008 Laurent Destailleur -- Copyright (C) 2005-2010 Regis Houssin +-- Copyright (C) 2020 Open-Dsi -- -- 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 @@ -57,6 +58,8 @@ create table llx_socpeople photo varchar(255), no_email smallint NOT NULL DEFAULT 0, -- deprecated. Use table llx_mailing_unsubscribe instead priv smallint NOT NULL DEFAULT 0, + fk_prospectcontactlevel varchar(12), -- prospect level (in llx_c_prospectcontactlevel) + fk_stcommcontact integer DEFAULT 0 NOT NULL, -- commercial statut fk_user_creat integer DEFAULT 0, -- user qui a creel'enregistrement fk_user_modif integer, note_private text, diff --git a/htdocs/install/mysql/tables/llx_user.sql b/htdocs/install/mysql/tables/llx_user.sql index e27ac19c15a..b49feba85d6 100644 --- a/htdocs/install/mysql/tables/llx_user.sql +++ b/htdocs/install/mysql/tables/llx_user.sql @@ -85,7 +85,7 @@ create table llx_user openid varchar(255), statut tinyint DEFAULT 1, photo varchar(255), -- filename or url of photo - lang varchar(6), + lang varchar(6), -- default language for communication. Note that language selected by user as interface language is savec into llx_user_param. color varchar(6), barcode varchar(255) DEFAULT NULL, fk_barcode_type integer DEFAULT 0, diff --git a/htdocs/install/pgsql/functions/functions.sql b/htdocs/install/pgsql/functions/functions.sql index 40628f93ac6..22c122a1164 100644 --- a/htdocs/install/pgsql/functions/functions.sql +++ b/htdocs/install/pgsql/functions/functions.sql @@ -58,6 +58,7 @@ CREATE OR REPLACE FUNCTION dol_util_triggerall(DoEnable boolean) RETURNS integer -- Add triggers for timestamp fields named tms CREATE OR REPLACE FUNCTION update_modified_column_tms() RETURNS TRIGGER AS $$ BEGIN NEW.tms = now(); RETURN NEW; END; $$ LANGUAGE plpgsql; + CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_accounting_account FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_accounting_fiscalyear FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_actioncomm FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); @@ -127,6 +128,9 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_localtax FOR EACH RO CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mailing_cibles FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_menu FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_mo FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_mo_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_mrp_production FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_notify FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_notify_def FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_opensurvey_comments FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); diff --git a/htdocs/install/repair.php b/htdocs/install/repair.php index d427e529a8d..ef4e3b82a9d 100644 --- a/htdocs/install/repair.php +++ b/htdocs/install/repair.php @@ -996,7 +996,7 @@ if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) $resql2 = $db->query($sql2); if ($resql2) { - // We update product_stock, so we must field stock into product too. + // We update product_stock, so we must fill p.stock into product too. $sql3 = 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)'; $resql3 = $db->query($sql3); if (!$resql3) diff --git a/htdocs/langs/de_AT/main.lang b/htdocs/langs/de_AT/main.lang index 545ae518ec7..124392e3512 100644 --- a/htdocs/langs/de_AT/main.lang +++ b/htdocs/langs/de_AT/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias NoRecordFound=Kein Eintrag gefunden NoRecordDeleted=Kein Eintrag gelöscht NoError=Kein Fehler diff --git a/htdocs/langs/de_CH/main.lang b/htdocs/langs/de_CH/main.lang index 60ec3c2adff..ba91e452a89 100644 --- a/htdocs/langs/de_CH/main.lang +++ b/htdocs/langs/de_CH/main.lang @@ -21,7 +21,6 @@ FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M NoTemplateDefined=Für diesen Emailtyp habe ich keine Vorlage.. AvailableVariables=Verfügbare Ersatzvariablen -EmptySearchString=Enter non empty search criterias NoRecordDeleted=Es wurde kein Datensatz gelöscht NotEnoughDataYet=Nicht genügend Daten NoError=Kein Fehler diff --git a/htdocs/langs/de_CH/stocks.lang b/htdocs/langs/de_CH/stocks.lang index a7776df946c..fc51f5818de 100644 --- a/htdocs/langs/de_CH/stocks.lang +++ b/htdocs/langs/de_CH/stocks.lang @@ -14,7 +14,6 @@ StockLimit=Sicherungsbestand für autom. Benachrichtigung RealStock=Realer Lagerbestand VirtualStock=Theoretisches Warenlager AverageUnitPricePMPShort=Gewichteter Durchschnitts-Einstandspreis -AverageUnitPricePMP=Gewichteter Durchschnittpreis bei Erwerb DesiredStockDesc=Dieser Bestand wird für die Nachbestellfunktion verwendet. UseVirtualStockByDefault=Nutze theoretische Lagerbestände anstatt des physischem Bestands für die Nachbestellungsfunktion UseVirtualStock=theoretisches Warenlager verwenden diff --git a/htdocs/langs/en_AU/admin.lang b/htdocs/langs/en_AU/admin.lang index 50add47a7d4..0980facb414 100644 --- a/htdocs/langs/en_AU/admin.lang +++ b/htdocs/langs/en_AU/admin.lang @@ -1,5 +1,4 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OldVATRates=Old GST rate NewVATRates=New GST rate DictionaryVAT=GST Rates or Sales Tax Rates diff --git a/htdocs/langs/en_AU/main.lang b/htdocs/langs/en_AU/main.lang index f51ad592766..dac6a875c2d 100644 --- a/htdocs/langs/en_AU/main.lang +++ b/htdocs/langs/en_AU/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %I:%M %p FormatDateHourSecShort=%d/%m/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias ErrorNoVATRateDefinedForSellerCountry=Error, no GST rates defined for country '%s'. Quadri=Quarter PriceUTTC=U.P. (incl GST) diff --git a/htdocs/langs/en_AU/website.lang b/htdocs/langs/en_AU/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/en_AU/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/en_CA/admin.lang b/htdocs/langs/en_CA/admin.lang index a7c6cc9d271..62dd510c5e0 100644 --- a/htdocs/langs/en_CA/admin.lang +++ b/htdocs/langs/en_CA/admin.lang @@ -1,5 +1,4 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. LocalTax1Management=PST Management CompanyZip=Postal code LDAPFieldZip=Postal code diff --git a/htdocs/langs/en_CA/main.lang b/htdocs/langs/en_CA/main.lang index 7ce3e998978..6d4ce6e30f2 100644 --- a/htdocs/langs/en_CA/main.lang +++ b/htdocs/langs/en_CA/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d.%m.%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias ErrorNoVATRateDefinedForSellerCountry=Error, no vat rate defined for country '%s'. AmountVAT=Amount GST AmountLT1=Amount PST diff --git a/htdocs/langs/en_CA/website.lang b/htdocs/langs/en_CA/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/en_CA/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/en_GB/admin.lang b/htdocs/langs/en_GB/admin.lang index 1d26334c78d..11a52c3a368 100644 --- a/htdocs/langs/en_GB/admin.lang +++ b/htdocs/langs/en_GB/admin.lang @@ -20,7 +20,6 @@ ImportPostgreSqlDesc=To import a backup file, you must use the pg_restore comman CommandsToDisableForeignKeysForImportWarning=This is mandatory if you want to restore your sql dumps later ModulesMarketPlaceDesc=You can find more modules to download from external websites on the Internet... ModulesMarketPlaces=Find external applications and modules -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. AvailableOnlyIfJavascriptAndAjaxNotDisabled=Available only if JavaScript is enabled InstrucToEncodePass=To have password encoded into the conf.php file, replace the line
    $dolibarr_main_db_pass="...";
    with
    $dolibarr_main_db_pass="crypted:%s"; InstrucToClearPass=To have password decoded (clear) into the conf.php file, replace the line
    $dolibarr_main_db_pass="crypted:...";
    with
    $dolibarr_main_db_pass="%s"; diff --git a/htdocs/langs/en_GB/main.lang b/htdocs/langs/en_GB/main.lang index b712cacaa69..5617fe77778 100644 --- a/htdocs/langs/en_GB/main.lang +++ b/htdocs/langs/en_GB/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias ErrorNoVATRateDefinedForSellerCountry=Error, no VAT rates defined for country '%s'. NotAuthorized=You are not authorised to do that. BackgroundColorByDefault=Default background colour diff --git a/htdocs/langs/en_GB/website.lang b/htdocs/langs/en_GB/website.lang index f2cfbf3456c..ef8e16da6ad 100644 --- a/htdocs/langs/en_GB/website.lang +++ b/htdocs/langs/en_GB/website.lang @@ -1,3 +1,2 @@ # Dolibarr language file - Source file is en_US - website PageNameAliasHelp=Name or alias of the page.
    This alias is also used to forge an SEO URL when the website is run from a Virtual host of a Web server (like Apache, Nginx, ...). Use the button "%s" to edit this alias. -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/en_IN/admin.lang b/htdocs/langs/en_IN/admin.lang index ebfc7deb6d3..4b3c42b80b1 100644 --- a/htdocs/langs/en_IN/admin.lang +++ b/htdocs/langs/en_IN/admin.lang @@ -1,5 +1,4 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. Module20Name=Quotations Module20Desc=Management of quotations Permission21=Read quotations diff --git a/htdocs/langs/en_IN/main.lang b/htdocs/langs/en_IN/main.lang index 15902ff1c4d..46aef779403 100644 --- a/htdocs/langs/en_IN/main.lang +++ b/htdocs/langs/en_IN/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %I:%M %p FormatDateHourSecShort=%d/%m/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias CommercialProposalsShort=Quotations LinkToProposal=Link to quotation SearchIntoCustomerProposals=Quotations diff --git a/htdocs/langs/en_IN/website.lang b/htdocs/langs/en_IN/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/en_IN/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/en_SG/admin.lang b/htdocs/langs/en_SG/admin.lang index bdc794e1b31..c1d306ec390 100644 --- a/htdocs/langs/en_SG/admin.lang +++ b/htdocs/langs/en_SG/admin.lang @@ -1,4 +1,3 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OperationParamDesc=Define the values to use for the object of the action, or how to extract values. For example:
    objproperty1=SET:the value to set
    objproperty2=SET:a value with replacement of __objproperty1__
    objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
    objproperty4=EXTRACT:HEADER:X-Myheaderkey:\\s*([^\\s]*)
    options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
    object.objproperty5=EXTRACT:BODY:My company name is\\s([^\\s]*)

    Use a ; char as separator to extract or set several properties. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\\s([^\\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/langs/en_SG/main.lang b/htdocs/langs/en_SG/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/en_SG/main.lang +++ b/htdocs/langs/en_SG/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/en_SG/website.lang b/htdocs/langs/en_SG/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/en_SG/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index be6ca9e2f19..7b59e33b296 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -149,6 +149,7 @@ ACCOUNTING_MANAGE_ZERO=Allow to manage different number of zeros at the end of a BANK_DISABLE_DIRECT_INPUT=Disable direct recording of transaction in bank account ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL=Enable draft export on journal ACCOUNTANCY_COMBO_FOR_AUX=Enable combo list for subsidiary account (may be slow if you have a lot of third parties) +ACCOUNTING_DATE_START_BINDING=Define a date to start binding & transfer in accountancy. Below this date, the transactions will not be transferred to accounting. ACCOUNTING_SELL_JOURNAL=Sell journal ACCOUNTING_PURCHASE_JOURNAL=Purchase journal @@ -284,6 +285,7 @@ ShowTutorial=Show Tutorial NotReconciled=Not reconciled ## Admin +BindingOptions=Binding options ApplyMassCategories=Apply mass categories AddAccountFromBookKeepingWithNoCategories=Available account not yet in the personalized group CategoryDeleted=Category for the accounting account has been removed diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 76b74231570..67611c6c0c0 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -409,7 +409,9 @@ PriceBaseTypeToChange=Modify on prices with base reference value defined on MassConvert=Launch bulk conversion PriceFormatInCurrentLanguage=Price Format In Current Language String=String +String1Line=String (1 line) TextLong=Long text +TextLongNLines=Long text (n lines) HtmlText=Html text Int=Integer Float=Float @@ -544,9 +546,9 @@ Module54Desc=Management of contracts (services or recurring subscriptions) Module55Name=Barcodes Module55Desc=Barcode management Module56Name=Payment by credit transfer -Module56Desc=Management of payment of suppliers by credit transfer orders. It includes generation of SEPA file for European countries. -Module57Name=Bank Direct Debit payments -Module57Desc=Management of Direct Debit payment orders. It includes generation of SEPA file for European countries. +Module56Desc=Management of payment of suppliers by Credit Transfer orders. It includes generation of SEPA file for European countries. +Module57Name=Payments by Direct Debit +Module57Desc=Management of Direct Debit orders. It includes generation of SEPA file for European countries. Module58Name=ClickToDial Module58Desc=Integration of a ClickToDial system (Asterisk, ...) Module59Name=Bookmark4u @@ -948,7 +950,8 @@ Permission63003=Delete resources Permission63004=Link resources to agenda events DictionaryCompanyType=Third-party types DictionaryCompanyJuridicalType=Third-party legal entities -DictionaryProspectLevel=Prospect potential +DictionaryProspectLevel=Prospect potential level for companies +DictionaryProspectContactLevel=Prospect potential level for contacts DictionaryCanton=States/Provinces DictionaryRegion=Regions DictionaryCountry=Countries @@ -978,7 +981,8 @@ DictionaryEMailTemplates=Email Templates DictionaryUnits=Units DictionaryMeasuringUnits=Measuring Units DictionarySocialNetworks=Social Networks -DictionaryProspectStatus=Prospect status +DictionaryProspectStatus=Prospect status for companies +DictionaryProspectContactStatus=Prospect status for contacts DictionaryHolidayTypes=Types of leave DictionaryOpportunityStatus=Lead status for project/lead DictionaryExpenseTaxCat=Expense report - Transportation categories @@ -1077,7 +1081,7 @@ LoginPage=Login page BackgroundImageLogin=Background image PermanentLeftSearchForm=Permanent search form on left menu DefaultLanguage=Default language -EnableMultilangInterface=Enable multilanguage support +EnableMultilangInterface=Enable multilanguage support for customer or vendor relationships EnableShowLogo=Show the company logo in the menu CompanyInfo=Company/Organization CompanyIds=Company/Organization identities @@ -1241,8 +1245,8 @@ WarningAtLeastKeyOrTranslationRequired=A search criteria is required at least fo NewTranslationStringToShow=New translation string to show OriginalValueWas=The original translation is overwritten. Original value was:

    %s TransKeyWithoutOriginalValue=You forced a new translation for the translation key '%s' that does not exist in any language files -TitleNumberOfActivatedModules=Activated application|modules -TotalNumberOfActivatedModules=Activated application/modules: %s / %s +TitleNumberOfActivatedModules=Activated modules +TotalNumberOfActivatedModules=Activated modules: %s / %s YouMustEnableOneModule=You must at least enable 1 module ClassNotFoundIntoPathWarning=Class %s not found in PHP path YesInSummer=Yes in summer @@ -1680,7 +1684,7 @@ AGENDA_USE_EVENT_TYPE=Use events types (managed in menu Setup -> Dictionaries -> AGENDA_USE_EVENT_TYPE_DEFAULT=Automatically set this default value for type of event in event create form AGENDA_DEFAULT_FILTER_TYPE=Automatically set this type of event in search filter of agenda view AGENDA_DEFAULT_FILTER_STATUS=Automatically set this status for events in search filter of agenda view -AGENDA_DEFAULT_VIEW=Which tab do you want to open by default when selecting menu Agenda +AGENDA_DEFAULT_VIEW=Which view do you want to open by default when selecting menu Agenda AGENDA_REMINDER_EMAIL=Enable event reminder by emails (remind option/delay can be defined on each event). Note: Module %s must be enabled and correctly setup to have reminder sent at the correct frequency. AGENDA_REMINDER_BROWSER=Enable event reminder on user's browser (when event date is reached, each user is able to refuse this from the browser confirmation question) AGENDA_REMINDER_BROWSER_SOUND=Enable sound notification @@ -1688,7 +1692,7 @@ AGENDA_SHOW_LINKED_OBJECT=Show linked object into agenda view ##### Clicktodial ##### ClickToDialSetup=Click To Dial module setup ClickToDialUrlDesc=Url called when a click on phone picto is done. In URL, you can use tags
    __PHONETO__ that will be replaced with the phone number of person to call
    __PHONEFROM__ that will be replaced with phone number of calling person (yours)
    __LOGIN__ that will be replaced with clicktodial login (defined on user card)
    __PASS__ that will be replaced with clicktodial password (defined on user card). -ClickToDialDesc=This module makea phone numbers clickable links. A click on the icon will make your phone call the number. This can be used to call a call-center system from Dolibarr that can call the phone number on a SIP system for example. +ClickToDialDesc=This module change phone numbers, when using a desktop computer, into clickable links. A click will call the number. This can be used to start the phone call when using a soft phone on your desktop or when using a CTI system based on SIP protocol for example. Note: When using a smartphone, phone numbers are always clickable. ClickToDialUseTelLink=Use just a link "tel:" on phone numbers ClickToDialUseTelLinkDesc=Use this method if your users have a softphone or a software interface installed on the same computer as the browser, and called when you click on a link in your browser that starts with "tel:". If you need a full server solution (no need of local software installation), you must set this to "No" and fill next field. ##### Point Of Sale (CashDesk) ##### @@ -1819,6 +1823,7 @@ EnterAnyCode=This field contains a reference to identify line. Enter any value o Enter0or1=Enter 0 or 1 UnicodeCurrency=Enter here between braces, list of byte number that represent the currency symbol. For example: for $, enter [36] - for brazil real R$ [82,36] - for €, enter [8364] ColorFormat=The RGB color is in HEX format, eg: FF0000 +PictoHelp=Icon name in dolibarr format ('image.png' if into the current theme directory, 'image.png@nom_du_module' if into the directory /img/ of a module) PositionIntoComboList=Position of line into combo lists SellTaxRate=Sale tax rate RecuperableOnly=Yes for VAT "Not Perceived but Recoverable" dedicated for some state in France. Keep value to "No" in all other cases. @@ -1845,6 +1850,7 @@ MailToSendSupplierRequestForQuotation=Quotation request MailToSendSupplierOrder=Purchase orders MailToSendSupplierInvoice=Vendor invoices MailToSendContract=Contracts +MailToSendReception=Receptions MailToThirdparty=Third parties MailToMember=Members MailToUser=Users @@ -1858,6 +1864,7 @@ ExampleOfNewsMessageForMajorRelease=Dolibarr ERP & CRM %s is available. Version ExampleOfNewsMessageForMaintenanceRelease=Dolibarr ERP & CRM %s is available. Version %s is a maintenance version, so contains only bug fixes. We recommend all users to upgrade to this version. A maintenance release does not introduce new features or changes to the database. You may download it from the download area of https://www.dolibarr.org portal (subdirectory Stable versions). You can read the ChangeLog for complete list of changes. MultiPriceRuleDesc=When option "Several levels of prices per product/service" is enabled, you can define different prices (one per price level) for each product. To save you time, here you may enter a rule to autocalculate a price for each level based on the price of the first level, so you will have to only enter a price for the first level for each product. This page is designed to save you time but is useful only if your prices for each level are relative to first level. You can ignore this page in most cases. ModelModulesProduct=Templates for product documents +WarehouseModelModules=Templates for documents of warehouses ToGenerateCodeDefineAutomaticRuleFirst=To be able to generate codes automatically, you must first define a manager to auto-define the barcode number. SeeSubstitutionVars=See * note for list of possible substitution variables SeeChangeLog=See ChangeLog file (english only) @@ -2008,3 +2015,6 @@ RssNote=Note: Each RSS feed definition provides a widget that you must enable to JumpToBoxes=Jump to Setup -> Widgets MeasuringUnitTypeDesc=Use here a value like "size", "surface", "volume", "weight", "time" MeasuringScaleDesc=The scale is the number of places you have to move the decimal part to match the default reference unit. For "time" unit type, it is the number of seconds. Values between 80 and 99 are reserved values. +TemplateAdded=Template added +TemplateUpdated=Template updated +TemplateDeleted=Template deleted diff --git a/htdocs/langs/en_US/boxes.lang b/htdocs/langs/en_US/boxes.lang index bd62684421a..69025458630 100644 --- a/htdocs/langs/en_US/boxes.lang +++ b/htdocs/langs/en_US/boxes.lang @@ -83,6 +83,7 @@ BoxTitleLatestModifiedSupplierOrders=Vendor Orders: last %s modified BoxTitleLastModifiedCustomerBills=Customer Invoices: last %s modified BoxTitleLastModifiedCustomerOrders=Sales Orders: last %s modified BoxTitleLastModifiedPropals=Latest %s modified proposals +BoxTitleLatestModifiedJobPositions=Latest %s modified jobs ForCustomersInvoices=Customers invoices ForCustomersOrders=Customers orders ForProposals=Proposals diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index c7d7dd95cb7..094c70ca687 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -77,7 +77,7 @@ POSModule=POS Module BasicPhoneLayout=Use basic layout for phones SetupOfTerminalNotComplete=Setup of terminal %s is not complete DirectPayment=Direct payment -DirectPaymentButton=Direct cash payment button +DirectPaymentButton=Add a "Direct cash payment" button InvoiceIsAlreadyValidated=Invoice is already validated NoLinesToBill=No lines to bill CustomReceipt=Custom Receipt @@ -94,12 +94,12 @@ TakeposConnectorMethodDescription=External module with extra features. Posibilit PrintMethod=Print method ReceiptPrinterMethodDescription=Powerful method with a lot of parameters. Full customizable with templates. Cannot print from the cloud. ByTerminal=By terminal -TakeposNumpadUsePaymentIcon=Use payment icon on numpad +TakeposNumpadUsePaymentIcon=Use icon instead of text on payment buttons of numpad CashDeskRefNumberingModules=Numbering module for POS sales CashDeskGenericMaskCodes6 =
    {TN} tag is used to add the terminal number TakeposGroupSameProduct=Group same products lines StartAParallelSale=Start a new parallel sale -ControlCashOpening=Control cash box at opening pos +ControlCashOpening=Control cash box at opening POS CloseCashFence=Close cash fence CashReport=Cash report MainPrinterToUse=Main printer to use @@ -117,3 +117,7 @@ HideCategoryImages=Hide Category Images HideProductImages=Hide Product Images NumberOfLinesToShow=Number of lines of images to show DefineTablePlan=Define tables plan +GiftReceiptButton=Add a "Gift receipt" button +GiftReceipt=Gift receipt +ModuleReceiptPrinterMustBeEnabled=Module Receipt printer must have been enabled first +AllowDelayedPayment=Allow delayed payment diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index f46307a21ae..62f028b45e4 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -240,6 +240,8 @@ ErrorBatchNoFoundEnoughQuantityForProductInWarehouse=No enough quantity for this ErrorOnlyOneFieldForGroupByIsPossible=Only 1 field for the 'Group by' is possible (others are discarded) ErrorTooManyDifferentValueForSelectedGroupBy=Found too many different value (more than %s) for the field '%s', so we can't use it as a 'Group by' for graphics. The field 'Group By' has been removed. May be you wanted to use it as an X-Axis ? ErrorReplaceStringEmpty=Error, the string to replace into is empty +ErrorProductNeedBatchNumber=Error, product '%s' need a lot/serial number +ErrorProductDoesNotNeedBatchNumber=Error, product '%s' does not accept a lot/serial number # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. WarningPasswordSetWithNoAccount=A password was set for this member. However, no user account was created. So this password is stored but can't be used to login to Dolibarr. It may be used by an external module/interface but if you don't need to define any login nor password for a member, you can disable option "Manage a login for each member" from Member module setup. If you need to manage a login but don't need any password, you can keep this field empty to avoid this warning. Note: Email can also be used as a login if the member is linked to a user. diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 2f673ea445b..1466b6389a9 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -355,8 +355,8 @@ PriceUTTC=U.P. (inc. tax) Amount=Amount AmountInvoice=Invoice amount AmountInvoiced=Amount invoiced -AmountInvoicedHT=Amount invoiced (incl. tax) -AmountInvoicedTTC=Amount invoiced (excl. tax) +AmountInvoicedHT=Amount invoiced (excl. tax) +AmountInvoicedTTC=Amount invoiced (inc. tax) AmountPayment=Payment amount AmountHTShort=Amount (excl.) AmountTTCShort=Amount (inc. tax) @@ -688,6 +688,7 @@ Method=Method Receive=Receive CompleteOrNoMoreReceptionExpected=Complete or nothing more expected ExpectedValue=Expected Value +ExpectedQty=Expected Qty PartialWoman=Partial TotalWoman=Total NeverReceived=Never received @@ -944,6 +945,39 @@ ShortThursday=T ShortFriday=F ShortSaturday=S ShortSunday=S +one=one +two=two +three=three +four=four +five=five +six=six +seven=seven +eight=eight +nine=nine +ten=ten +eleven=eleven +twelve=twelve +thirteen=thirdteen +fourteen=fourteen +fifteen=fifteen +sixteen=sixteen +seventeen=seventeen +eighteen=eighteen +nineteen=nineteen +twenty=twenty +thirty=thirty +forty=forty +fifty=fifty +sixty=sixty +seventy=seventy +eighty=eighty +ninety=ninety +hundred=hundred +thousand=thousand +million=million +billion=billion +trillion=trillion +quadrillion=quadrillion SelectMailModel=Select an email template SetRef=Set ref Select2ResultFoundUseArrows=Some results found. Use arrows to select. @@ -1041,4 +1075,6 @@ SwitchInEditModeToAddTranslation=Switch in edit mode to add translations for thi NotUsedForThisCustomer=Not used for this customer AmountMustBePositive=Amount must be positive ByStatus=By status -InformationMessage=Information \ No newline at end of file +InformationMessage=Information +ASAP=As Soon As Possible + \ No newline at end of file diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index dd0a5bf49e2..5ef946ddf67 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -81,7 +81,7 @@ DeleteType=Delete VoteAllowed=Vote allowed Physical=Physical Moral=Moral -MorPhy=Moral/Physical +MorPhy=Nature Reenable=Reenable ResiliateMember=Terminate a member ConfirmResiliateMember=Are you sure you want to terminate this member? diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index 5dc70fa068f..4555d3a6bc5 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -280,7 +280,9 @@ LinesToImport=Lines to import MemoryUsage=Memory usage RequestDuration=Duration of request +ProductsPerPopularity=Products/Services by popularity PopuProp=Products/Services by popularity in Proposals PopuCom=Products/Services by popularity in Orders ProductStatistics=Products/Services Statistics NbOfQtyInOrders=Qty in orders +SelectTheTypeOfObjectToAnalyze=Select the type of object to analyze... diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 7f82db63178..b59aa2f7080 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -104,6 +104,7 @@ SetDefaultBarcodeType=Set barcode type BarcodeValue=Barcode value NoteNotVisibleOnBill=Note (not visible on invoices, proposals...) ServiceLimitedDuration=If product is a service with limited duration: +FillWithLastServiceDates=Fill with last service line dates MultiPricesAbility=Multiple price segments per product/service (each customer is in one price segment) MultiPricesNumPrices=Number of prices DefaultPriceType=Base of prices per default (with versus without tax) when adding new sale prices @@ -361,6 +362,9 @@ SelectCombination=Select combination ProductCombinationGenerator=Variants generator Features=Features PriceImpact=Price impact +ImpactOnPriceLevel=Impact on price level %s +ApplyToAllPriceImpactLevel= Apply to all levels +ApplyToAllPriceImpactLevelHelp=By clicking here you set the same price impact on all levels WeightImpact=Weight impact NewProductAttribute=New attribute NewProductAttributeValue=New attribute value diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index a068fe247fe..670fff06f03 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -211,9 +211,9 @@ ProjectNbProjectByMonth=No. of created projects by month ProjectNbTaskByMonth=No. of created tasks by month ProjectOppAmountOfProjectsByMonth=Amount of leads by month ProjectWeightedOppAmountOfProjectsByMonth=Weighted amount of leads by month -ProjectOpenedProjectByOppStatus=Open project/lead by lead status -ProjectsStatistics=Statistics on projects/leads -TasksStatistics=Statistics on project/lead tasks +ProjectOpenedProjectByOppStatus=Open project|lead by lead status +ProjectsStatistics=Statistics on projects or leads +TasksStatistics=Statistics on tasks of projects or leads TaskAssignedToEnterTime=Task assigned. Entering time on this task should be possible. IdTaskTime=Id task time YouCanCompleteRef=If you want to complete the ref with some suffix, it is recommanded to add a - character to separate it, so the automatic numbering will still work correctly for next projects. For example %s-MYSUFFIX diff --git a/htdocs/langs/en_US/recruitment.lang b/htdocs/langs/en_US/recruitment.lang index de5f96fe082..b4a7abbe825 100644 --- a/htdocs/langs/en_US/recruitment.lang +++ b/htdocs/langs/en_US/recruitment.lang @@ -27,8 +27,10 @@ ModuleRecruitmentDesc = Manage and follow recruitment campaigns for new job posi # RecruitmentSetup = Recruitment setup Settings = Settings -RecruitmentSetupPage = Recruitment setup page +RecruitmentSetupPage = Enter here the setup of main options for the recruitment module RecruitmentArea=Recruitement area +PublicInterfaceRecruitmentDesc=Public interface is public URLs to show and answer to open jobs. There is one different link for each open job. +EnablePublicRecruitmentPages=Enable public recruitment pages # # About page @@ -43,8 +45,13 @@ DateExpected=Expected date FutureManager=Future manager ResponsibleOfRecruitement=Responsible of recruitment IfJobIsLocatedAtAPartner=If job is located at a partner place -PositionToBeFilled=Position to be filled -PositionsToBeFilled=Positions to be filled -ListOfPositionsToBeFilled=List of positions to be filled -NewPositionToBeFilled=New position to be filled +PositionToBeFilled=Job offer to be filled +PositionsToBeFilled=Job offers to be filled +ListOfPositionsToBeFilled=List of job offers to be filled +NewPositionToBeFilled=New job offers to be filled +JobOfferToBeFilled=Job offer to be filled +ThisIsInformationOnJobPosition=Information of the job position to be filled +ContactForRecruitment=Contact for recruitment +EmailRecruiter=Email recruiter +ToUseAGenericEmail=To use a generic email. If not defined, the email of the responsible of recruitment will be used \ No newline at end of file diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 994eae20e04..ce128bc5c91 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -236,4 +236,7 @@ ForceTo=Force to AlwaysShowFullArbo=Display full tree of warehouse on popup of warehouse links (Warning: This may decrease dramatically performances) StockAtDatePastDesc=You can view here the stock (real stock) at a given date in the past StockAtDateFutureDesc=You can view here the stock (virtual stock) at a given date in future -CurrentStock=Current stock \ No newline at end of file +CurrentStock=Current stock +InventoryRealQtyHelp=Set value to 0 to reset qty
    Keep field empty, or remove line, to keep unchanged +UpdateByScaningProductBarcode=Update by scaning product barcode +UpdateByScaningLot=Update by scaning lot diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index aea757e4a15..37ad1c0fc0d 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -117,3 +117,4 @@ ForceUserHolidayValidator=Force leave request validator ValidatorIsSupervisorByDefault=By default, the validator is the supervisor of the user. Keep empty to keep this behaviour. UserPersonalEmail=Personal email UserPersonalMobile=Personal mobile phone +WarningNotLangOfInterface=Warning, this is the main language the user speak, not the language of the interface he choosed to see. To change the interface language visible by this user, go on tab %s \ No newline at end of file diff --git a/htdocs/langs/en_US/withdrawals.lang b/htdocs/langs/en_US/withdrawals.lang index 841a9c2d480..553e3ac0eaa 100644 --- a/htdocs/langs/en_US/withdrawals.lang +++ b/htdocs/langs/en_US/withdrawals.lang @@ -63,7 +63,9 @@ InvoiceRefused=Invoice refused (Charge the rejection to customer) StatusDebitCredit=Status debit/credit StatusWaiting=Waiting StatusTrans=Sent +StatusDebited=Debited StatusCredited=Credited +StatusPaid=Paid StatusRefused=Refused StatusMotif0=Unspecified StatusMotif1=Insufficient funds @@ -77,13 +79,13 @@ StatusMotif8=Other reason CreateForSepaFRST=Create direct debit file (SEPA FRST) CreateForSepaRCUR=Create direct debit file (SEPA RCUR) CreateAll=Create direct debit file (all) -CreateFileForPaymentByBankTransfer=Create credit transfer (all) +CreateFileForPaymentByBankTransfer=Create file for credit transfer CreateSepaFileForPaymentByBankTransfer=Create credit transfer file (SEPA) CreateGuichet=Only office CreateBanque=Only bank OrderWaiting=Waiting for treatment -NotifyTransmision=Withdrawal Transmission -NotifyCredit=Withdrawal Credit +NotifyTransmision=Record file transmission of order +NotifyCredit=Record credit of order NumeroNationalEmetter=National Transmitter Number WithBankUsingRIB=For bank accounts using RIB WithBankUsingBANBIC=For bank accounts using IBAN/BIC/SWIFT @@ -95,7 +97,8 @@ ShowWithdraw=Show Direct Debit Order IfInvoiceNeedOnWithdrawPaymentWontBeClosed=However, if invoice has at least one direct debit payment order not yet processed, it won't be set as paid to allow prior withdrawal management. DoStandingOrdersBeforePayments=This tab allows you to request a direct debit payment order. Once done, go into menu Bank->Payment by direct debit to generate and manage the direct debit order. When direct debit order is closed, payment on invoices will be automatically recorded, and invoices closed if remainder to pay is null. DoCreditTransferBeforePayments=This tab allows you to request a credit transfer order. Once done, go into menu Bank->Payment by credit transfer to generate and manage the credit transfer order. When credit transfer order is closed, payment on invoices will be automatically recorded, and invoices closed if remainder to pay is null. -WithdrawalFile=Withdrawal file +WithdrawalFile=Debit order file +CreditTransferFile=Credit transfer file SetToStatusSent=Set to status "File Sent" ThisWillAlsoAddPaymentOnInvoice=This will also record payments on invoices and will classify them as "Paid" if remain to pay is null StatisticsByLineStatus=Statistics by status of lines @@ -121,6 +124,7 @@ SEPAFrstOrRecur=Type of payment ModeRECUR=Recurring payment ModeFRST=One-off payment PleaseCheckOne=Please check one only +CreditTransferOrderCreated=Credit transfer order %s created DirectDebitOrderCreated=Direct debit order %s created AmountRequested=Amount requested SEPARCUR=SEPA CUR @@ -141,3 +145,4 @@ InfoTransData=Amount: %s
    Method: %s
    Date: %s InfoRejectSubject=Direct debit payment order refused InfoRejectMessage=Hello,

    the direct debit payment order of invoice %s related to the company %s, with an amount of %s has been refused by the bank.

    --
    %s ModeWarning=Option for real mode was not set, we stop after this simulation +ErrorCompanyHasDuplicateDefaultBAN=Company with id %s has more than one default bank account. No way to know wich one to use. \ No newline at end of file diff --git a/htdocs/langs/es_AR/main.lang b/htdocs/langs/es_AR/main.lang index 7f068578411..6bcf44704f7 100644 --- a/htdocs/langs/es_AR/main.lang +++ b/htdocs/langs/es_AR/main.lang @@ -22,7 +22,6 @@ FormatDateHourText=%B %d, %Y, %I:%M %p DatabaseConnection=Conexión de base de datos NoTemplateDefined=No hay plantilla para este tipo de email AvailableVariables=Variables disponibles de substitución -EmptySearchString=Enter non empty search criterias NoRecordFound=Sin registros NoRecordDeleted=Sin registros eliminados NotEnoughDataYet=Sin datos suficientes diff --git a/htdocs/langs/es_BO/main.lang b/htdocs/langs/es_BO/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/es_BO/main.lang +++ b/htdocs/langs/es_BO/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_CL/main.lang b/htdocs/langs/es_CL/main.lang index 0c12ed62b34..e6342fa3f44 100644 --- a/htdocs/langs/es_CL/main.lang +++ b/htdocs/langs/es_CL/main.lang @@ -22,7 +22,6 @@ FormatDateHourText=%d %B %Y %H:%M DatabaseConnection=Conexión a la base NoTemplateDefined=No hay plantilla disponible para este tipo de correo electrónico AvailableVariables=Variables de sustitución disponibles -EmptySearchString=Enter non empty search criterias NoRecordFound=Ningún record fue encontrado NoRecordDeleted=No se eliminó ningún registro NoError=No hay error diff --git a/htdocs/langs/es_CL/stocks.lang b/htdocs/langs/es_CL/stocks.lang index ffd436fb51a..ba63c7f81bf 100644 --- a/htdocs/langs/es_CL/stocks.lang +++ b/htdocs/langs/es_CL/stocks.lang @@ -66,7 +66,6 @@ IdWarehouse=Id almacén LieuWareHouse=Almacén de localización WarehousesAndProductsBatchDetail=Almacenes y productos (con detalle por lote / serie) AverageUnitPricePMPShort=Precio de entrada promedio ponderado -AverageUnitPricePMP=Precio de entrada promedio ponderado SellPriceMin=Precio unitario de venta EstimatedStockValueSellShort=Valor para la venta EstimatedStockValueSell=Valor para la venta diff --git a/htdocs/langs/es_CO/main.lang b/htdocs/langs/es_CO/main.lang index 038f333d9ea..8db201ad380 100644 --- a/htdocs/langs/es_CO/main.lang +++ b/htdocs/langs/es_CO/main.lang @@ -21,7 +21,6 @@ FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M NoTemplateDefined=No hay plantilla disponible para este tipo de correo electrónico. AvailableVariables=Variables de sustitución disponibles -EmptySearchString=Enter non empty search criterias NoRecordFound=No se encontraron registros NoRecordDeleted=Ningún registro eliminado Errors=Los errores diff --git a/htdocs/langs/es_DO/main.lang b/htdocs/langs/es_DO/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/es_DO/main.lang +++ b/htdocs/langs/es_DO/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_EC/main.lang b/htdocs/langs/es_EC/main.lang index 2dd7a66de05..3227c745a02 100644 --- a/htdocs/langs/es_EC/main.lang +++ b/htdocs/langs/es_EC/main.lang @@ -22,7 +22,6 @@ FormatDateHourText=%d %B %Y %H:%M DatabaseConnection=Conexión con la base de datos NoTemplateDefined=No hay plantilla disponible para este tipo de correo electrónico AvailableVariables=Variables de sustitución disponibles -EmptySearchString=Enter non empty search criterias NoRecordFound=Ningún registro encontrado NoRecordDeleted=Ningún registro eliminado NoError=No hay error diff --git a/htdocs/langs/es_EC/stocks.lang b/htdocs/langs/es_EC/stocks.lang index 88ed5a7e742..c8f3a1758af 100644 --- a/htdocs/langs/es_EC/stocks.lang +++ b/htdocs/langs/es_EC/stocks.lang @@ -72,7 +72,6 @@ DescWareHouse=Descripción de almacén LieuWareHouse=Almacén de localización WarehousesAndProductsBatchDetail=Almacenes y productos (con detalle por lote / serie) AverageUnitPricePMPShort=Precio medio ponderado de los insumos -AverageUnitPricePMP=Precio medio ponderado de los insumos SellPriceMin=Precio unitario de venta EstimatedStockValueSellShort=Valor para la venta EstimatedStockValueSell=Valor para la venta diff --git a/htdocs/langs/es_GT/main.lang b/htdocs/langs/es_GT/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/es_GT/main.lang +++ b/htdocs/langs/es_GT/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_HN/main.lang b/htdocs/langs/es_HN/main.lang index 7579f1f4693..0d6b013ca18 100644 --- a/htdocs/langs/es_HN/main.lang +++ b/htdocs/langs/es_HN/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_MX/main.lang b/htdocs/langs/es_MX/main.lang index 7405807c6c8..1b7e397c375 100644 --- a/htdocs/langs/es_MX/main.lang +++ b/htdocs/langs/es_MX/main.lang @@ -20,7 +20,6 @@ FormatDateHourSecShort=%I:%M:%S %p %d/%m/%Y FormatDateHourTextShort=%I:%M %p, %d %b %Y FormatDateHourText=%I:%M %p, %d %B %Y AvailableVariables=Variables de sustitución disponibles -EmptySearchString=Enter non empty search criterias NoRecordFound=Ningún registro fue encontrado NoError=No hay error ErrorFieldFormat=El campo '%s' contiene un valor incorrecto diff --git a/htdocs/langs/es_PA/main.lang b/htdocs/langs/es_PA/main.lang index bcdd3f914eb..1602d6a7ffa 100644 --- a/htdocs/langs/es_PA/main.lang +++ b/htdocs/langs/es_PA/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_PE/main.lang b/htdocs/langs/es_PE/main.lang index 7140f0a388b..aa60b7d10cc 100644 --- a/htdocs/langs/es_PE/main.lang +++ b/htdocs/langs/es_PE/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias NoError=Sin error ErrorNoVATRateDefinedForSellerCountry=Error, no hay tipos de IGV definidos para el país '%s'. NotClosed=No se ha cerrado diff --git a/htdocs/langs/es_PY/main.lang b/htdocs/langs/es_PY/main.lang index bcdd3f914eb..1602d6a7ffa 100644 --- a/htdocs/langs/es_PY/main.lang +++ b/htdocs/langs/es_PY/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_US/main.lang b/htdocs/langs/es_US/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/es_US/main.lang +++ b/htdocs/langs/es_US/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_UY/main.lang b/htdocs/langs/es_UY/main.lang index bcdd3f914eb..1602d6a7ffa 100644 --- a/htdocs/langs/es_UY/main.lang +++ b/htdocs/langs/es_UY/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/es_VE/main.lang b/htdocs/langs/es_VE/main.lang index 1785d537814..1de75d20c42 100644 --- a/htdocs/langs/es_VE/main.lang +++ b/htdocs/langs/es_VE/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias DateEnd=Fecha finalización AmountLT1ES=Importe de retención AmountLT2ES=Importe ISLR diff --git a/htdocs/langs/fr_BE/admin.lang b/htdocs/langs/fr_BE/admin.lang index 3d058e6b61d..5d24a311ccd 100644 --- a/htdocs/langs/fr_BE/admin.lang +++ b/htdocs/langs/fr_BE/admin.lang @@ -14,7 +14,6 @@ WarningModuleNotActive=Le module %s doit être activé WarningOnlyPermissionOfActivatedModules=Seules les permissions liées à des modules activés sont montrées ici. Vous pouvez activer d'autres modules sur la page Accueil->Configuration->Modules. FormToTestFileUploadForm=Formulaire pour tester l'upload de fichiers (selon la configuration) IfModuleEnabled=Note: oui ne fonctionne que si le module %s est activé -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. Module20Name=Propales Module30Name=Factures Target=Objectif diff --git a/htdocs/langs/fr_BE/main.lang b/htdocs/langs/fr_BE/main.lang index e425c275844..3042af1642f 100644 --- a/htdocs/langs/fr_BE/main.lang +++ b/htdocs/langs/fr_BE/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d/%m/%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias Update=Mise à jour DateStart=Date de début DateEnd=Date de fin diff --git a/htdocs/langs/fr_BE/website.lang b/htdocs/langs/fr_BE/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/fr_BE/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/fr_CA/admin.lang b/htdocs/langs/fr_CA/admin.lang index 09df3da74ad..88e376626be 100644 --- a/htdocs/langs/fr_CA/admin.lang +++ b/htdocs/langs/fr_CA/admin.lang @@ -39,7 +39,6 @@ CompatibleAfterUpdate=Ce module nécessite une mise à jour de votre Dolibarr %s SeeInMarkerPlace=Voir dans Market place Updated=Mis à jour AchatTelechargement=Acheter / Télécharger -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. DevelopYourModuleDesc=Quelques solutions pour développer votre propre module ... InstrucToEncodePass=Pour chiffrer le mot de passe de la base dans le fichier de configuration conf.php, remplacer la ligne
    $dolibarr_main_db_pass="...";
    par
    $dolibarr_main_db_pass="crypted:%s"; InstrucToClearPass=Pour avoir le mot de passe de la base décodé (en clair) dans le fichier de configuration conf.php, remplacer dans ce fichier la ligne
    $dolibarr_main_db_pass="crypted:..."
    par
    $dolibarr_main_db_pass="%s" diff --git a/htdocs/langs/fr_CA/main.lang b/htdocs/langs/fr_CA/main.lang index 0da76b0aab2..6914f73c3a7 100644 --- a/htdocs/langs/fr_CA/main.lang +++ b/htdocs/langs/fr_CA/main.lang @@ -20,7 +20,6 @@ FormatDateHourSecShort=%d/%m/%Y %H:%M:%S FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M DatabaseConnection=Connexion à la base de donnée -EmptySearchString=Enter non empty search criterias ErrorCanNotCreateDir=Impossible de créer le dir %s ErrorCanNotReadDir=Impossible de lire le dir %s ErrorNoSocialContributionForSellerCountry=Erreur, aucun type de charges défini pour le pays '%s'. diff --git a/htdocs/langs/fr_CA/stocks.lang b/htdocs/langs/fr_CA/stocks.lang index 8c85ddc91fd..b94830980a7 100644 --- a/htdocs/langs/fr_CA/stocks.lang +++ b/htdocs/langs/fr_CA/stocks.lang @@ -36,7 +36,6 @@ IdWarehouse=Id entrepôt LieuWareHouse=Entrepôt de localisation WarehousesAndProductsBatchDetail=Entrepôts et produits (avec détail par lot / série) AverageUnitPricePMPShort=Prix ​​moyen pondéré des intrants -AverageUnitPricePMP=Prix ​​moyen pondéré des intrants SellPriceMin=Prix ​​unitaire de vente EstimatedStockValueSellShort=Valeur à vendre EstimatedStockValueSell=Valeur à vendre diff --git a/htdocs/langs/fr_CA/website.lang b/htdocs/langs/fr_CA/website.lang index f6c1b71c174..5255b2f9da5 100644 --- a/htdocs/langs/fr_CA/website.lang +++ b/htdocs/langs/fr_CA/website.lang @@ -7,4 +7,3 @@ EditMenu=Menu Edition ViewSiteInNewTab=Afficher le site dans un nouvel onglet ViewPageInNewTab=Afficher la page dans un nouvel onglet ViewWebsiteInProduction=Afficher le site Web à l'aide d'URL d'accueil -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/fr_CH/admin.lang b/htdocs/langs/fr_CH/admin.lang index bdc794e1b31..c1d306ec390 100644 --- a/htdocs/langs/fr_CH/admin.lang +++ b/htdocs/langs/fr_CH/admin.lang @@ -1,4 +1,3 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OperationParamDesc=Define the values to use for the object of the action, or how to extract values. For example:
    objproperty1=SET:the value to set
    objproperty2=SET:a value with replacement of __objproperty1__
    objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
    objproperty4=EXTRACT:HEADER:X-Myheaderkey:\\s*([^\\s]*)
    options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
    object.objproperty5=EXTRACT:BODY:My company name is\\s([^\\s]*)

    Use a ; char as separator to extract or set several properties. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\\s([^\\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/langs/fr_CH/main.lang b/htdocs/langs/fr_CH/main.lang index 75d787bb95c..65f49b2ef5e 100644 --- a/htdocs/langs/fr_CH/main.lang +++ b/htdocs/langs/fr_CH/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%d/%m/%Y %I:%M %p FormatDateHourSecShort=%d/%m/%Y %I:%M:%S %p FormatDateHourTextShort=%d %b %Y, %I:%M %p FormatDateHourText=%d %B %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/fr_CH/website.lang b/htdocs/langs/fr_CH/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/fr_CH/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/fr_CI/admin.lang b/htdocs/langs/fr_CI/admin.lang index bdc794e1b31..c1d306ec390 100644 --- a/htdocs/langs/fr_CI/admin.lang +++ b/htdocs/langs/fr_CI/admin.lang @@ -1,4 +1,3 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OperationParamDesc=Define the values to use for the object of the action, or how to extract values. For example:
    objproperty1=SET:the value to set
    objproperty2=SET:a value with replacement of __objproperty1__
    objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
    objproperty4=EXTRACT:HEADER:X-Myheaderkey:\\s*([^\\s]*)
    options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
    object.objproperty5=EXTRACT:BODY:My company name is\\s([^\\s]*)

    Use a ; char as separator to extract or set several properties. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\\s([^\\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/langs/fr_CI/main.lang b/htdocs/langs/fr_CI/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/fr_CI/main.lang +++ b/htdocs/langs/fr_CI/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/fr_CI/website.lang b/htdocs/langs/fr_CI/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/fr_CI/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/fr_CM/admin.lang b/htdocs/langs/fr_CM/admin.lang index bdc794e1b31..c1d306ec390 100644 --- a/htdocs/langs/fr_CM/admin.lang +++ b/htdocs/langs/fr_CM/admin.lang @@ -1,4 +1,3 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OperationParamDesc=Define the values to use for the object of the action, or how to extract values. For example:
    objproperty1=SET:the value to set
    objproperty2=SET:a value with replacement of __objproperty1__
    objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
    objproperty4=EXTRACT:HEADER:X-Myheaderkey:\\s*([^\\s]*)
    options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
    object.objproperty5=EXTRACT:BODY:My company name is\\s([^\\s]*)

    Use a ; char as separator to extract or set several properties. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\\s([^\\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/langs/fr_CM/main.lang b/htdocs/langs/fr_CM/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/fr_CM/main.lang +++ b/htdocs/langs/fr_CM/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/fr_CM/website.lang b/htdocs/langs/fr_CM/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/fr_CM/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index c4025fb1577..236b4c61bd9 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -300,8 +300,9 @@ MAIN_MAIL_DEFAULT_FROMTYPE=Expéditeur par défaut des e-mails pour les envois m UserEmail=Email utilisateur CompanyEmail=Email organization FeatureNotAvailableOnLinux=Fonctionnalité non disponible sous systèmes Unix. Tester votre sendmail localement. +FixOnTransifex=Corriger la traduction sur la plate-forme en ligne de traduction du projet SubmitTranslation=Si la traduction de cette langue est incomplète ou si vous trouvez des erreurs, vous pouvez corriger cela en éditant les fichiers dans le répertoire langs/%s et soumettre vos changements sur www.transifex.com/dolibarr-association/dolibarr/ -SubmitTranslationENUS=Si la traduction pour cette langue est incomplète ou si vous trouvez des erreurs, vous pouvez les corriger en éditant les fichiers dans le répertoire langs/%s et soumettre les modifications sur le forum dolibarr.org/forum ou pour les développeurs sur github.com/Dolibarr/dolibarr. +SubmitTranslationENUS=Si la traduction pour cette langue est incomplète ou si vous trouvez des erreurs, vous pouvez les corriger en éditant les fichiers dans le dossier langs/%s et soumettre les fichiers modifiés sur le forum dolibarr.org/forum ou, pour les développeurs, via une PR sur github.com/Dolibarr/dolibarr ModuleSetup=Configuration du module ModulesSetup=Configuration Modules/Application ModuleFamilyBase=Système @@ -387,7 +388,7 @@ SecurityToken=Clé de sécurisation des URLs NoSmsEngine=Aucun gestionnaire d'envoi de SMS n'est disponible. Les gestionnaires d'envois SMS ne sont pas installés en standard, car dépendent d'un fournisseur externe, mais vous pourrez en trouver depuis la plateforme %s PDF=PDF PDFDesc=Options globales sur la génération des PDF -PDFAddressForging=Règles de fabrication des zones adresses +PDFAddressForging=Règles pour le contenu des sections Adresse HideAnyVATInformationOnPDF=Masquer toutes les informations relatives à la Taxe de vente / TVA sur les PDF générés PDFRulesForSalesTax=Règles pour la taxe de vente / TVA PDFLocaltax=Règles pour %s @@ -947,7 +948,8 @@ Permission63003=Supprimer les ressources Permission63004=Lier les ressources aux événements de l'agenda DictionaryCompanyType=Type de Tiers DictionaryCompanyJuridicalType=Formes juridiques des Tiers -DictionaryProspectLevel=Niveau de potentiel des prospects +DictionaryProspectLevel=Niveau de potentiel des prospects pour les tiers +DictionaryProspectContactLevel=Niveau de potentiel des prospects pour les contacts DictionaryCanton=Etats/Province DictionaryRegion=Régions DictionaryCountry=Pays @@ -977,7 +979,8 @@ DictionaryEMailTemplates=Modèles des courriels DictionaryUnits=Unités DictionaryMeasuringUnits=Unités de mesure DictionarySocialNetworks=Réseaux sociaux -DictionaryProspectStatus=Statut prospect +DictionaryProspectStatus=Statuts de prospection des tiers +DictionaryProspectContactStatus=Statuts de prospection des contacts DictionaryHolidayTypes=Type de congés DictionaryOpportunityStatus=Statut d'opportunités pour les affaires/projets DictionaryExpenseTaxCat=Note de frais - catégories de déplacement @@ -1240,6 +1243,7 @@ WarningAtLeastKeyOrTranslationRequired=Un critère de recherche est nécessaire NewTranslationStringToShow=Nouvelle traduction à afficher OriginalValueWas=La traduction d'origine est écrasée. La valeur initiale était:

    %s TransKeyWithoutOriginalValue=Vous avez forcé une nouvelle traduction pour la clé de traduction '%s' qui n'existe dans aucun fichier de langue +TitleNumberOfActivatedModules=Modules activés TotalNumberOfActivatedModules=Modules activés : %s / %s YouMustEnableOneModule=Vous devez activer au moins une fonctionnalité ClassNotFoundIntoPathWarning=La classe %s n'a pas été trouvée dans le chemin PHP @@ -1686,8 +1690,8 @@ AGENDA_SHOW_LINKED_OBJECT=Afficher l'objet lié dans la vue agenda ##### Clicktodial ##### ClickToDialSetup=Configuration du module Click To Dial ClickToDialUrlDesc=URL appelée quand un clic sur l'icône téléphone est fait. Dans l'URL, vous pouvez utiliser les tags
    __PHONETO__ qui sera remplacée par le numéro de téléphone de la personne à appeler
    __PHONEFROM__ qui sera remplacée par le numéro de l'appelant (vous)
    __LOGIN__ qui sera remplacée par l'identifiant d'accès de l'utilisateur à l'application d'appel (à définir sur la fiche utilisateur) et
    __PASS__ qui sera remplacée par le mot de passe d'accès de l'utilisateur à l'application d'appel (également à définir sur la fiche utilisateur). -ClickToDialDesc=Ce module permet de rendre les numéros de téléphone cliquables. Un clic sur cette icône appellera votre téléphone à composer le numéro de téléphone. Cela peut être utilisé pour appeler un système de centre d'appels de Dolibarr qui peut appeler le numéro de téléphone d'un système SIP, par exemple. -ClickToDialUseTelLink=Utiliser un lien «Tel.» sur les numéros de téléphone +ClickToDialDesc=Ce module permet de rendre les numéros de téléphone cliquables lorsque vous utilisez l'application sur un ordinateur de bureau. Un clic sur cette icône composera le numéro de téléphone. Cela peut être utilisé pour commencer une conversation avec un soft phone sur votre bureau ou lorsque vous utilisez un système basé sur le protocole SIP par exemple. Note: Sur un smartphone, les numéros de téléphones sont toujours clicables. +ClickToDialUseTelLink=Utiliser un lien "tel:" sur les numéros de téléphone ClickToDialUseTelLinkDesc=Utilisez cette méthode si vos utilisateurs ont un softphone ou une interface de logiciel installé sur un même ordinateur que le navigateur, et a appelé lorsque vous cliquez sur un lien dans votre navigateur qui commencent par "tel:". Si vous avez besoin d'une solution de serveur complet (pas besoin d'installation locale du logiciel), vous devez définir ceci à "Non" et remplir le champ suivant. ##### Point Of Sale (CashDesk) ##### CashDesk=Point de Vente @@ -1817,6 +1821,7 @@ EnterAnyCode=Ce champ contient une référence pour identifier le champ. Entrez Enter0or1=Saisir 0 ou 1  UnicodeCurrency=Saisissez ici entre accolades, la liste du numéro des octets qui représentent le symbole de la monnaie. Pour exemple: pour $, entrez [36] - pour le Real Brésilien R$ [82,36] - pour l'euro €, entrez [8364] ColorFormat=La couleur RVB au format HEX est, par exemple: FF0000 +PictoHelp=Nom de l'icone au format dolibarr ('image.png' si mise dans le répertoire du thème actuel, 'image.png@nom_du_module' si mise dans le repertoire /img/ d'un module) PositionIntoComboList=Position de la ligne dans des listes déroulantes SellTaxRate=Taux de TVA RecuperableOnly=Oui pour une TVA "Non Perçue mais Récupérable" dédiée à certains pays comme la France. Gardez la valeur à "Non" dans tous les autres cas. @@ -1881,7 +1886,7 @@ UrlToGetKeyToUseAPIs=Url pour obtenir le jeton pour utiliser l'API (une fois le ListOfAvailableAPIs=Liste des APIs disponibles activateModuleDependNotSatisfied=Le module "%s" dépend du module "%s" qui est manquant, aussi le module "%1$s" peut ne pas fonctionner correctement. Merci d'installer le module "%2$s" ou désactiver le module "%1$s" si vous ne souhaitez pas avoir de mauvaise surprise CommandIsNotInsideAllowedCommands=La commande que vous essayez d'exécuter ne figure pas dans la liste des commandes autorisées définies dans le paramètre $dolibarr_main_restrict_os_commands du fichier conf.php . -LandingPage=Page cible +LandingPage=Page d'accueil SamePriceAlsoForSharedCompanies=Si vous utilisez un module multi-société, avec le choix «prix unique», le prix sera aussi le même pour toutes les sociétés si les produits sont partagés entre les environnements ModuleEnabledAdminMustCheckRights=Le module a été activé. Les permissions pour le(s) module(s) activé(s) ont été donnés aux utilisateurs admin uniquement. Vous devrez peut-être accorder des autorisations aux autres utilisateurs ou groupes manuellement si nécessaire. UserHasNoPermissions=Cet utilisateur n'a pas de permission définie @@ -1894,6 +1899,7 @@ MAIN_PDF_MARGIN_LEFT=Marge gauche sur les PDF MAIN_PDF_MARGIN_RIGHT=Marge droite sur les PDF MAIN_PDF_MARGIN_TOP=Marge haute sur les PDF MAIN_PDF_MARGIN_BOTTOM=Marge bas sur les PDF +MAIN_DOCUMENTS_LOGO_HEIGHT=Hauteur du logo sur les PDFs NothingToSetup=Aucune configuration particulière n'est requise pour ce module. SetToYesIfGroupIsComputationOfOtherGroups=Réglez ceci sur Oui si ce groupe est un calcul d'autres groupes EnterCalculationRuleIfPreviousFieldIsYes=Entrez la règle de calcul si le champ précédent a été défini sur Oui (par exemple, 'CODEGRP1 + CODEGRP2') diff --git a/htdocs/langs/fr_FR/agenda.lang b/htdocs/langs/fr_FR/agenda.lang index 2e0ac6e5ed1..6da45f7976d 100644 --- a/htdocs/langs/fr_FR/agenda.lang +++ b/htdocs/langs/fr_FR/agenda.lang @@ -14,7 +14,7 @@ EventsNb=Nombre d'événements ListOfActions=Liste des événements EventReports=Rapport des évènements Location=Lieu -ToUserOfGroup=à tout utilisateur du groupe +ToUserOfGroup=Assigné à tout utilisateur du groupe EventOnFullDay=Événement sur la(les) journée(s) MenuToDoActions=Événements incomplets MenuDoneActions=Événements terminés @@ -121,10 +121,10 @@ MRP_MO_CANCELInDolibarr=OF annulé AgendaModelModule=Modèle de document pour les événements DateActionStart=Date de début DateActionEnd=Date de fin -AgendaUrlOptions1=Vous pouvez aussi ajouter les paramètres suivants pour filtrer les réponses : +AgendaUrlOptions1=Vous pouvez aussi ajouter les paramètres suivants pour filtrer les réponses : AgendaUrlOptions3=logina=%s pour limiter l'export aux actions dont l'utilisateur %s est propriétaire. -AgendaUrlOptionsNotAdmin=logina=!%s pour limiter l'export aux actions non assignées à l'utilisateur %s. -AgendaUrlOptions4=logint=%s pour limiter l'export aux actions assignées à l'utilisateur %s (propriétaire et autres). +AgendaUrlOptionsNotAdmin=logina=!%s pour limiter l'export aux actions n'appartenant pas à l'utilisateur %s. +AgendaUrlOptions4=logint=%spour limiter l'export aux actions assignées à l'utilisateur %s (propriétaire et autres). AgendaUrlOptionsProject=project=__PROJECT_ID__ pour restreindre aux événements associés au projet __PROJECT_ID__. AgendaUrlOptionsNotAutoEvent=notactiontype=systemauto pour exclure les événements automatiques. AgendaUrlOptionsIncludeHolidays=includeholidays=1 pour inclure les événements de type congé. diff --git a/htdocs/langs/fr_FR/cashdesk.lang b/htdocs/langs/fr_FR/cashdesk.lang index 8ed5994e3f3..2ab64973e1a 100644 --- a/htdocs/langs/fr_FR/cashdesk.lang +++ b/htdocs/langs/fr_FR/cashdesk.lang @@ -115,5 +115,5 @@ ScanToOrder=Scannez le code QR pour commander Appearance=Apparence HideCategoryImages=Masquer les images de catégorie HideProductImages=Masquer les images de produits -NumberOfLinesToShow=Nombre de lignes d'image à afficher +NumberOfLinesToShow=Nombre de lignes d'images à afficher DefineTablePlan=Définir le plan des tables diff --git a/htdocs/langs/fr_FR/compta.lang b/htdocs/langs/fr_FR/compta.lang index 6245901d321..bc79d32d709 100644 --- a/htdocs/langs/fr_FR/compta.lang +++ b/htdocs/langs/fr_FR/compta.lang @@ -69,6 +69,7 @@ SocialContribution=Charge sociale ou fiscale SocialContributions=Charges fiscales ou sociales SocialContributionsDeductibles=Charge ou taxe déductible SocialContributionsNondeductibles=Charge ou taxe non déductible +DateOfSocialContribution=Date de la charge fiscale ou sociale LabelContrib=Libellé de la dépense TypeContrib=Type de la charge MenuSpecialExpenses=Dépenses spéciales diff --git a/htdocs/langs/fr_FR/contracts.lang b/htdocs/langs/fr_FR/contracts.lang index f2910a8e76e..1d6a99378d3 100644 --- a/htdocs/langs/fr_FR/contracts.lang +++ b/htdocs/langs/fr_FR/contracts.lang @@ -99,6 +99,6 @@ TypeContact_contrat_internal_SALESREPFOLL=Commercial suivi du contrat TypeContact_contrat_external_BILLING=Contact client facturation contrat TypeContact_contrat_external_CUSTOMER=Contact client suivi contrat TypeContact_contrat_external_SALESREPSIGN=Contact client signataire contrat -HideClosedServiceByDefault=Cacher les services fermés sur les contrats par défaut +HideClosedServiceByDefault=Masquer les services fermés par défaut ShowClosedServices=Afficher les services fermés -HideClosedServices=Cacher les services fermés +HideClosedServices=Masquer les services fermés diff --git a/htdocs/langs/fr_FR/errors.lang b/htdocs/langs/fr_FR/errors.lang index 5bfcd36ce0b..4080466f427 100644 --- a/htdocs/langs/fr_FR/errors.lang +++ b/htdocs/langs/fr_FR/errors.lang @@ -136,7 +136,8 @@ ErrorNewValueCantMatchOldValue=La nouvelle valeur ne peut être égale à l'anci ErrorFailedToValidatePasswordReset=Echec de la réinitialisation du mot de passe. Il est possible que ce lien ait déjà été utilisé (l'utilisation de ce lien ne fonctionne qu'une fois). Si ce n'est pas le cas, essayez de recommencer le processus de réinitialisation de mot de passe depuis le début. ErrorToConnectToMysqlCheckInstance=Echec de la connection au serveur de base de données. Vérifier que votre serveur est bien lancé (par exemple, avec MySQL/MariaDB, vous pouvez le lancer depuis la ligne de commande avec 'sudo service mysql start'). ErrorFailedToAddContact=Echec à l'ajout du contact -ErrorDateMustBeBeforeToday=La date ne peut pas être supérieure à aujourd'hui +ErrorDateMustBeBeforeToday=La date doit être inférieure à la date courante +ErrorDateMustBeInFuture=La date doit être postérieure à la date courante ErrorPaymentModeDefinedToWithoutSetup=Un mode de paiement a été défini de type %s mais la configuration du module Facture n'a pas été complétée pour définir les informations affichées pour ce mode de paiement. ErrorPHPNeedModule=Erreur, votre PHP doit avoir le module %s installé pour utiliser cette fonctionnalité. ErrorOpenIDSetupNotComplete=Vous avez configuré Dolibarr pour accepter l'authentication OpenID, mais l'URL du service OpenID n'est pas défini dans la constante %s diff --git a/htdocs/langs/fr_FR/languages.lang b/htdocs/langs/fr_FR/languages.lang index 9da1ef41151..9a980afffe8 100644 --- a/htdocs/langs/fr_FR/languages.lang +++ b/htdocs/langs/fr_FR/languages.lang @@ -1,8 +1,11 @@ # Dolibarr language file - Source file is en_US - languages +Language_am_ET=Ethiopien Language_ar_AR=Arabe Language_ar_EG=Arabe (Egypte) Language_ar_SA=Arabe +Language_az_AZ=Azerbaïdjanais Language_bn_BD=Bengalais +Language_bn_IN=Bengali (Inde) Language_bg_BG=Bulgare Language_bs_BA=Bosniaque Language_ca_ES=Catalan @@ -20,6 +23,7 @@ Language_en_GB=Anglais (Royaume-Uni) Language_en_IN=Anglais (Inde) Language_en_NZ=Anglais (Nouvelle Zeland) Language_en_SA=Anglais (Arabie Saoudite) +Language_en_SG=Anglais (Singapour) Language_en_US=Anglais (Etats-Unis) Language_en_ZA=Anglais (Afrique du Sud) Language_es_ES=Espagnol @@ -29,6 +33,7 @@ Language_es_CL=Espagnol (Chili) Language_es_CO=Espagnol (Colombie) Language_es_DO=Espagnol (République dominicaine) Language_es_EC=Espagnol (Équateur) +Language_es_GT=Espagnol (Guatemala) Language_es_HN=Espagnol (Honduras) Language_es_MX=Espagnol (Mexique) Language_es_PA=Espagnol (Panama) @@ -36,6 +41,7 @@ Language_es_PY=Espagnol (Paraguay) Language_es_PE=Espagnol (Peru) Language_es_PR=Espagnol (Puerto Rico) Language_es_UY=Espagnol (Uruguay) +Language_es_GT=Espagnol (Guatemala) Language_es_VE=Espagnol (Venezuela) Language_et_EE=Estonien Language_eu_ES=Basque @@ -44,15 +50,21 @@ Language_fi_FI=Finlandais Language_fr_BE=Français (Belgique) Language_fr_CA=Français (Canada) Language_fr_CH=Français (Suisse) +Language_fr_CI=Français (Cote d'Ivoire) +Language_fr_CM=Français (Cameroun) Language_fr_FR=Français +Language_fr_GA=Français (Gabon) Language_fr_NC=Français (Nouvelle Calédonie) Language_fy_NL=Frisian +Language_gl_ES=Galicien Language_he_IL=Hébreux +Language_hi_IN=Hindi (Inde) Language_hr_HR=Croate Language_hu_HU=Hongrois Language_id_ID=Indonésien Language_is_IS=Islandais Language_it_IT=Italien +Language_it_CH=Italien (Suisse) Language_ja_JP=Japonais Language_ka_GE=Géorgien Language_km_KH=Khmer @@ -64,8 +76,9 @@ Language_lv_LV=Léton Language_mk_MK=Macédonien Language_mn_MN=Mongol Language_nb_NO=Norvégien (Bokmal) +Language_ne_NP=Népalais Language_nl_BE=Néerlandais (Belgique) -Language_nl_NL=Dutch +Language_nl_NL=Néerlandais Language_pl_PL=Polonais Language_pt_BR=Portugais (Brésil) Language_pt_PT=Portugais @@ -86,4 +99,5 @@ Language_uz_UZ=Ouzbek Language_vi_VN=Vietnamien Language_zh_CN=Chinois Language_zh_TW=Chinois (Traditionel) +Language_zh_HK=Chinois (Hong-Kong) Language_bh_MY=Malais diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 670a486345c..1d5dd9bc6cb 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -355,8 +355,8 @@ PriceUTTC=P.U TTC Amount=Montant AmountInvoice=Montant facture AmountInvoiced=Montant facturé -AmountInvoicedHT=Montant facturé (TTC) -AmountInvoicedTTC=Montant facturé (HT) +AmountInvoicedHT=Montant facturé (HT) +AmountInvoicedTTC=Montant facturé (TTC) AmountPayment=Montant paiement AmountHTShort=Montant HT AmountTTCShort=Montant TTC @@ -485,6 +485,7 @@ Categories=Tags/catégories Category=Tag/catégorie By=Par From=Du +FromDate=A partir du FromLocation=A partir du to=au To=au @@ -703,6 +704,7 @@ MenuECM=Documents MenuAWStats=AWStats MenuMembers=Adhérents MenuAgendaGoogle=Agenda Google +MenuTaxesAndSpecialExpenses=Charges | Dépenses spéciales ThisLimitIsDefinedInSetup=Limite Dolibarr (Menu accueil-configuration-sécurité): %s Ko, Limite PHP: %s Ko NoFileFound=Pas de documents stockés dans cette rubrique CurrentUserLanguage=Langue utilisateur actuelle @@ -1039,3 +1041,6 @@ SwitchInEditModeToAddTranslation=Passer en mode édition pour ajouter des traduc NotUsedForThisCustomer=Non utilisé pour ce client AmountMustBePositive=Le montant doit être positif. ByStatus=Par statut +InformationMessage=Information +ASAP=Dès que possible + diff --git a/htdocs/langs/fr_FR/other.lang b/htdocs/langs/fr_FR/other.lang index 09c378008f3..bd75f6c9035 100644 --- a/htdocs/langs/fr_FR/other.lang +++ b/htdocs/langs/fr_FR/other.lang @@ -280,7 +280,9 @@ LinesToImport=Lignes à importer MemoryUsage=Utilisation de la mémoire RequestDuration=Durée de la demande +ProductsPerPopularity=Produits / services par popularité PopuProp=Produits / services par popularité dans les propositions PopuCom=Produits/services par popularité dans les commandes ProductStatistics=Statistiques sur les produits / services NbOfQtyInOrders=Qté en commandes +SelectTheTypeOfObjectToAnalyze=Sélectionnez le type d'objet à analyser ... diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index 8366e029c2f..09c470552e5 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -169,6 +169,8 @@ SuppliersPricesOfProductsOrServices=Prix fournisseurs (des produits ou services) CustomCode=Nomenclature douanière / Code SH CountryOrigin=Pays d'origine Nature=Nature du produit (matière première / produit fini) +NatureOfProductShort=Nature de produit +NatureOfProductDesc=Matière première ou produit fini ShortLabel=Libellé court Unit=Unité p=u. diff --git a/htdocs/langs/fr_FR/projects.lang b/htdocs/langs/fr_FR/projects.lang index c521a0a965a..fda884c6203 100644 --- a/htdocs/langs/fr_FR/projects.lang +++ b/htdocs/langs/fr_FR/projects.lang @@ -178,6 +178,7 @@ TypeContact_project_task_internal_TASKCONTRIBUTOR=Contributeur TypeContact_project_task_external_TASKCONTRIBUTOR=Contributeur SelectElement=Séléctionnez l'élément AddElement=Associer l'élément +LinkToElementShort=Lier à # Documents models DocumentModelBeluga=Modèle de document project pour l'aperçu des objets liées DocumentModelBaleine=Modèles de document de rapport de tâches de projets diff --git a/htdocs/langs/fr_FR/recruitment.lang b/htdocs/langs/fr_FR/recruitment.lang new file mode 100644 index 00000000000..d95d76cd421 --- /dev/null +++ b/htdocs/langs/fr_FR/recruitment.lang @@ -0,0 +1,54 @@ +# Copyright (C) 2020 Laurent Destailleur +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# Generic +# + +# Module label 'ModuleRecruitmentName' +ModuleRecruitmentName = Recrutement +# Module description 'ModuleRecruitmentDesc' +ModuleRecruitmentDesc = Gestion et suivi des campagnes de recrutement + +# +# Admin page +# +RecruitmentSetup = Paramétrages du recrutement +Settings = Paramétrages +RecruitmentSetupPage = Entrez ici la configuration des principales options du module de recrutement +RecruitmentArea=Espace recrutement +PublicInterfaceRecruitmentDesc=L'interface publique est une URL publique pour afficher et répondre aux postes en cours de recrutement. Il existe un lien différent pour chaque poste. +EnablePublicRecruitmentPages=Activer les pages de recrutement publiques + +# +# About page +# +About = À propos +RecruitmentAbout = À propos du module Recrutement +RecruitmentAboutPage = À propos du module Recrutement +NbOfEmployeesExpected=Nombre de postes disponibles +JobLabel=Intitulé du poste +WorkPlace=Poste de travail +DateExpected=Date souhaitée +FutureManager=Responsable futur +ResponsibleOfRecruitement=Responsable du recrutement +IfJobIsLocatedAtAPartner=Si le poste est localisé chez un partenaire +PositionToBeFilled=Poste à pourvoir +PositionsToBeFilled=Postes à pourvoir +ListOfPositionsToBeFilled=Liste des postes à pourvoir +NewPositionToBeFilled=Nouveau poste à pourvoir + +JobOfferToBeFilled=Poste à pourvoir +ThisIsInformationOnJobPosition=Informations sur le poste à pourvoir diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index fa44e8e1172..dc1428b6e19 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -95,14 +95,16 @@ RealStock=Stock réel RealStockDesc=Le stock physique ou réel est le stock présent dans les entrepôts. RealStockWillAutomaticallyWhen=Le stock réel sera modifié selon ces règles (voir la configuration du module Stock) : VirtualStock=Stock virtuel -VirtualStockDesc=Le stock virtuel est la quantité de produit en stock après que les opération affectant les stock sont terminées (réceptions de commandes fournisseurs, expéditions de commandes clients,...) +VirtualStockAtDate=Stock virtuel à date +VirtualStockAtDateDesc=Stock virtuel une fois que toutes les commandes en attente qui doivent être effectuées avant la date seront terminées +VirtualStockDesc=Le stock virtuel est la quantité de produit en stock après que les opérations en cours (et qui affectent les stocks) soient terminées (réceptions de commandes fournisseurs, expéditions de commandes clients, production des ordres de fabrications, etc) IdWarehouse=Identifiant entrepôt DescWareHouse=Description entrepôt LieuWareHouse=Lieu entrepôt WarehousesAndProducts=Entrepôts et produits WarehousesAndProductsBatchDetail=Entrepôts et produits (avec détail par lot/série) AverageUnitPricePMPShort=Prix moyen pondéré (PMP) -AverageUnitPricePMP=Prix moyen pondéré (PMP) d'acquisition +AverageUnitPricePMPDesc=Le prix unitaire moyen d'entrée que nous avons dû payer aux fournisseurs pour intégrer le produit dans notre stock. SellPriceMin=Prix de vente unitaire EstimatedStockValueSellShort=Valeur à la vente EstimatedStockValueSell=Valeur vente @@ -141,7 +143,7 @@ Replenishments=Réapprovisionnement NbOfProductBeforePeriod=Quantité du produit %s en stock avant la période sélectionnée (< %s) NbOfProductAfterPeriod=Quantité du produit %s en stock après la période sélectionnée (> %s) MassMovement=Mouvement en masse -SelectProductInAndOutWareHouse=Sélectionner un produit, une quantité à transférer, un entrepôt source et destination et cliquer sur "%s". Une fois tous les mouvements choisis, cliquer sur "%s". +SelectProductInAndOutWareHouse=Sélectionner un entrepôt source et destination, un produit et une quantité à transférer, puis cliquer sur "%s". Une fois tous les mouvements choisis, cliquer sur "%s". RecordMovement=Enregistrer transfert ReceivingForSameOrder=Réceptions pour cette commande StockMovementRecorded=Mouvement de stocks enregistré diff --git a/htdocs/langs/fr_FR/suppliers.lang b/htdocs/langs/fr_FR/suppliers.lang index 81860c25a45..2b4ab9dcf70 100644 --- a/htdocs/langs/fr_FR/suppliers.lang +++ b/htdocs/langs/fr_FR/suppliers.lang @@ -1,4 +1,4 @@ -# Dolibarr language file - Source file is en_US - suppliers +# Dolibarr language file - Source file is en_US - vendors Suppliers=Fournisseurs SuppliersInvoice=Facture fournisseur ShowSupplierInvoice=Montrer la facture fournisseur @@ -15,7 +15,7 @@ SomeSubProductHaveNoPrices=Certains sous-produits n'ont pas de prix définis AddSupplierPrice=Ajouter un prix d'achat ChangeSupplierPrice=Modifier un prix d'achat SupplierPrices=Prix fournisseurs -ReferenceSupplierIsAlreadyAssociatedWithAProduct=Cette référence fournisseur est déjà associée à la référence : %s +ReferenceSupplierIsAlreadyAssociatedWithAProduct=Cette référence fournisseur est déjà associée à un produit : %s NoRecordedSuppliers=Pas de fournisseur enregistré SupplierPayment=Paiement fournisseur SuppliersArea=Espace fournisseurs diff --git a/htdocs/langs/fr_FR/users.lang b/htdocs/langs/fr_FR/users.lang index 1ed6c956e66..5e951464dff 100644 --- a/htdocs/langs/fr_FR/users.lang +++ b/htdocs/langs/fr_FR/users.lang @@ -108,6 +108,7 @@ DisabledInMonoUserMode=Désactivé en mode maintenance UserAccountancyCode=Code comptable de l'utilisateur UserLogoff=Déconnexion de l'utilisateur UserLogged=Utilisateur connecté +DateOfEmployment=Date d'embauche DateEmployment=Date d'embauche DateEmploymentEnd=Date de fin d'emploi CantDisableYourself=Vous ne pouvez pas désactiver votre propre compte utilisateur diff --git a/htdocs/langs/fr_FR/withdrawals.lang b/htdocs/langs/fr_FR/withdrawals.lang index 446de9e09d3..6cb4796acd6 100644 --- a/htdocs/langs/fr_FR/withdrawals.lang +++ b/htdocs/langs/fr_FR/withdrawals.lang @@ -10,7 +10,7 @@ PaymentByBankTransferReceipts=Ordres de virement bancaire PaymentByBankTransferLines=Lignes d'ordre de virement bancaire WithdrawalsReceipts=Bons de prélèvements WithdrawalReceipt=Bon de prélèvement -BankTransferReceipts=Ordres de virement +BankTransferReceipts=Ordres de virement bancaire BankTransferReceipt=Ordre de virement LatestBankTransferReceipts=Les %s derniers ordres de virement bancaire LastWithdrawalReceipts=Les %s derniers bons de prélèvements @@ -77,12 +77,12 @@ StatusMotif8=Autre motif CreateForSepaFRST=Créer fichier de prélèvement (SEPA FRST) CreateForSepaRCUR=Créer fichier de prélèvement (SEPA RCUR) CreateAll=Créer le fichier de prélèvement (tout) -CreateFileForPaymentByBankTransfer=Créer un virement (tout) +CreateFileForPaymentByBankTransfer=Créer un fichier de virement CreateSepaFileForPaymentByBankTransfer=Créer un fichier de virement (SEPA) CreateGuichet=Seulement guichet CreateBanque=Seulement banque OrderWaiting=En attente de traitement -NotifyTransmision=Transmission du bon +NotifyTransmision=Transmission du fichier NotifyCredit=Crédit du bon NumeroNationalEmetter=Numéro National Émetteur WithBankUsingRIB=Pour les comptes bancaires utilisant le RIB @@ -93,9 +93,10 @@ CreditDate=Crédité le WithdrawalFileNotCapable=Impossible de générer le fichier de reçu des prélèvement pour votre pays %s (Votre pays n'est pas supporté) ShowWithdraw=Afficher ordre de prélèvement IfInvoiceNeedOnWithdrawPaymentWontBeClosed=Toutefois, si la facture a au moins une demande de prélèvement non traité, elle ne sera pas classée payée afin de permettre le prélèvement d'abord. -DoStandingOrdersBeforePayments=Cet onglet vous permet de demander un prélèvement. Une fois la demande faite, allez dans le menu Banque->Paiement par prélèvement pour gérer l'ordre de prélèvement. Lorsque l'ordre de paiement est clos, le paiement sur la facture sera automatiquement enregistrée, et la facture fermée si le reste à payer est nul. -DoCreditTransferBeforePayments=Cet onglet vous permet de demander un ordre de virement. Une fois fait, allez dans le menu Banque -> Paiements par virement pour gérer l'ordre de virement. Lorsque le virement est clôturé, le paiement des factures sera automatiquement enregistré et les factures clôturées si le solde à payer est nul. +DoStandingOrdersBeforePayments=Cet onglet vous permet de demander un prélèvement. Une fois la demande faite, allez dans le menu Banque->Paiement par prélèvement pour générer l'ordre de prélèvement. Lorsque l'ordre de paiement est clos, le paiement sur les factures seront automatiquement enregistrés, et les factures fermées si le reste à payer est nul. +DoCreditTransferBeforePayments=Cet onglet vous permet de demander un ordre de virement. Une fois fait, allez dans le menu Banque ->Paiements par virement pour gérer l'ordre de virement. Lorsque le virement est clôturé, le paiement des factures fournisseurs sera automatiquement enregistré et les factures clôturées si le solde à payer est nul. WithdrawalFile=Fichier de prélèvement +CreditTransferFile=Fichier de virement SetToStatusSent=Mettre au statut "Fichier envoyé" ThisWillAlsoAddPaymentOnInvoice=Cette action enregistrera aussi les règlements des factures et les classera au statut "Payé" si le solde est nul StatisticsByLineStatus=Statistiques par statut des lignes @@ -121,6 +122,7 @@ SEPAFrstOrRecur=Type de paiement ModeRECUR=Payment récurrent ModeFRST=Paiement unitaire PleaseCheckOne=Cocher un choix uniquement +CreditTransferOrderCreated=Ordre de virement %s créé DirectDebitOrderCreated=Ordre de prélèvement %s créé AmountRequested=Montant réclamé SEPARCUR=SEPA RCUR diff --git a/htdocs/langs/fr_GA/admin.lang b/htdocs/langs/fr_GA/admin.lang index bdc794e1b31..c1d306ec390 100644 --- a/htdocs/langs/fr_GA/admin.lang +++ b/htdocs/langs/fr_GA/admin.lang @@ -1,4 +1,3 @@ # Dolibarr language file - Source file is en_US - admin -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. OperationParamDesc=Define the values to use for the object of the action, or how to extract values. For example:
    objproperty1=SET:the value to set
    objproperty2=SET:a value with replacement of __objproperty1__
    objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
    objproperty4=EXTRACT:HEADER:X-Myheaderkey:\\s*([^\\s]*)
    options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
    object.objproperty5=EXTRACT:BODY:My company name is\\s([^\\s]*)

    Use a ; char as separator to extract or set several properties. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\\s([^\\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/langs/fr_GA/main.lang b/htdocs/langs/fr_GA/main.lang index 0f9be27b22f..2e691473326 100644 --- a/htdocs/langs/fr_GA/main.lang +++ b/htdocs/langs/fr_GA/main.lang @@ -19,4 +19,3 @@ FormatDateHourShort=%m/%d/%Y %I:%M %p FormatDateHourSecShort=%m/%d/%Y %I:%M:%S %p FormatDateHourTextShort=%b %d, %Y, %I:%M %p FormatDateHourText=%B %d, %Y, %I:%M %p -EmptySearchString=Enter non empty search criterias diff --git a/htdocs/langs/fr_GA/website.lang b/htdocs/langs/fr_GA/website.lang deleted file mode 100644 index ff992a2be9e..00000000000 --- a/htdocs/langs/fr_GA/website.lang +++ /dev/null @@ -1,2 +0,0 @@ -# Dolibarr language file - Source file is en_US - website -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/nl_BE/admin.lang b/htdocs/langs/nl_BE/admin.lang index 009d9292997..0b0d5b0e10f 100644 --- a/htdocs/langs/nl_BE/admin.lang +++ b/htdocs/langs/nl_BE/admin.lang @@ -67,7 +67,6 @@ SeeInMarkerPlace=Zie Marktplaats AchatTelechargement=Kopen / Downloaden GoModuleSetupArea=Ga naar het gedeelte Module-instellingen om een nieuwe module te implementeren / installeren: %s . DoliStoreDesc=DoliStore, de officiële markt voor externe Dolibarr ERP / CRM modules -DoliPartnersDesc=List of companies providing custom-developed modules or features.
    Note: since Dolibarr is an open source application, anyone experienced in PHP programming should be able to develop a module. WebSiteDesc=Externe websites voor meer add-on (niet-basis) modules ... BoxesActivated=Geactiveerde widgets DoNotStoreClearPassword=Versleutel wachtwoorden opgeslagen in database (NIET als platte tekst). Het wordt sterk aanbevolen om deze optie te activeren. diff --git a/htdocs/langs/nl_BE/main.lang b/htdocs/langs/nl_BE/main.lang index 34b534324fb..05ff5191d8f 100644 --- a/htdocs/langs/nl_BE/main.lang +++ b/htdocs/langs/nl_BE/main.lang @@ -19,7 +19,6 @@ FormatDateHourShort=%d-%m-%Y %H:%M FormatDateHourSecShort=%d/%m/%Y %I:%M:%S %p FormatDateHourTextShort=%d %b %Y %H:%M FormatDateHourText=%d %B %Y %H:%M -EmptySearchString=Enter non empty search criterias NoRecordFound=Geen record gevonden ErrorCanNotCreateDir=Kan dir %s niet maken ErrorCanNotReadDir=Kan dir %s niet lezen diff --git a/htdocs/langs/nl_BE/website.lang b/htdocs/langs/nl_BE/website.lang index 05a97bd129a..e8f0a2d4af0 100644 --- a/htdocs/langs/nl_BE/website.lang +++ b/htdocs/langs/nl_BE/website.lang @@ -7,4 +7,3 @@ ViewSiteInNewTab=Bekijk de site in een nieuwe tab ViewPageInNewTab=Bekijk de pagina in een nieuwe tab SetAsHomePage=Zet als Homepagina ViewWebsiteInProduction=Bekijk website via de home URL's -YouTryToAccessToAFileThatIsNotAWebsitePage=You try to access to a page that is not available.
    (ref=%s, type=%s, status=%s) diff --git a/htdocs/langs/pt_BR/stocks.lang b/htdocs/langs/pt_BR/stocks.lang index a04e49809f8..3315b8f6924 100644 --- a/htdocs/langs/pt_BR/stocks.lang +++ b/htdocs/langs/pt_BR/stocks.lang @@ -54,7 +54,6 @@ DescWareHouse=Descrição do armazém LieuWareHouse=Localização do armazenamento WarehousesAndProducts=Armazenamento de produtos AverageUnitPricePMPShort=Preço médio de entrada -AverageUnitPricePMP=Preço médio de entrada SellPriceMin=Venda Preço unitário EstimatedStockValueSellShort=Valor para venda EstimatedStockValueSell=Valor para venda diff --git a/htdocs/livraison/class/livraison.class.php b/htdocs/livraison/class/livraison.class.php index 6199bc4ec88..7baf41ee51e 100644 --- a/htdocs/livraison/class/livraison.class.php +++ b/htdocs/livraison/class/livraison.class.php @@ -314,6 +314,7 @@ class Livraison extends CommonObject $this->note = $obj->note_private; //TODO deprecated $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->origin = $obj->origin; // May be 'shipping' $this->origin_id = $obj->origin_id; // May be id of shipping @@ -880,6 +881,8 @@ class Livraison extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; $sql .= " AND tosell = 1"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -1035,6 +1038,7 @@ class Livraison extends CommonObject global $conf, $user, $langs; $langs->load("deliveries"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'typhon'; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1084c07f755..90db6718a3b 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -644,6 +644,11 @@ if (!defined('NOLOGIN')) if (GETPOST('lang', 'aZ09')) $paramsurl[] = 'lang='.GETPOST('lang', 'aZ09'); header('Location: '.DOL_URL_ROOT.'/index.php'.(count($paramsurl) ? '?'.implode('&', $paramsurl) : '')); exit; + } else { + // User is loaded, we may need to change language for him according to its choice + if (! empty($user->conf->MAIN_LANG_DEFAULT)) { + $langs->setDefaultLang($user->conf->MAIN_LANG_DEFAULT); + } } } else { // We are already into an authenticated session @@ -850,13 +855,13 @@ if (GETPOST('theme', 'alpha')) } // Set javascript option -if (!GETPOST('nojs', 'int')) // If javascript was not disabled on URL -{ - if (!empty($user->conf->MAIN_DISABLE_JAVASCRIPT)) - { +if (GETPOST('nojs', 'int')) { // If javascript was not disabled on URL + $conf->use_javascript_ajax = 0; +} else { + if (!empty($user->conf->MAIN_DISABLE_JAVASCRIPT)) { $conf->use_javascript_ajax = !$user->conf->MAIN_DISABLE_JAVASCRIPT; } -} else $conf->use_javascript_ajax = 0; +} // Set MAIN_OPTIMIZEFORTEXTBROWSER for user (must be after login part) if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && !empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) { @@ -1233,6 +1238,7 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr if (GETPOSTISSET('dol_optimize_smallscreen')) { $themeparam .= '&dol_optimize_smallscreen='.GETPOST('dol_optimize_smallscreen', 'int'); } if (GETPOSTISSET('dol_no_mouse_hover')) { $themeparam .= '&dol_no_mouse_hover='.GETPOST('dol_no_mouse_hover', 'int'); } if (GETPOSTISSET('dol_use_jmobile')) { $themeparam .= '&dol_use_jmobile='.GETPOST('dol_use_jmobile', 'int'); $conf->dol_use_jmobile = GETPOST('dol_use_jmobile', 'int'); } + if (GETPOSTISSET('THEME_DARKMODEENABLED')) { $themeparam .= '&THEME_DARKMODEENABLED='.GETPOST('THEME_DARKMODEENABLED', 'int'); } if (GETPOSTISSET('THEME_SATURATE_RATIO')) { $themeparam .= '&THEME_SATURATE_RATIO='.GETPOST('THEME_SATURATE_RATIO', 'int'); } if (!defined('DISABLE_JQUERY') && !$disablejs && $conf->use_javascript_ajax) diff --git a/htdocs/modulebuilder/admin/setup.php b/htdocs/modulebuilder/admin/setup.php index 1b260396e6b..f7613f8ef0b 100644 --- a/htdocs/modulebuilder/admin/setup.php +++ b/htdocs/modulebuilder/admin/setup.php @@ -114,7 +114,7 @@ print "\n"; if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - // What is use cas of this 2 options ? + // What is use case of this 2 options ? print ''; print ''.$langs->trans("UseAboutPage").''; @@ -123,9 +123,9 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) print ajax_constantonoff('MODULEBUILDER_USE_ABOUT'); } else { if (empty($conf->global->MODULEBUILDER_USE_ABOUT)) { - print ''.img_picto($langs->trans("Disabled"), 'off').''; + print ''.img_picto($langs->trans("Disabled"), 'off').''; } else { - print ''.img_picto($langs->trans("Enabled"), 'on').''; + print ''.img_picto($langs->trans("Enabled"), 'on').''; } } print ''; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index df9e58e9b31..eb350eb9a3a 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -95,6 +95,85 @@ $result = restrictedArea($user, 'modulebuilder', null); $error = 0; +// Define $listofmodules +$dirsrootforscan = array($dirread); +// Add also the core modules into the list of modules to show/edit +if ($dirread != DOL_DOCUMENT_ROOT && ($conf->global->MAIN_FEATURES_LEVEL >= 2 || !empty($conf->global->MODULEBUILDER_ADD_DOCUMENT_ROOT))) { $dirsrootforscan[] = DOL_DOCUMENT_ROOT; } + +// Search modules to edit +$textforlistofdirs = ''."\n"; +$listofmodules = array(); +$i = 0; +foreach ($dirsrootforscan as $dirread) +{ + $moduletype = 'external'; + if ($dirread == DOL_DOCUMENT_ROOT) { + $moduletype = 'internal'; + } + + $dirsincustom = dol_dir_list($dirread, 'directories'); + if (is_array($dirsincustom) && count($dirsincustom) > 0) { + foreach ($dirsincustom as $dircustomcursor) { + $fullname = $dircustomcursor['fullname']; + if (dol_is_file($fullname.'/'.$FILEFLAG)) + { + // Get real name of module (MyModule instead of mymodule) + $dirtoscanrel = basename($fullname).'/core/modules/'; + + $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$'); + if (empty($descriptorfiles)) // If descriptor not found into module dir, we look into main module dir. + { + $dirtoscanrel = 'core/modules/'; + $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$'); + } + $modulenamewithcase = ''; + $moduledescriptorrelpath = ''; + $moduledescriptorfullpath = ''; + + foreach ($descriptorfiles as $descriptorcursor) { + $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']); + $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase); + $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name']; + $moduledescriptorfullpath = $descriptorcursor['fullname']; + //var_dump($descriptorcursor); + } + if ($modulenamewithcase) + { + $listofmodules[$dircustomcursor['name']] = array( + 'modulenamewithcase'=>$modulenamewithcase, + 'moduledescriptorrelpath'=> $moduledescriptorrelpath, + 'moduledescriptorfullpath'=>$moduledescriptorfullpath, + 'moduledescriptorrootpath'=>$dirread, + 'moduletype'=>$moduletype + ); + } + //var_dump($listofmodules); + } + } + } + + if ($forceddirread && empty($listofmodules)) // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir + { + $listofmodules[strtolower($module)] = array( + 'modulenamewithcase'=>$module, + 'moduledescriptorrelpath'=> 'notyetimplemented', + 'moduledescriptorfullpath'=> 'notyetimplemented', + 'moduledescriptorrootpath'=> 'notyetimplemented', + ); + } + + // Show description of content + $newdircustom = $dirins; + if (empty($newdircustom)) $newdircustom = img_warning(); + // If dirread was forced to somewhere else, by using URL + // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product + if (empty($i)) $textforlistofdirs .= $langs->trans("DirScanned").' : '; + else $textforlistofdirs .= ', '; + $textforlistofdirs .= ''.$dirread.''; + $i++; +} + + /* * Actions */ @@ -214,7 +293,6 @@ if ($dirins && $action == 'initmodule' && $modulename) } $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); - //var_dump($result); if ($result < 0) { @@ -769,6 +847,9 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { $objectname = ucfirst($objectname); + $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; + $moduletype = $listofmodules[strtolower($module)]['moduletype']; + if (preg_match('/[^a-z0-9_]/i', $objectname)) { $error++; @@ -1076,6 +1157,9 @@ if ($dirins && $action == 'addproperty' && !empty($module) && !empty($tabobj)) $objectname = $tabobj; + $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; + $moduletype = $listofmodules[strtolower($module)]['moduletype']; + $srcdir = $dirread.'/'.strtolower($module); $destdir = $dirins.'/'.strtolower($module); dol_mkdir($destdir); @@ -1125,7 +1209,9 @@ if ($dirins && $action == 'addproperty' && !empty($module) && !empty($tabobj)) // Edit the class file to write properties if (!$error) { - $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry); + $moduletype = 'external'; + + $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype); if (is_numeric($object) && $object <= 0) { $error++; @@ -1135,7 +1221,9 @@ if ($dirins && $action == 'addproperty' && !empty($module) && !empty($tabobj)) // Edit sql with new properties if (!$error) { - $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object); + $moduletype = 'external'; + + $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype); if ($result <= 0) { $error++; @@ -1477,79 +1565,11 @@ print load_fiche_titre($text, '', 'title_setup'); print ''.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
    '; -$dirsrootforscan = array($dirread); -// Add also the core modules into the list of modules to show/edit -if ($dirread != DOL_DOCUMENT_ROOT && ($conf->global->MAIN_FEATURES_LEVEL >= 2 || !empty($conf->global->MODULEBUILDER_ADD_DOCUMENT_ROOT))) { $dirsrootforscan[] = DOL_DOCUMENT_ROOT; } - -// Search modules to edit -print ''."\n"; -$listofmodules = array(); -$i = 0; -foreach ($dirsrootforscan as $dirread) -{ - $dirsincustom = dol_dir_list($dirread, 'directories'); - if (is_array($dirsincustom) && count($dirsincustom) > 0) { - foreach ($dirsincustom as $dircustomcursor) { - $fullname = $dircustomcursor['fullname']; - if (dol_is_file($fullname.'/'.$FILEFLAG)) - { - // Get real name of module (MyModule instead of mymodule) - $dirtoscanrel = basename($fullname).'/core/modules/'; - - $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$'); - if (empty($descriptorfiles)) // If descriptor not found into module dir, we look into main module dir. - { - $dirtoscanrel = 'core/modules/'; - $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$'); - } - $modulenamewithcase = ''; - $moduledescriptorrelpath = ''; - $moduledescriptorfullpath = ''; - - foreach ($descriptorfiles as $descriptorcursor) { - $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']); - $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase); - $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name']; - $moduledescriptorfullpath = $descriptorcursor['fullname']; - //var_dump($descriptorcursor); - } - if ($modulenamewithcase) - { - $listofmodules[$dircustomcursor['name']] = array( - 'modulenamewithcase'=>$modulenamewithcase, - 'moduledescriptorrelpath'=> $moduledescriptorrelpath, - 'moduledescriptorfullpath'=>$moduledescriptorfullpath, - 'moduledescriptorrootpath'=>$dirread - ); - } - //var_dump($listofmodules); - } - } - } - - if ($forceddirread && empty($listofmodules)) // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir - { - $listofmodules[strtolower($module)] = array( - 'modulenamewithcase'=>$module, - 'moduledescriptorrelpath'=> 'notyetimplemented', - 'moduledescriptorfullpath'=> 'notyetimplemented', - 'moduledescriptorrootpath'=> 'notyetimplemented', - ); - } - - // Show description of content - $newdircustom = $dirins; - if (empty($newdircustom)) $newdircustom = img_warning(); - // If dirread was forced to somewhere else, by using URL - // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product - if (empty($i)) print $langs->trans("DirScanned").' : '; - else print ', '; - print ''.$dirread.''; - $i++; -} +print $textforlistofdirs; print '
    '; //var_dump($listofmodules); + $message = ''; if (!$dirins) { @@ -1583,7 +1603,6 @@ $error = 0; $moduleobj = null; - if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') { $modulelowercase = strtolower($module); @@ -1835,6 +1854,8 @@ if ($module == 'initmodule') print '
    '; + // Note module is inside $dirread + if ($tab == 'description') { $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; @@ -1974,7 +1995,7 @@ if ($module == 'initmodule') print ''; print ''; - dol_fiche_head($head2, $tab, '', -1, ''); + dol_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix'); $doleditor = new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%', ''); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ?GETPOST('format', 'aZ09') : 'html')); @@ -1990,7 +2011,7 @@ if ($module == 'initmodule') print ''; } } else { - dol_fiche_head($head2, $tab, '', -1, ''); // Level 2 + dol_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix'); // Level 2 } if ($tab == 'languages') @@ -2315,29 +2336,31 @@ if ($module == 'initmodule') $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png'; $pathtoscript = strtolower($module).'/scripts/'.strtolower($tabobj).'.php'; - //var_dump($pathtolib); - $realpathtoclass = dol_buildpath($pathtoclass, 0, 2); - $realpathtoapi = dol_buildpath($pathtoapi, 0, 2); - $realpathtoagenda = dol_buildpath($pathtoagenda, 0, 2); - $realpathtocard = dol_buildpath($pathtocard, 0, 2); - $realpathtodocument = dol_buildpath($pathtodocument, 0, 2); - $realpathtolist = dol_buildpath($pathtolist, 0, 2); - $realpathtonote = dol_buildpath($pathtonote, 0, 2); - $realpathtophpunit = dol_buildpath($pathtophpunit, 0, 2); - $realpathtosql = dol_buildpath($pathtosql, 0, 2); - $realpathtosqlextra = dol_buildpath($pathtosqlextra, 0, 2); - $realpathtosqlkey = dol_buildpath($pathtosqlkey, 0, 2); - $realpathtosqlextrakey = dol_buildpath($pathtosqlextrakey, 0, 2); - $realpathtolib = dol_buildpath($pathtolib, 0, 2); - $realpathtoobjlib = dol_buildpath($pathtoobjlib, 0, 2); - $realpathtopicto = dol_buildpath($pathtopicto, 0, 2); - $realpathtoscript = dol_buildpath($pathtoscript, 0, 2); + //var_dump($pathtoclass); var_dump($dirread); + $realpathtoclass = $dirread.'/'.$pathtoclass; + $realpathtoapi = $dirread.'/'.$pathtoapi; + $realpathtoagenda = $dirread.'/'.$pathtoagenda; + $realpathtocard = $dirread.'/'.$pathtocard; + $realpathtodocument = $dirread.'/'.$pathtodocument; + $realpathtolist = $dirread.'/'.$pathtolist; + $realpathtonote = $dirread.'/'.$pathtonote; + $realpathtophpunit = $dirread.'/'.$pathtophpunit; + $realpathtosql = $dirread.'/'.$pathtosql; + $realpathtosqlextra = $dirread.'/'.$pathtosqlextra; + $realpathtosqlkey = $dirread.'/'.$pathtosqlkey; + $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey; + $realpathtolib = $dirread.'/'.$pathtolib; + $realpathtoobjlib = $dirread.'/'.$pathtoobjlib; + $realpathtopicto = $dirread.'/'.$pathtopicto; + $realpathtoscript = $dirread.'/'.$pathtoscript; if (empty($realpathtoapi)) // For compatibility with some old modules { $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'s.class.php'; - $realpathtoapi = dol_buildpath($pathtoapi, 0, 2); + $realpathtoapi = $dirread.'/'.$pathtoapi; } + $urloflist = $dirread.'/'.$pathtolist; + $urlofcard = $dirread.'/'.$pathtocard; print '
    '; print ' '.$langs->trans("ClassFile").' : '.($realpathtoclass ? '' : '').$pathtoclass.($realpathtoclass ? '' : '').''; @@ -2423,9 +2446,6 @@ if ($module == 'initmodule') print '
    '; print '
    '; - $urloflist = dol_buildpath($pathtolist, 1); - $urlofcard = dol_buildpath($pathtocard, 1); - print '
    '; print ' '.$langs->trans("PageForList").' : '.($realpathtolist ? '' : '').$pathtolist.($realpathtolist ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; @@ -2472,7 +2492,7 @@ if ($module == 'initmodule') if (function_exists('opcache_invalidate')) opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! - if (empty($forceddirread)) + if (empty($forceddirread) && empty($dirread)) { $result = dol_include_once($pathtoclass); } else { diff --git a/htdocs/modulebuilder/template/admin/myobject_extrafields.php b/htdocs/modulebuilder/template/admin/myobject_extrafields.php index 13a6e7b54c5..065feb6cebe 100644 --- a/htdocs/modulebuilder/template/admin/myobject_extrafields.php +++ b/htdocs/modulebuilder/template/admin/myobject_extrafields.php @@ -68,7 +68,7 @@ $linkback = 'trans("MyObjectExtraFields"), -1, 'account'); diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 9c3bbe0bec0..5a2e27e6bc6 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -310,7 +310,7 @@ class MyObject extends CommonObject foreach ($object->array_options as $key => $option) { $shortkey = preg_replace('/options_/', '', $key); - if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) { //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; unset($object->array_options[$key]); @@ -1060,11 +1060,29 @@ class MyObject extends CommonObject } } + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + /** * Class MyObjectLine. You can also remove this and generate a CRUD class for lines objects. */ -class MyObjectLine +class MyObjectLine extends CommonObjectLine { // To complete with content of an object MyObjectLine // We should have a field rowid, fk_myobject and position + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } } diff --git a/htdocs/modulebuilder/template/modulebuilder.txt b/htdocs/modulebuilder/template/modulebuilder.txt index 24ea0d6eac5..670a1774929 100644 --- a/htdocs/modulebuilder/template/modulebuilder.txt +++ b/htdocs/modulebuilder/template/modulebuilder.txt @@ -1,3 +1,3 @@ # DO NOT DELETE THIS FILE MANUALLY # File to flag module built using official module template. -# When this file is present into a module directory, you can edit it with the module builder tool. Use ModuleBuilder if you want to delete module. \ No newline at end of file +# When this file is present into a module directory, you can edit it with the module builder tool. \ No newline at end of file diff --git a/htdocs/modulebuilder/template/mymoduleindex.php b/htdocs/modulebuilder/template/mymoduleindex.php index 4a3356f1d7e..91eb5eca8da 100644 --- a/htdocs/modulebuilder/template/mymoduleindex.php +++ b/htdocs/modulebuilder/template/mymoduleindex.php @@ -106,7 +106,7 @@ if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) print ''; print ''; - print ''; + print ''; $var = true; if ($num > 0) @@ -117,22 +117,17 @@ if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) $obj = $db->fetch_object($resql); print ''; print ''; print ''; $i++; @@ -171,14 +166,12 @@ $max = 3; // Last modified myobject if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) { - $sql = "SELECT s.rowid, s.nom as name, s.client, s.datec, s.tms, s.canvas"; - $sql.= ", s.code_client"; - $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; - if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE s.client IN (1, 2, 3)"; - $sql.= " AND s.entity IN (".getEntity($companystatic->element).")"; - if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; - if ($socid) $sql.= " AND s.rowid = $socid"; + $sql = "SELECT s.rowid, s.ref, s.label, s.date_creation, s.tms"; + $sql.= " FROM ".MAIN_DB_PREFIX."mymodule_myobject as s"; + //if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE s.entity IN (".getEntity($myobjectstatic->element).")"; + //if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + //if ($socid) $sql.= " AND s.rowid = $socid"; $sql .= " ORDER BY s.tms DESC"; $sql .= $db->plimit($max, 0); @@ -191,9 +184,7 @@ if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) print '
    '.$langs->trans("DraftOrders").($num?''.$num.'':'').'
    '.$langs->trans("DraftMyObjects").($num?''.$num.'':'').'
    '; - $orderstatic->id=$obj->rowid; - $orderstatic->ref=$obj->ref; - $orderstatic->ref_client=$obj->ref_client; - $orderstatic->total_ht = $obj->total_ht; - $orderstatic->total_tva = $obj->total_tva; - $orderstatic->total_ttc = $obj->total_ttc; - print $orderstatic->getNomUrl(1); + + $myobjectstatic->id=$obj->rowid; + $myobjectstatic->ref=$obj->ref; + $myobjectstatic->ref_client=$obj->ref_client; + $myobjectstatic->total_ht = $obj->total_ht; + $myobjectstatic->total_tva = $obj->total_tva; + $myobjectstatic->total_ttc = $obj->total_ttc; + + print $myobjectstatic->getNomUrl(1); print ''; - $companystatic->id=$obj->socid; - $companystatic->name=$obj->name; - $companystatic->client=$obj->client; - $companystatic->code_client = $obj->code_client; - $companystatic->code_fournisseur = $obj->code_fournisseur; - $companystatic->canvas=$obj->canvas; - print $companystatic->getNomUrl(1,'customer',16); print ''.price($obj->total_ttc).'
    '; print ''; print ''; print ''; print ''; @@ -202,28 +193,23 @@ if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) while ($i < $num) { $objp = $db->fetch_object($resql); - $companystatic->id=$objp->rowid; - $companystatic->name=$objp->name; - $companystatic->client=$objp->client; - $companystatic->code_client = $objp->code_client; - $companystatic->code_fournisseur = $objp->code_fournisseur; - $companystatic->canvas=$objp->canvas; + + $myobjectstatic->id=$objp->rowid; + $myobjectstatic->ref=$objp->ref; + $myobjectstatic->label=$objp->label; + $myobjectstatic->status = $objp->status; + print ''; - print ''; + print ''; print '"; - print '"; + print '"; print ''; $i++; - - } $db->free($resql); - } - else - { + } else { print ''; } print "
    '; - if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastCustomersOrProspects",$max); - else if (! empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastModifiedProspects",$max); - else print $langs->trans("BoxTitleLastModifiedCustomers",$max); + print $langs->trans("BoxTitleLatestModifiedMyObjects", $max); print ''.$langs->trans("DateModificationShort").'
    '.$companystatic->getNomUrl(1,'customer',48).''.$myobjectstatic->getNomUrl(1).''; - print $companystatic->getLibCustProspStatut(); print "'.dol_print_date($db->jdate($objp->tms),'day')."'.dol_print_date($db->jdate($objp->tms), 'day')."
    '.$langs->trans("None").'

    "; diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 20d6588f3d6..a85f84a50ba 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -287,13 +287,11 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formconfirm = ''; // Confirmation to delete - if ($action == 'delete') - { + if ($action == 'delete') { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteMyObject'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); } // Confirmation to delete line - if ($action == 'deleteline') - { + if ($action == 'deleteline') { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); } // Clone confirmation @@ -345,19 +343,19 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (! empty($conf->projet->enabled)) { $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; + $morehtmlref .= '
    '.$langs->trans('Project') . ' '; if ($permissiontoadd) { //if ($action != 'classify') $morehtmlref.='
    ' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' '; - $morehtmlref.=' : '; + $morehtmlref .= ' : '; if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; + //$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
    '; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
    '; } else { $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); } @@ -470,27 +468,22 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Back to draft - if ($object->status == $object::STATUS_VALIDATED) - { - if ($permissiontoadd) - { + if ($object->status == $object::STATUS_VALIDATED) { + if ($permissiontoadd) { print ''.$langs->trans("SetToDraft").''; } } // Modify - if ($permissiontoadd) - { + if ($permissiontoadd) { print ''.$langs->trans("Modify").''."\n"; } else { print ''.$langs->trans('Modify').''."\n"; } // Validate - if ($object->status == $object::STATUS_DRAFT) - { - if ($permissiontoadd) - { + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) { print ''.$langs->trans("Validate").''; @@ -502,31 +495,24 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Clone - if ($permissiontoadd) - { + if ($permissiontoadd) { print ''.$langs->trans("ToClone").''."\n"; } /* if ($permissiontoadd) { - if ($object->status == $object::STATUS_ENABLED) - { + if ($object->status == $object::STATUS_ENABLED) { print ''.$langs->trans("Disable").''."\n"; - } - else - { + } else { print ''.$langs->trans("Enable").''."\n"; } } if ($permissiontoadd) { - if ($object->status == $object::STATUS_VALIDATED) - { + if ($object->status == $object::STATUS_VALIDATED) { print ''.$langs->trans("Cancel").''."\n"; - } - else - { + } else { print ''.$langs->trans("Re-Open").''."\n"; } } diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 932f0242507..2dfa672acbf 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -127,7 +127,15 @@ $arrayfields = array(); foreach ($object->fields as $key => $val) { // If $val['visible']==0, then we never show the field - if (!empty($val['visible'])) $arrayfields['t.'.$key] = array('label'=>$val['label'], 'checked'=>(($val['visible'] < 0) ? 0 : 1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']); + if (!empty($val['visible'])) { + $visible = dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'] + ); + } } // Extra fields if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) @@ -139,7 +147,8 @@ if (is_array($extrafields->attributes[$object->table_element]['label']) && count 'label'=>$extrafields->attributes[$object->table_element]['label'][$key], 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], - 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]) + 'enabled'=>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]), + 'langfile'=>$extrafields->attributes[$object->table_element]['langfile'][$key] ); } } diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index 05d0f3f8a7c..8acd4430e47 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -517,6 +517,7 @@ class MultiCurrency extends CommonObject global $conf; $sql1 = 'SELECT m.rowid, mc.rate FROM '.MAIN_DB_PREFIX.'multicurrency m'; + $sql1 .= ' LEFT JOIN '.MAIN_DB_PREFIX.'multicurrency_rate mc ON (m.rowid = mc.fk_multicurrency)'; $sql1 .= " WHERE m.code = '".$db->escape($code)."'"; $sql1 .= " AND m.entity IN (".getEntity('multicurrency').")"; @@ -525,7 +526,7 @@ class MultiCurrency extends CommonObject $tmparray = dol_getdate($date_document); $sql2 .= " AND mc.date_sync <= '".$db->idate(dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year'], true))."'"; } - $sql3 .= ' ORDER BY mc.date_sync DESC LIMIT 1'; + $sql3 = ' ORDER BY mc.date_sync DESC LIMIT 1'; dol_syslog(__METHOD__, LOG_DEBUG); $resql = $db->query($sql1.$sql2.$sql3); diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 67e6e9e70f3..32c50ccb661 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1107,7 +1107,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.$langs->trans('DefaultUnitToShow').''; print ''; - print $form->selectUnits('', 'units'); + print $form->selectUnits(empty($line->fk_unit) ? $conf->global->PRODUCT_USE_UNITS : $line->fk_unit, 'units'); print ''; } @@ -2082,35 +2082,45 @@ if ($result > 0) $tmpcode = ''; if (!empty($modCodeProduct->code_auto)) $tmpcode = $modCodeProduct->getNextValue($object, $object->type); -// Define confirmation messages -$formquestionclone = array( - 'text' => $langs->trans("ConfirmClone"), - array('type' => 'text', 'name' => 'clone_ref', 'label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24), - array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneContentProduct"), 'value' => 1), - array('type' => 'checkbox', 'name' => 'clone_categories', 'label' => $langs->trans("CloneCategoriesProduct"), 'value' => 1), -); -if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("CustomerPrices").')', 'value' => 0); -} -if (!empty($conf->global->PRODUIT_SOUSPRODUITS)) -{ - $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1); -} +$formconfirm=''; // Confirm delete product if (($action == 'delete' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js { - print $form->formconfirm("card.php?id=".$object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete"); + $formconfirm = $form->formconfirm("card.php?id=".$object->id, $langs->trans("DeleteProduct"), $langs->trans("ConfirmDeleteProduct"), "confirm_delete", '', 0, "action-delete"); } // Clone confirmation if (($action == 'clone' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) // Always output when not jmobile nor js { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneProduct', $object->ref), 'confirm_clone', $formquestionclone, 'yes', 'action-clone', 350, 600); + // Define confirmation messages + $formquestionclone = array( + 'text' => $langs->trans("ConfirmClone"), + array('type' => 'text', 'name' => 'clone_ref', 'label' => $langs->trans("NewRefForClone"), 'value' => empty($tmpcode) ? $langs->trans("CopyOf").' '.$object->ref : $tmpcode, 'size'=>24), + array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneContentProduct"), 'value' => 1), + array('type' => 'checkbox', 'name' => 'clone_categories', 'label' => $langs->trans("CloneCategoriesProduct"), 'value' => 1), + ); + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_prices', 'label' => $langs->trans("ClonePricesProduct").' ('.$langs->trans("CustomerPrices").')', 'value' => 0); + } + if (!empty($conf->global->PRODUIT_SOUSPRODUITS)) + { + $formquestionclone[] = array('type' => 'checkbox', 'name' => 'clone_composition', 'label' => $langs->trans('CloneCompositionProduct'), 'value' => 1); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneProduct', $object->ref), 'confirm_clone', $formquestionclone, 'yes', 'action-clone', 350, 600); } +// Call Hook formConfirm +$parameters = array('formConfirm' => $formconfirm, 'object' => $object); +$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; +elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; + +// Print form confirm +print $formconfirm; /* ************************************************************************** */ /* */ diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 1f4bbf870f3..f1b3e91617b 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -287,6 +287,9 @@ class Products extends DolibarrApi foreach ($request_data as $field => $value) { if ($field == 'id') { continue; } + if ($field == 'stock_reel') { + throw new RestException(400, 'Stock reel cannot be updated here. Use the /stockmovements endpoint instead'); + } $this->product->$field = $value; } @@ -575,12 +578,12 @@ class Products extends DolibarrApi } if ($result > 0) { - require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; - $prodcustprice = new Productcustomerprice($this->db); - $filter = array(); - $filter['t.fk_product'] .= $id; - if ($thirdparty_id) $filter['t.fk_soc'] .= $thirdparty_id; - $result = $prodcustprice->fetch_all('', '', 0, 0, $filter); + require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; + $prodcustprice = new Productcustomerprice($this->db); + $filter = array(); + $filter['t.fk_product'] .= $id; + if ($thirdparty_id) $filter['t.fk_soc'] .= $thirdparty_id; + $result = $prodcustprice->fetch_all('', '', 0, 0, $filter); } if (empty($prodcustprice->lines)) { @@ -621,8 +624,8 @@ class Products extends DolibarrApi } return array( - 'prices_by_qty'=>$this->product->prices_by_qty[0], // 1 if price by quantity was activated for the product - 'prices_by_qty_list'=>$this->product->prices_by_qty_list[0] + 'prices_by_qty'=>$this->product->prices_by_qty[0], // 1 if price by quantity was activated for the product + 'prices_by_qty_list'=>$this->product->prices_by_qty_list[0] ); } @@ -638,11 +641,11 @@ class Products extends DolibarrApi * @param string $ref_fourn Supplier ref * @param float $tva_tx New VAT Rate (For example 8.5. Should not be a string) * @param string $charges costs affering to product - * @param float $remise_percent Discount regarding qty (percent) - * @param float $remise Discount regarding qty (amount) - * @param int $newnpr Set NPR or not - * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined. - * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER) + * @param float $remise_percent Discount regarding qty (percent) + * @param float $remise Discount regarding qty (amount) + * @param int $newnpr Set NPR or not + * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined. + * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER) * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function). * @param string $newdefaultvatcode Default vat code * @param float $multicurrency_buyprice Purchase price for the quantity min in currency @@ -746,77 +749,77 @@ class Products extends DolibarrApi */ public function getSupplierProducts($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $supplier = 0, $sqlfilters = '') { - global $db, $conf; - $obj_ret = array(); - $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; - $sql = "SELECT t.rowid, t.ref, t.ref_ext"; - $sql .= " FROM ".MAIN_DB_PREFIX."product as t"; - if ($category > 0) { - $sql .= ", ".MAIN_DB_PREFIX."categorie_product as c"; - } - $sql .= ", ".MAIN_DB_PREFIX."product_fournisseur_price as s"; + global $db, $conf; + $obj_ret = array(); + $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; + $sql = "SELECT t.rowid, t.ref, t.ref_ext"; + $sql .= " FROM ".MAIN_DB_PREFIX."product as t"; + if ($category > 0) { + $sql .= ", ".MAIN_DB_PREFIX."categorie_product as c"; + } + $sql .= ", ".MAIN_DB_PREFIX."product_fournisseur_price as s"; - $sql .= ' WHERE t.entity IN ('.getEntity('product').')'; + $sql .= ' WHERE t.entity IN ('.getEntity('product').')'; - if ($supplier > 0) { - $sql .= " AND s.fk_soc = ".$db->escape($supplier); - } - $sql .= " AND s.fk_product = t.rowid"; - // Select products of given category - if ($category > 0) { - $sql .= " AND c.fk_categorie = ".$db->escape($category); - $sql .= " AND c.fk_product = t.rowid"; - } - if ($mode == 1) { - // Show only products - $sql .= " AND t.fk_product_type = 0"; - } elseif ($mode == 2) { - // Show only services - $sql .= " AND t.fk_product_type = 1"; - } - // Add sql filters - if ($sqlfilters) { - if (!DolibarrApi::_checkFilters($sqlfilters)) { - throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); - } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; - $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; - } - $sql .= $db->order($sortfield, $sortorder); - if ($limit) { - if ($page < 0) { - $page = 0; - } - $offset = $limit * $page; - $sql .= $db->plimit($limit + 1, $offset); - } - $result = $db->query($sql); - if ($result) { - $num = $db->num_rows($result); - $min = min($num, ($limit <= 0 ? $num : $limit)); - $i = 0; - while ($i < $min) - { - $obj = $db->fetch_object($result); + if ($supplier > 0) { + $sql .= " AND s.fk_soc = ".$db->escape($supplier); + } + $sql .= " AND s.fk_product = t.rowid"; + // Select products of given category + if ($category > 0) { + $sql .= " AND c.fk_categorie = ".$db->escape($category); + $sql .= " AND c.fk_product = t.rowid"; + } + if ($mode == 1) { + // Show only products + $sql .= " AND t.fk_product_type = 0"; + } elseif ($mode == 2) { + // Show only services + $sql .= " AND t.fk_product_type = 1"; + } + // Add sql filters + if ($sqlfilters) { + if (!DolibarrApi::_checkFilters($sqlfilters)) { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + $sql .= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + $sql .= $db->plimit($limit + 1, $offset); + } + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + $min = min($num, ($limit <= 0 ? $num : $limit)); + $i = 0; + while ($i < $min) + { + $obj = $db->fetch_object($result); - $product_fourn = new ProductFournisseur($this->db); - $product_fourn_list = $product_fourn->list_product_fournisseur_price($obj->rowid, '', '', 0, 0); - foreach ($product_fourn_list as $tmpobj) { - $this->_cleanObjectDatas($tmpobj); - } + $product_fourn = new ProductFournisseur($this->db); + $product_fourn_list = $product_fourn->list_product_fournisseur_price($obj->rowid, '', '', 0, 0); + foreach ($product_fourn_list as $tmpobj) { + $this->_cleanObjectDatas($tmpobj); + } - //var_dump($product_fourn_list->db);exit; - $obj_ret[$obj->rowid] = $product_fourn_list; + //var_dump($product_fourn_list->db);exit; + $obj_ret[$obj->rowid] = $product_fourn_list; - $i++; - } - } else { - throw new RestException(503, 'Error when retrieve product list : '.$db->lasterror()); - } - if (!count($obj_ret)) { - throw new RestException(404, 'No product found'); - } - return $obj_ret; + $i++; + } + } else { + throw new RestException(503, 'Error when retrieve product list : '.$db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No product found'); + } + return $obj_ret; } /** @@ -1054,7 +1057,7 @@ class Products extends DolibarrApi $result = $prodattr->delete(DolibarrApiAccess::$user); if ($result <= 0) { - throw new RestException(500, "Error deleting attribute"); + throw new RestException(500, "Error deleting attribute"); } return $result; @@ -1158,9 +1161,23 @@ class Products extends DolibarrApi throw new RestException(401); } - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE ref LIKE '".trim($ref)."' AND fk_product_attribute = ".(int) $id; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE ref LIKE '".trim($ref)."' AND fk_product_attribute = ".(int) $id." AND entity IN (".getEntity('product').")"; + $query = $this->db->query($sql); - if ($this->db->query($sql)) { + if (!$query) { + throw new RestException(401); + } + + if (!$this->db->num_rows($query)) { + throw new RestException(404, 'Attribute value not found'); + } + + $result = $this->db->fetch_object($query); + + $attrval = new ProductAttributeValue($this->db); + $attrval->id = $result->rowid; + $result = $attrval->delete(DolibarrApiAccess::$user); + if ($result > 0) { return 1; } @@ -1325,7 +1342,7 @@ class Products extends DolibarrApi $objectval = new ProductAttributeValue($this->db); $objectval->id = (int) $id; - if ($objectval->delete() > 0) { + if ($objectval->delete(DolibarrApiAccess::$user) > 0) { return 1; } throw new RestException(500, "Error deleting attribute value"); @@ -1445,9 +1462,9 @@ class Products extends DolibarrApi $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact, $reference); if ($result > 0) { - return $result; + return $result; } else { - throw new RestException(500, "Error creating new product variant"); + throw new RestException(500, "Error creating new product variant"); } } @@ -1570,7 +1587,7 @@ class Products extends DolibarrApi $result = $prodcomb->delete(DolibarrApiAccess::$user); if ($result <= 0) { - throw new RestException(500, "Error deleting variant"); + throw new RestException(500, "Error deleting variant"); } return $result; } @@ -1662,17 +1679,17 @@ class Products extends DolibarrApi } if ($includestockdata) { - $this->product->load_stock(); + $this->product->load_stock(); - if (is_array($this->product->stock_warehouse)) { - foreach ($this->product->stock_warehouse as $keytmp => $valtmp) { - if (is_array($this->product->stock_warehouse[$keytmp]->detail_batch)) { - foreach ($this->product->stock_warehouse[$keytmp]->detail_batch as $keytmp2 => $valtmp2) { - unset($this->product->stock_warehouse[$keytmp]->detail_batch[$keytmp2]->db); - } - } - } - } + if (is_array($this->product->stock_warehouse)) { + foreach ($this->product->stock_warehouse as $keytmp => $valtmp) { + if (is_array($this->product->stock_warehouse[$keytmp]->detail_batch)) { + foreach ($this->product->stock_warehouse[$keytmp]->detail_batch as $keytmp2 => $valtmp2) { + unset($this->product->stock_warehouse[$keytmp]->detail_batch[$keytmp2]->db); + } + } + } + } } if ($includesubproducts) { diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 5de1ee5ad99..1fcb76a571d 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -205,7 +205,7 @@ class Product extends CommonObject /** * Stock alert * - * @var int + * @var float */ public $seuil_stock_alerte = 0; @@ -563,7 +563,7 @@ class Product extends CommonObject return -1; } - if (empty($this->ref)) { + if (empty($this->ref) || $this->ref == 'auto') { // Load object modCodeProduct $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON : 'mod_codeproduct_leopard'); if ($module != 'mod_codeproduct_leopard') // Do not load module file for leopard @@ -995,7 +995,7 @@ class Product extends CommonObject $sql .= ", volume = ".($this->volume != '' ? "'".$this->db->escape($this->volume)."'" : 'null'); $sql .= ", volume_units = ".($this->volume_units != '' ? "'".$this->db->escape($this->volume_units)."'" : 'null'); $sql .= ", fk_default_warehouse = ".($this->fk_default_warehouse > 0 ? $this->db->escape($this->fk_default_warehouse) : 'null'); - $sql .= ", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (int) $this->seuil_stock_alerte : 'null'); + $sql .= ", seuil_stock_alerte = ".((isset($this->seuil_stock_alerte) && is_numeric($this->seuil_stock_alerte)) ? (float) $this->seuil_stock_alerte : 'null'); $sql .= ", description = '".$this->db->escape($this->description)."'"; $sql .= ", url = ".($this->url ? "'".$this->db->escape($this->url)."'" : 'null'); $sql .= ", customcode = '".$this->db->escape($this->customcode)."'"; @@ -1008,7 +1008,7 @@ class Product extends CommonObject $sql .= ", accountancy_code_sell= '".$this->db->escape($this->accountancy_code_sell)."'"; $sql .= ", accountancy_code_sell_intra= '".$this->db->escape($this->accountancy_code_sell_intra)."'"; $sql .= ", accountancy_code_sell_export= '".$this->db->escape($this->accountancy_code_sell_export)."'"; - $sql .= ", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (int) $this->desiredstock : "null"); + $sql .= ", desiredstock = ".((isset($this->desiredstock) && is_numeric($this->desiredstock)) ? (float) $this->desiredstock : "null"); $sql .= ", cost_price = ".($this->cost_price != '' ? $this->db->escape($this->cost_price) : 'null'); $sql .= ", fk_unit= ".(!$this->fk_unit ? 'NULL' : (int) $this->fk_unit); $sql .= ", price_autogen = ".(!$this->price_autogen ? 0 : 1); @@ -1077,7 +1077,7 @@ class Product extends CommonObject $comb = new ProductCombination($this->db); foreach ($comb->fetchAllByFkProductParent($this->id) as $currcomb) { - $currcomb->updateProperties($this, $user); + $currcomb->updateProperties($this, $user); } } @@ -2025,7 +2025,7 @@ class Product extends CommonObject return -1; } - $sql = "SELECT rowid, ref, ref_ext, label, description, url, note as note_private, customcode, fk_country, price, price_ttc,"; + $sql = "SELECT rowid, ref, ref_ext, label, description, url, note_public, note as note_private, customcode, fk_country, price, price_ttc,"; $sql .= " price_min, price_min_ttc, price_base_type, cost_price, default_vat_code, tva_tx, recuperableonly as tva_npr, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, tosell,"; $sql .= " tobuy, fk_product_type, duration, fk_default_warehouse, seuil_stock_alerte, canvas, net_measure, net_measure_units, weight, weight_units,"; $sql .= " length, length_units, width, width_units, height, height_units,"; @@ -2033,7 +2033,7 @@ class Product extends CommonObject $sql .= " accountancy_code_buy, accountancy_code_buy_intra, accountancy_code_buy_export,"; $sql .= " accountancy_code_sell, accountancy_code_sell_intra, accountancy_code_sell_export, stock, pmp,"; $sql .= " datec, tms, import_key, entity, desiredstock, tobatch, fk_unit,"; - $sql .= " fk_price_expression, price_autogen"; + $sql .= " fk_price_expression, price_autogen, model_pdf"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; if ($id) { $sql .= " WHERE rowid = ".(int) $id; @@ -2061,8 +2061,9 @@ class Product extends CommonObject $this->label = $obj->label; $this->description = $obj->description; $this->url = $obj->url; - $this->note_private = $obj->note_private; - $this->note = $obj->note_private; // deprecated + $this->note_public = $obj->note_public; + $this->note_private = $obj->note_private; + $this->note = $obj->note_private; // deprecated $this->type = $obj->fk_product_type; $this->status = $obj->tosell; @@ -2134,6 +2135,7 @@ class Product extends CommonObject $this->fk_price_expression = $obj->fk_price_expression; $this->fk_unit = $obj->fk_unit; $this->price_autogen = $obj->price_autogen; + $this->model_pdf = $obj->model_pdf; $this->db->free($resql); @@ -2208,7 +2210,7 @@ class Product extends CommonObject } }*/ } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; return -1; } } @@ -2253,12 +2255,12 @@ class Product extends CommonObject } $this->prices_by_qty_list[0] = $resultat; } else { - dol_print_error($this->db); - return -1; + $this->error=$this->db->lasterror; + return -1; } } } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; return -1; } } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES) && empty($ignore_price_load)) // prices per customer and quantity @@ -2312,12 +2314,12 @@ class Product extends CommonObject } $this->prices_by_qty_list[$i] = $resultat; } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; return -1; } } } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; return -1; } } @@ -2344,7 +2346,7 @@ class Product extends CommonObject return 0; } } else { - dol_print_error($this->db); + $this->error=$this->db->lasterror; return -1; } } @@ -3489,7 +3491,7 @@ class Product extends CommonObject $sql = "SELECT sum(d.qty), date_format(d.date_valid, '%Y%m')"; if ($mode == 'bynumber') { - $sql .= ", count(DISTINCT c.rowid)"; + $sql .= ", count(DISTINCT d.rowid)"; } $sql .= " FROM ".MAIN_DB_PREFIX."mrp_mo as d LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON d.fk_soc = s.rowid"; if ($filteronproducttype >= 0) { @@ -4426,6 +4428,7 @@ class Product extends CommonObject global $conf, $user, $langs; $langs->load("products"); + $outputlangs->load("products"); // Positionne le modele sur le nom du modele a utiliser if (!dol_strlen($modele)) { diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index aa3b49dd2c6..1c1dfa0913e 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -66,7 +66,7 @@ if ($id > 0 || !empty($ref)) if ($cancel) $action = ''; -// Action association d'un sousproduit +// Add subproduct to product if ($action == 'add_prod' && ($user->rights->produit->creer || $user->rights->service->creer)) { $error = 0; diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php index 9f3afa55738..6a2406d74b5 100644 --- a/htdocs/product/inventory/card.php +++ b/htdocs/product/inventory/card.php @@ -22,9 +22,11 @@ */ require '../../main.inc.php'; -include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; // Load translation files required by the page $langs->loadLangs(array("stocks", "other")); @@ -49,7 +51,7 @@ if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) $object = new Inventory($db); $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('inventorycard')); // Note that conf->hooks_modules contains array +$hookmanager->initHooks(array('inventorycard', 'globalcard')); // Note that conf->hooks_modules contains array // Fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); @@ -76,11 +78,19 @@ include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be includ if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { + $permissiontoread = $user->rights->stock->lire; $permissiontoadd = $user->rights->stock->creer; $permissiontodelete = $user->rights->stock->supprimer; + $permissionnote = $user->rights->stock->creer; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $user->rights->stock->creer; // Used by the include of actions_dellink.inc.php + $upload_dir = $conf->stock->multidir_output[isset($object->entity) ? $object->entity : 1]; } else { + $permissiontoread = $user->rights->stock->inventory_advance->read; $permissiontoadd = $user->rights->stock->inventory_advance->write; $permissiontodelete = $user->rights->stock->inventory_advance->write; + $permissionnote = $user->rights->stock->inventory_advance->write; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $user->rights->stock->inventory_advance->write; // Used by the include of actions_dellink.inc.php + $upload_dir = $conf->stock->multidir_output[isset($object->entity) ? $object->entity : 1]; } @@ -98,7 +108,15 @@ if (empty($reshook)) $backurlforlist = DOL_URL_ROOT.'/product/inventory/list.php'; - // Actions cancel, add, update, delete or clone + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist; + else $backtopage = dol_buildpath('/product/inventory/card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); + } + } + $triggermodname = 'STOCK_INVENTORY_MODIFY'; // Name of trigger action code to execute when we modify record + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; // Actions when linking object each other @@ -107,11 +125,26 @@ if (empty($reshook)) // Actions when printing a doc from card include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + // Action to move up and down lines of object + //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + /*if ($action == 'set_thirdparty' && $permissiontoadd) + { + $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, 'MYOBJECT_MODIFY'); + }*/ + if ($action == 'classin' && $permissiontoadd) + { + $object->setProject(GETPOST('projectid', 'int')); + } + // Actions to send emails - /*$triggersendname = 'MYOBJECT_SENTBYMAIL'; - $autocopy='MAIN_MAIL_AUTOCOPY_MYOBJECT_TO'; - $trackid='myobject'.$object->id; - include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';*/ + $triggersendname = 'INVENTORY_SENTBYMAIL'; + $autocopy='MAIN_MAIL_AUTOCOPY_INVENTORY_TO'; + $trackid='stockinv'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; } @@ -122,8 +155,12 @@ if (empty($reshook)) */ $form = new Form($db); +$formfile = new FormFile($db); +$formproject = new FormProjets($db); -llxHeader('', $langs->trans('Inventory'), ''); +$title = $langs->trans("Inventory"); +$help_url = ''; +llxHeader('', $title, $help_url); // Example : Adding jquery code print ''; - print load_fiche_titre($langs->trans("StockCorrection"), '', 'generic'); +print load_fiche_titre($langs->trans("StockCorrection"), '', 'generic'); - print '
    '."\n"; +print ''."\n"; - dol_fiche_head(); +dol_fiche_head(); - print ''; - print ''; - print ''; - print ''; +print ''; +print ''; +print ''; +print '
    '; - // Warehouse or product - print ''; -if ($object->element == 'product') -{ +// Warehouse or product +print ''; +if ($object->element == 'product') { print ''; print ''; } -if ($object->element == 'stock') -{ +if ($object->element == 'stock') { print ''; print ''; } - print ''; - print ''; - print ''; +print ''; +print ''; +print ''; - // Purchase price - print ''; - print ''; - print ''; -if (!empty($conf->projet->enabled)) -{ - print ''; - print ''; -} - print ''; - - // Serial / Eat-by date +// Serial / Eat-by date if (!empty($conf->productbatch->enabled) && - (($object->element == 'product' && $object->hasbatch()) - || ($object->element == 'stock')) - ) +(($object->element == 'product' && $object->hasbatch()) +|| ($object->element == 'stock')) +) { print ''; print 'element == 'stock' ? '' : ' class="fieldrequired"').'>'.$langs->trans("batch_number").''; } - // Label of mouvement of id of inventory - $valformovementlabel = ((GETPOST("label") && (GETPOST('label') != $langs->trans("MovementCorrectStock", ''))) ? GETPOST("label") : $langs->trans("MovementCorrectStock", $productref)); - print ''; - print ''; - print ''; - print ''; - print ''; +// Purchase price and project +print ''; +print ''; +print ''; +if (!empty($conf->projet->enabled)) +{ + print ''; + print ''; +} +print ''; - print '
    '.$langs->trans("Warehouse").''; $ident = (GETPOST("dwid") ?GETPOST("dwid", 'int') : (GETPOST('id_entrepot') ? GETPOST('id_entrepot', 'int') : ($object->element == 'product' && $object->fk_default_warehouse ? $object->fk_default_warehouse : 'ifone'))); if (empty($ident) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) $ident = $conf->global->MAIN_DEFAULT_WAREHOUSE; print $formproduct->selectWarehouses($ident, 'id_entrepot', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'minwidth100'); - print '   '; print ''; print ''; print ''; print ''.$langs->trans("Product").''; $form->select_produits(GETPOST('product_id', 'int'), 'product_id', (empty($conf->global->STOCK_SUPPORTS_SERVICES) ? '0' : ''), 0, 0, -1, 2, '', 0, null, 0, 1, 0, 'maxwidth500'); - print '   '; print ''; print ''; print ''; print ''.$langs->trans("NumberOfUnit").'
    '.$langs->trans("NumberOfUnit").'
    '.$langs->trans("UnitPurchaseValue").''.$langs->trans('Project').''; - $formproject->select_projects(-1, '', 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, 'maxwidth300'); - print '
    '; @@ -130,26 +114,39 @@ if (!empty($conf->productbatch->enabled) && print '
    '.$langs->trans("MovementLabel").''; - print ''; - print ''.$langs->trans("InventoryCode").'
    '.$langs->trans("UnitPurchaseValue").''.$langs->trans('Project').''; + $formproject->select_projects(-1, '', 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, 'maxwidth300'); + print '
    '; +// Label of mouvement of id of inventory +$valformovementlabel = ((GETPOST("label") && (GETPOST('label') != $langs->trans("MovementCorrectStock", ''))) ? GETPOST("label") : $langs->trans("MovementCorrectStock", $productref)); +print ''; +print ''.$langs->trans("MovementLabel").''; +print ''; +print ''; +print ''; +print ''.$langs->trans("InventoryCode").''; +print ''; - dol_fiche_end(); +print ''; - print '
    '; - print ''; - print '     '; - print ''; - print '
    '; +dol_fiche_end(); - print '
    '; +print '
    '; +print ''; +print '     '; +print ''; +print '
    '; + +print ''; ?> diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index 097f1d2c84b..f725a5ebbfe 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -29,16 +29,16 @@ if (empty($conf) || !is_object($conf)) { element == 'product') $productref = $object->ref; +$productref = ''; +if ($object->element == 'product') $productref = $object->ref; - $langs->load("productbatch"); +$langs->load("productbatch"); - if (empty($id)) $id = $object->id; +if (empty($id)) $id = $object->id; - $pdluoid = GETPOST('pdluoid', 'int'); +$pdluoid = GETPOST('pdluoid', 'int'); - $pdluo = new Productbatch($db); +$pdluo = new Productbatch($db); if ($pdluoid > 0) { @@ -51,49 +51,47 @@ if ($pdluoid > 0) } } - print load_fiche_titre($langs->trans("StockTransfer"), '', 'generic'); +print load_fiche_titre($langs->trans("StockTransfer"), '', 'generic'); - print '
    '."\n"; +print ''."\n"; - dol_fiche_head(); +dol_fiche_head(); - print ''; - print ''; - print ''; +print ''; +print ''; +print ''; if ($pdluoid) { print ''; } - print ''; +print '
    '; - // Source warehouse or product - print ''; -if ($object->element == 'product') -{ +// Source warehouse or product +print ''; +if ($object->element == 'product') { print ''; print ''; } -if ($object->element == 'stock') -{ +if ($object->element == 'stock') { print ''; print ''; } - print ''; - print ''; - print ''; +print ''; +print ''; +print ''; - // Serial / Eat-by date +// Serial / Eat-by date if (!empty($conf->productbatch->enabled) && - (($object->element == 'product' && $object->hasbatch()) - || ($object->element == 'stock')) - ) +(($object->element == 'product' && $object->hasbatch()) +|| ($object->element == 'stock')) +) { print ''; print 'element == 'stock' ? '' : ' class="fieldrequired"').'>'.$langs->trans("batch_number").''; } - // Label - $valformovementlabel = (GETPOST("label") ?GETPOST("label") : $langs->trans("MovementTransferStock", $productref)); - print ''; - print ''; - print ''; - print ''; - print ''; +// Label +$valformovementlabel = (GETPOST("label") ?GETPOST("label") : $langs->trans("MovementTransferStock", $productref)); +print ''; +print ''; +print ''; +print ''; +print ''; - print '
    '.$langs->trans("WarehouseSource").''; print $formproduct->selectWarehouses((GETPOST("dwid") ?GETPOST("dwid", 'int') : (GETPOST('id_entrepot') ?GETPOST('id_entrepot', 'int') : ($object->element == 'product' && $object->fk_default_warehouse ? $object->fk_default_warehouse : 'ifone'))), 'id_entrepot', 'warehouseopen,warehouseinternal', 1); print ''.$langs->trans("Product").''; $form->select_produits(GETPOST('product_id', 'int'), 'product_id', (empty($conf->global->STOCK_SUPPORTS_SERVICES) ? '0' : ''), 0, 0, -1, 2, '', 0, null, 0, 1, 0, 'maxwidth500'); print ''.$langs->trans("WarehouseTarget").''; - print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'), 'id_entrepot_destination', 'warehouseopen,warehouseinternal', 1); - print '
    '.$langs->trans("NumberOfUnit").'
    '.$langs->trans("WarehouseTarget").''; +print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'), 'id_entrepot_destination', 'warehouseopen,warehouseinternal', 1); +print '
    '.$langs->trans("NumberOfUnit").'
    '; @@ -118,26 +116,26 @@ if (!empty($conf->productbatch->enabled) && print '
    '.$langs->trans("MovementLabel").''; - print ''; - print ''.$langs->trans("InventoryCode").'
    '.$langs->trans("MovementLabel").''; +print ''; +print ''.$langs->trans("InventoryCode").'
    '; +print ''; - dol_fiche_end(); +dol_fiche_end(); - print '
    '; - print ''; - print '     '; - print ''; - print '
    '; +print '
    '; +print ''; +print '     '; +print ''; +print '
    '; - print '
    '; +print ''; ?> diff --git a/htdocs/product/traduction.php b/htdocs/product/traduction.php index 4e5c7b13458..055e3cbefc7 100644 --- a/htdocs/product/traduction.php +++ b/htdocs/product/traduction.php @@ -73,11 +73,11 @@ $cancel != $langs->trans("Cancel") && $current_lang = $langs->getDefaultLang(); // update de l'objet - if ($_POST["forcelangprod"] == $current_lang) - { + if ($_POST["forcelangprod"] == $current_lang) { $object->label = $_POST["libelle"]; $object->description = dol_htmlcleanlastbr($_POST["desc"]); $object->other = dol_htmlcleanlastbr($_POST["other"]); + $object->update($object->id, $user); } else { $object->multilangs[$_POST["forcelangprod"]]["label"] = $_POST["libelle"]; $object->multilangs[$_POST["forcelangprod"]]["description"] = dol_htmlcleanlastbr($_POST["desc"]); @@ -85,8 +85,7 @@ $cancel != $langs->trans("Cancel") && } // sauvegarde en base - if ($object->setMultiLangs($user) > 0) - { + if ($object->setMultiLangs($user) > 0) { $action = ''; } else { $action = 'add'; diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index f3a68dd979f..437c5934c81 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -119,8 +119,7 @@ $object = new Task($db); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels -//$extrafields->fetch_name_optionals_label('projet'); -$extrafields->fetch_name_optionals_label('projet_task'); +$extrafields->fetch_name_optionals_label($object->table_element); $arrayfields = array(); /*$arrayfields=array( diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index bf28eda4edf..e3331fcec74 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -178,12 +178,12 @@ if (empty($reshook)) if ($result < 0) { $langs->load("errors"); - setEventMessages($langs->trans($object->error), null, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } } else { $langs->load("errors"); - setEventMessages($langs->trans($object->error), null, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } if (!$error && !empty($object->id) > 0) diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 084292d0727..8466fdc3bcb 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -35,7 +35,8 @@ class Tasks extends DolibarrApi */ static $FIELDS = array( 'ref', - 'label' + 'label', + 'fk_project' ); /** diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 5d2eb217031..cc340600131 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -521,6 +521,7 @@ class Project extends CommonObject $this->opp_amount = $obj->opp_amount; $this->opp_percent = $obj->opp_percent; $this->budget_amount = $obj->budget_amount; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->usage_opportunity = (int) $obj->usage_opportunity; $this->usage_task = (int) $obj->usage_task; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 10f5a36d67f..0d737dfea7f 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -62,7 +62,7 @@ class Task extends CommonObject /** * @var int ID parent task */ - public $fk_task_parent; + public $fk_task_parent = 0; /** * @var string Label of task @@ -145,6 +145,9 @@ class Task extends CommonObject { global $conf, $langs; + //For the date + $now = dol_now(); + $error = 0; // Clean parameters @@ -175,7 +178,7 @@ class Task extends CommonObject $sql .= ", ".$this->fk_task_parent; $sql .= ", '".$this->db->escape($this->label)."'"; $sql .= ", '".$this->db->escape($this->description)."'"; - $sql .= ", '".$this->db->idate($this->date_c)."'"; + $sql .= ", '".$this->db->idate($now)."'"; $sql .= ", ".$user->id; $sql .= ", ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null'); $sql .= ", ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null'); diff --git a/htdocs/projet/ganttview.php b/htdocs/projet/ganttview.php index d578f372777..81b7be12e33 100644 --- a/htdocs/projet/ganttview.php +++ b/htdocs/projet/ganttview.php @@ -235,10 +235,11 @@ if ($user->rights->projet->all->creer || $user->rights->projet->creer) { $linktocreatetask = dolGetButtonTitle($langs->trans('AddTask'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id.'&action=create'.$param.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$object->id), '', $linktocreatetaskUserRight, $linktocreatetaskParam); -$linktolist = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss'=>'reposition')); +$linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss'=>'reposition')); +$linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss'=>'reposition marginleftonly btnTitleSelected')); //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1); -print load_fiche_titre($title, $linktolist.'   '.$linktocreatetask, 'generic'); +print load_fiche_titre($title, $linktotasks.'   '.$linktocreatetask, 'generic'); // Get list of tasks in tasksarray and taskarrayfiltered @@ -369,7 +370,17 @@ if (count($tasksarray) > 0) //var_dump($dateformatinput); //var_dump($dateformatinput2); - print '
    '; + $moreforfilter = '
    '; + + $moreforfilter .= '
    '; + //$moreforfilter .= $langs->trans("TasksAssignedTo").': '; + //$moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', 1); + $moreforfilter .= ' '; + $moreforfilter .= '
    '; + + $moreforfilter .= '
    '; + + print $moreforfilter; print '
    '; diff --git a/htdocs/projet/graph_opportunities.inc.php b/htdocs/projet/graph_opportunities.inc.php index a18b2dc54a5..5a2febe5a33 100644 --- a/htdocs/projet/graph_opportunities.inc.php +++ b/htdocs/projet/graph_opportunities.inc.php @@ -1,4 +1,22 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// variable $listofopplabel and $listofoppstatus should be defined + if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { $sql = "SELECT p.fk_opp_status as opp_status, cls.code, COUNT(p.rowid) as nb, SUM(p.opp_amount) as opp_amount, SUM(p.opp_amount * p.opp_percent) as ponderated_opp_amount"; @@ -54,7 +72,7 @@ if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) $labelStatus = ''; $code = dol_getIdFromCode($db, $status, 'c_lead_status', 'rowid', 'code'); - if ($code) $labelStatus = $langs->trans("OppStatus".$code); + if ($code) $labelStatus = $langs->transnoentitiesnoconv("OppStatus".$code); if (empty($labelStatus)) $labelStatus = $listofopplabel[$status]; //$labelStatus .= ' ('.$langs->trans("Coeff").': '.price2num($listofoppstatus[$status]).')'; diff --git a/htdocs/projet/info.php b/htdocs/projet/info.php index 6c73d2cfc8b..b3cebaad913 100644 --- a/htdocs/projet/info.php +++ b/htdocs/projet/info.php @@ -61,7 +61,7 @@ $search_agenda_label = GETPOST('search_agenda_label'); $id = GETPOST("id", 'int'); $socid = 0; //if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. -$result = restrictedArea($user, 'projet', $id, ''); +$result = restrictedArea($user, 'projet', $id, 'projet&project'); if (!$user->rights->projet->lire) accessforbidden(); diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index f395a4ee27a..c11ffcd8d6f 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -632,7 +632,8 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third print ''; $title = $langs->trans("ListOfTasks"); - $linktotasks = dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss'=>'reposition')); + $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss'=>'reposition btnTitleSelected')); + $linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss'=>'reposition marginleftonly')); //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1); print load_fiche_titre($title, $linktotasks.'   '.$linktocreatetask, 'generic'); diff --git a/htdocs/public/demo/index.php b/htdocs/public/demo/index.php index 3773a530691..c5d610712d8 100644 --- a/htdocs/public/demo/index.php +++ b/htdocs/public/demo/index.php @@ -107,7 +107,7 @@ if (empty($reshook)) 'mailmanspip', 'notification', 'oauth', 'syslog', 'user', 'webservices', 'workflow', // Extended modules 'memcached', 'numberwords', 'zipautofillfr'); - $alwayshiddenuncheckedmodules = array('dav', 'debugbar', 'emailcollector', 'ftp', 'hrm', 'modulebuilder', 'printing', 'webservicesclient', + $alwayshiddenuncheckedmodules = array('collab', 'dav', 'debugbar', 'emailcollector', 'ftp', 'hrm', 'modulebuilder', 'printing', 'webservicesclient', 'zappier', // Extended modules 'awstats', 'bittorrent', 'bootstrap', 'cabinetmed', 'cmcic', 'concatpdf', 'customfield', 'datapolicy', 'deplacement', 'dolicloud', 'filemanager', 'lightbox', 'mantis', 'monitoring', 'moretemplates', 'multicompany', 'nltechno', 'numberingpack', 'openstreetmap', 'ovh', 'phenix', 'phpsysinfo', 'pibarcode', 'postnuke', 'dynamicprices', 'receiptprinter', 'selectbank', 'skincoloreditor', 'submiteverywhere', 'survey', 'thomsonphonebook', 'topten', 'tvacerfa', 'voyage', 'webcalendar', 'webmail'); @@ -417,16 +417,14 @@ if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AD_CLIEN if (empty($conf->dol_use_jmobile)) { print '
    '."\n"; - print ''."\n"; - print ''."\n"; + print ''."\n"; print '
    '."\n"; } else { print ''."\n"; diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index 2031c11a3ad..d29d441c611 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -45,6 +45,7 @@ $langs->loadLangs(array("main", "other", "dict", "bills", "companies", "errors", // Security check // No check on module enabled. Done later according to $validpaymentmethod +// Get parameters $action = GETPOST('action', 'aZ09'); // Input are: @@ -70,9 +71,6 @@ if (!$action) } - - - // Define $urlwithroot //$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); //$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file @@ -132,7 +130,7 @@ $conf->dol_hide_leftmenu = 1; $replacemainarea = (empty($conf->dol_hide_leftmenu) ? '
    ' : '').'
    '; llxHeader($head, $langs->trans("OnlineSignature"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea); -// Check link validity +// Check link validity for param 'source' if (!empty($source) && in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', ''))) { $langs->load("errors"); diff --git a/htdocs/public/payment/paymentko.php b/htdocs/public/payment/paymentko.php index c42677d8b21..4b87cf45b03 100644 --- a/htdocs/public/payment/paymentko.php +++ b/htdocs/public/payment/paymentko.php @@ -127,10 +127,12 @@ if (!empty($_SESSION['ipaddress'])) // To avoid to make action twice $ipaddress = $_SESSION['ipaddress']; $errormessage = $_SESSION['errormessage']; - // Call trigger - $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_KO', $user); - if ($result < 0) $error++; - // End call triggers + if (is_object($object) && method_exists($object, 'call_trigger')) { + // Call trigger + $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_KO', $user); + if ($result < 0) $error++; + // End call triggers + } // Send an email $sendemail = ''; diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 4bb899b930e..b316e7c68a8 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -186,7 +186,7 @@ if ($urllogo) } -print '

    '; +print '


    '; if (!empty($conf->paypal->enabled)) @@ -593,8 +593,8 @@ if ($ispaymentok) { // Record payment include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; - $invoice = new Facture($db); - $result = $invoice->fetch($tmptag['INV']); + $object = new Facture($db); + $result = $object->fetch($tmptag['INV']); if ($result) { $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; @@ -623,9 +623,9 @@ if ($ispaymentok) $paiement->datepaye = $now; if ($currencyCodeType == $conf->currency) { - $paiement->amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching with invoice id + $paiement->amounts = array($object->id => $FinalPaymentAmt); // Array with all payments dispatching with invoice id } else { - $paiement->multicurrency_amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching + $paiement->multicurrency_amounts = array($object->id => $FinalPaymentAmt); // Array with all payments dispatching $postactionmessages[] = 'Payment was done in a different currency that currency expected of company'; $ispostactionok = -1; @@ -662,7 +662,7 @@ if ($ispaymentok) if ($bankaccountid > 0) { $label = '(CustomerInvoicePayment)'; - if ($invoice->type == Facture::TYPE_CREDIT_NOTE) $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note + if ($object->type == Facture::TYPE_CREDIT_NOTE) $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note $result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, '', ''); if ($result < 0) { @@ -709,10 +709,12 @@ if ($ispaymentok) $currencyCodeType = $_SESSION['currencyCodeType']; $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; - // Call trigger - $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_OK', $user); - if ($result < 0) $error++; - // End call triggers + if (is_object($object) && method_exists($object, 'call_trigger')) { + // Call trigger + $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_OK', $user); + if ($result < 0) $error++; + // End call triggers + } print $langs->trans("YourPaymentHasBeenRecorded")."
    \n"; if ($TRANSACTIONID) print $langs->trans("ThisIsTransactionId", $TRANSACTIONID)."

    \n"; @@ -831,10 +833,12 @@ if ($ispaymentok) $currencyCodeType = $_SESSION['currencyCodeType']; $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; - // Call trigger - $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_KO', $user); - if ($result < 0) $error++; - // End call triggers + if (is_object($object) && method_exists($object, 'call_trigger')) { + // Call trigger + $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_KO', $user); + if ($result < 0) $error++; + // End call triggers + } print $langs->trans('DoExpressCheckoutPaymentAPICallFailed')."
    \n"; print $langs->trans('DetailedErrorMessage').": ".$ErrorLongMsg."
    \n"; diff --git a/htdocs/public/recruitment/index.php b/htdocs/public/recruitment/index.php new file mode 100644 index 00000000000..0797ff20735 --- /dev/null +++ b/htdocs/public/recruitment/index.php @@ -0,0 +1,457 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/public/recruitment/index.php + * \ingroup recruitment + * \brief Public file to list jobs + */ + +if (!defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +// Do not check anti CSRF attack test +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +// If there is no need to load and show top and left menu +if (!defined("NOLOGIN")) { + define("NOLOGIN", '1'); +} +// If this page is public (can be called outside logged session) + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("companies", "other", "recruitment")); + +// Get parameters +$action = GETPOST('action', 'aZ09'); +$email = GETPOST('email', 'alpha'); + +$object = new RecruitmentJobPosition($db); + + + + +/* + * Actions + */ + +// None + + + +/* + * View + */ + +$form = new Form($db); +$user_assign = new User($db); +$user_create = new User($db); + +if (!$conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE) { + print '
    '.$langs->trans('PublicInterfaceForbidden').'
    '; + $db->close(); + exit(); +} + +$arrayofjs = array(); +$arrayofcss = array(); + +llxHeaderTicket($langs->trans("Jobs"), "", 0, 0, $arrayofjs, $arrayofcss); + + +print '
    '; + +$display_ticket_list = 1; + +print '
    '; +if ($display_ticket_list) { + // Filters + $search_fk_status = GETPOST("search_fk_status", 'alpha'); + $search_subject = GETPOST("search_subject", 'alpha'); + $search_type = GETPOST("search_type", 'alpha'); + $search_category = GETPOST("search_category", 'alpha'); + $search_severity = GETPOST("search_severity", 'alpha'); + $search_fk_user_create = GETPOST("search_fk_user_create", 'int'); + $search_fk_user_assign = GETPOST("search_fk_user_assign", 'int'); + + // Store current page url + $url_page_current = dol_buildpath('/public/ticket/list.php', 1); + + // Do we click on purge search criteria ? + if (GETPOST("button_removefilter_x")) { + $search_fk_status = ''; + $search_subject = ''; + $search_type = ''; + $search_category = ''; + $search_severity = ''; + $search_fk_user_create = ''; + $search_fk_user_assign = ''; + } + + // fetch optionals attributes and labels + $extrafields = new ExtraFields($db); + $extrafields->fetch_name_optionals_label($object->table_element); + + $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + + $filter = array(); + $param = 'action=viewlist'; + + // Definition of fields for list + $arrayfields = array( + 't.datec' => array('label' => $langs->trans("Date"), 'checked' => 1), + 't.date_read' => array('label' => $langs->trans("TicketReadOn"), 'checked' => 0), + 't.date_close' => array('label' => $langs->trans("TicketCloseOn"), 'checked' => 0), + 't.ref' => array('label' => $langs->trans("Ref"), 'checked' => 1), + //'t.track_id' => array('label' => $langs->trans("IDTracking"), 'checked' => 0), + 't.fk_statut' => array('label' => $langs->trans("Status"), 'checked' => 1), + 't.subject' => array('label' => $langs->trans("Subject"), 'checked' => 1), + 'type.code' => array('label' => $langs->trans("Type"), 'checked' => 1), + 'category.code' => array('label' => $langs->trans("Category"), 'checked' => 1), + 'severity.code' => array('label' => $langs->trans("Severity"), 'checked' => 1), + 't.progress' => array('label' => $langs->trans("Progression"), 'checked' => 0), + //'t.fk_contract' => array('label' => $langs->trans("Contract"), 'checked' => 0), + 't.fk_user_create' => array('label' => $langs->trans("Author"), 'checked' => 1), + 't.fk_user_assign' => array('label' => $langs->trans("AssignedTo"), 'checked' => 0), + + //'t.entity'=>array('label'=>$langs->trans("Entity"), 'checked'=>1, 'enabled'=>(! empty($conf->multicompany->enabled) && empty($conf->multicompany->transverse_mode))), + //'t.datec' => array('label' => $langs->trans("DateCreation"), 'checked' => 0, 'position' => 500), + //'t.tms' => array('label' => $langs->trans("DateModificationShort"), 'checked' => 0, 'position' => 2) + //'t.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), + ); + + // Extra fields + if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate') { + $arrayfields["ef.".$key] = array('label' => $extrafields->attributes[$object->table_element]['label'][$key], 'checked' => ($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1, 'position' => $extrafields->attributes[$object->table_element]['pos'][$key], 'enabled' =>(abs($extrafields->attributes[$object->table_element]['list'][$key]) != 3) && $extrafields->attributes[$object->table_element]['perms'][$key]); + } + } + } + if (!empty($search_subject)) { + $filter['t.subject'] = $search_subject; + $param .= '&search_subject='.urlencode($search_subject); + } + if (!empty($search_type)) { + $filter['t.type_code'] = $search_type; + $param .= '&search_type='.urlencode($search_type); + } + if (!empty($search_category)) { + $filter['t.category_code'] = $search_category; + $param .= '&search_category='.urlencode($search_category); + } + if (!empty($search_severity)) { + $filter['t.severity_code'] = $search_severity; + $param .= '&search_severity='.urlencode($search_severity); + } + if (!empty($search_fk_user_assign)) { + // -1 value = all so no filter + if ($search_fk_user_assign > 0) { + $filter['t.fk_user_assign'] = $search_fk_user_assign; + $param .= '&search_fk_user_assign='.urlencode($search_fk_user_assign); + } + } + if (!empty($search_fk_user_create)) { + // -1 value = all so no filter + if ($search_fk_user_create > 0) { + $filter['t.fk_user_create'] = $search_fk_user_create; + $param .= '&search_fk_user_create='.urlencode($search_fk_user_create); + } + } + if ((isset($search_fk_status) && $search_fk_status != '') && $search_fk_status != '-1' && $search_fk_status != 'non_closed') { + $filter['t.fk_statut'] = $search_fk_status; + $param .= '&search_fk_status='.urlencode($search_fk_status); + } + if (isset($search_fk_status) && $search_fk_status == 'non_closed') { + $filter['t.fk_statut'] = array(0, 1, 3, 4, 5, 6); + $param .= '&search_fk_status=non_closed'; + } + + require DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + $sortfield = GETPOST("sortfield", 'alpha'); + $sortorder = GETPOST("sortorder", 'alpha'); + + if (!$sortfield) { + $sortfield = 't.datec'; + } + if (!$sortorder) { + $sortorder = 'DESC'; + } + + $limit = $conf->liste_limit; + + $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); + if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 + $offset = $limit * $page; + $pageprev = $page - 1; + $pagenext = $page + 1; + + // Request SQL + $sql = "SELECT DISTINCT"; + $sql .= " t.rowid,"; + $sql .= " t.ref,"; + $sql .= " t.track_id,"; + $sql .= " t.fk_soc,"; + $sql .= " t.fk_project,"; + $sql .= " t.origin_email,"; + $sql .= " t.fk_user_create, uc.lastname as user_create_lastname, uc.firstname as user_create_firstname,"; + $sql .= " t.fk_user_assign, ua.lastname as user_assign_lastname, ua.firstname as user_assign_firstname,"; + $sql .= " t.subject,"; + $sql .= " t.message,"; + $sql .= " t.fk_statut,"; + $sql .= " t.resolution,"; + $sql .= " t.progress,"; + $sql .= " t.timing,"; + $sql .= " t.type_code,"; + $sql .= " t.category_code,"; + $sql .= " t.severity_code,"; + $sql .= " t.datec,"; + $sql .= " t.date_read,"; + $sql .= " t.date_close,"; + $sql .= " t.tms,"; + $sql .= " type.label as type_label, category.label as category_label, severity.label as severity_label"; + // Add fields for extrafields + if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key.' as options_'.$key : ''); + } + $sql .= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as t"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=t.fk_soc"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as uc ON uc.rowid=t.fk_user_create"; + if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition_extrafields as ef on (t.rowid = ef.fk_object)"; + } + $sql .= " WHERE t.entity IN (".getEntity('recruitmentjobposition').")"; + // Manage filter + if (!empty($filter)) { + foreach ($filter as $key => $value) { + if (strpos($key, 'date')) { // To allow $filter['YEAR(s.dated)']=>$year + $sql .= ' AND '.$key.' = \''.$value.'\''; + } elseif ($key == 't.fk_statut') { + if (is_array($value) && count($value) > 0) { + $sql .= 'AND '.$key.' IN ('.implode(',', $value).')'; + } else { + $sql .= ' AND '.$key.' = '.$db->escape($value); + } + } else { + $sql .= ' AND '.$key.' LIKE \'%'.$value.'%\''; + } + } + } + $sql .= " ORDER BY ".$sortfield.' '.$sortorder; + + $resql = $db->query($sql); + if ($resql) { + $num_total = $db->num_rows($resql); + if (!empty($limit)) { + $sql .= ' '.$db->plimit($limit + 1, $offset); + } + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + print_barre_liste($langs->trans('JobList'), $page, 'public/recruitment/list.php', $param, $sortfield, $sortorder, '', $num, $num_total, 'ticket'); + + // Search bar + print '
    '."\n"; + print ''; + print ''; + print ''; + print ''; + + $varpage = empty($contextpage) ? $url_page_current : $contextpage; + $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + + print ''; + + // Filter bar + print ''; + + if (!empty($arrayfields['t.datec']['checked'])) { + print ''; + } + + if (!empty($arrayfields['t.ref']['checked'])) { + print ''; + } + + if (!empty($arrayfields['t.fk_user_create']['checked'])) { + print ''; + } + + if (!empty($arrayfields['t.tms']['checked'])) { + print ''; + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields); + $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Status + if (!empty($arrayfields['t.fk_statut']['checked'])) { + print ''; + } + + // Action column + print ''; + print ''; + + // Field title + print ''; + if (!empty($arrayfields['t.datec']['checked'])) { + print_liste_field_titre($arrayfields['t.datec']['label'], $url_page_current, 't.datec', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['t.ref']['checked'])) { + print_liste_field_titre($arrayfields['t.ref']['label'], $url_page_current, 't.ref', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['t.fk_user_create']['checked'])) { + print_liste_field_titre($arrayfields['t.fk_user_create']['label'], $url_page_current, 't.fk_user_create', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['t.tms']['checked'])) { + print_liste_field_titre($arrayfields['t.tms']['label'], $url_page_current, 't.tms', '', $param, '', $sortfield, $sortorder); + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; + + // Hook fields + $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); + $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + if (!empty($arrayfields['t.fk_statut']['checked'])) { + print_liste_field_titre($arrayfields['t.fk_statut']['label'], $url_page_current, 't.fk_statut', '', $param, '', $sortfield, $sortorder); + } + print_liste_field_titre($selectedfields, $url_page_current, "", '', '', 'align="right"', $sortfield, $sortorder, 'center maxwidthsearch '); + print ''; + + while ($obj = $db->fetch_object($resql)) + { + print ''; + + // Date ticket + if (!empty($arrayfields['t.datec']['checked'])) { + print ''; + } + + // Ref + if (!empty($arrayfields['t.ref']['checked'])) { + print ''; + } + + // Message author + if (!empty($arrayfields['t.fk_user_create']['checked'])) { + print ''; + } + + if (!empty($arrayfields['t.tms']['checked'])) { + print ''; + } + + // Extra fields + if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if (!empty($arrayfields["ef.".$key]['checked'])) { + print 'getAlignFlag($key); + if ($align) { + print ' align="'.$align.'"'; + } + print '>'; + $tmpkey = 'options_'.$key; + print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); + print ''; + } + } + } + + // Statut + if (!empty($arrayfields['t.fk_statut']['checked'])) { + print ''; + } + + print ''; + + $i++; + print ''; + } + + print '
    '; + $selected = ($search_fk_status != "non_closed" ? $search_fk_status : ''); + //$object->printSelectStatus($selected); + print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
    '; + print dol_print_date($db->jdate($obj->datec), 'dayhour'); + print ''; + print $obj->ref; + print ''; + if ($obj->fk_user_create > 0) { + $user_create->firstname = (!empty($obj->user_create_firstname) ? $obj->user_create_firstname : ''); + $user_create->name = (!empty($obj->user_create_lastname) ? $obj->user_create_lastname : ''); + $user_create->id = (!empty($obj->fk_user_create) ? $obj->fk_user_create : ''); + print $user_create->getFullName($langs); + } else { + print $langs->trans('Email'); + } + print ''.dol_print_date($db->jdate($obj->tms), 'dayhour').''; + $object->fk_statut = $obj->fk_statut; + print $object->getLibStatut(2); + print '
    '; + print '
    '; + + print '"; + print ''; + } + } +} else { + print ''; +} + + +print "
    "; + +// End of page +htmlPrintOnlinePaymentFooter($mysoc, $langs, 0, $suffix, $object); + +llxFooter('', 'public'); + +$db->close(); diff --git a/htdocs/public/recruitment/view.php b/htdocs/public/recruitment/view.php new file mode 100644 index 00000000000..2b07d303aa9 --- /dev/null +++ b/htdocs/public/recruitment/view.php @@ -0,0 +1,327 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/public/recruitment/view.php + * \ingroup recruitment + * \brief Public file to show on job + */ + +if (!defined('NOLOGIN')) define("NOLOGIN", 1); // This means this output page does not require to be logged. +if (!defined('NOCSRFCHECK')) define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. +if (!defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("companies", "other", "recruitment")); + +// Get parameters +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'alpha'); +$email = GETPOST('email', 'alpha'); +$backtopage = ''; + +$ref = GETPOST('ref', 'alpha'); + +if (GETPOST('btn_view')) { + unset($_SESSION['email_customer']); +} +if (isset($_SESSION['email_customer'])) { + $email = $_SESSION['email_customer']; +} + +$object = new RecruitmentJobPosition($db); + +if (!$action) +{ + if (!$ref) + { + print $langs->trans('ErrorBadParameters')." - ref missing"; + exit; + } else { + $object->fetch('', $ref); + } +} + +// Define $urlwithroot +//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost. + + +/* + * Actions + */ + +if ($cancel) +{ + if (!empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + $action = 'view'; +} + +if ($action == "view" || $action == "presend" || $action == "close" || $action == "confirm_public_close" || $action == "add_message") { + $error = 0; + $display_ticket = false; + if (!strlen($ref)) { + $error++; + array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref"))); + $action = ''; + } + if (!strlen($email)) { + $error++; + array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Email"))); + $action = ''; + } else { + if (!isValidEmail($email)) { + $error++; + array_push($object->errors, $langs->trans("ErrorEmailInvalid")); + $action = ''; + } + } + + if (!$error) { + $ret = $object->fetch('', $ref); + } + + /* + if (!$error && $action == "add_message" && $display_ticket && GETPOSTISSET('btn_add_message')) + { + // TODO Add message... + $ret = $object->dao->newMessage($user, $action, 0, 1); + + + + + if (!$error) + { + $action = 'view'; + } + } + */ + + if ($error || $errors) { + setEventMessages($object->error, $object->errors, 'errors'); + if ($action == "add_message") + { + $action = 'presend'; + } else { + $action = ''; + } + } +} +//var_dump($action); +//$object->doActions($action); + +// Actions to send emails (for ticket, we need to manage the addfile and removefile only) +$triggersendname = 'CANDIDATURE_SENTBYMAIL'; +$paramname = 'id'; +$autocopy = 'MAIN_MAIL_AUTOCOPY_CANDIDATURE_TO'; // used to know the automatic BCC to add +$trackid = 'can'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; + + + +/* + * View + */ + +$head = ''; +if (!empty($conf->global->MAIN_RECRUITMENT_CSS_URL)) $head = ''."\n"; + +$conf->dol_hide_topmenu = 1; +$conf->dol_hide_leftmenu = 1; + +if (!$conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE) { + print '
    '.$langs->trans('PublicInterfaceForbidden').'
    '; + $db->close(); + exit(); +} + +$arrayofjs = array(); +$arrayofcss = array(); + +$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '
    ' : '').'
    '; +llxHeader($head, $langs->trans("PositionToBeFilled"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea); + + +print ''."\n"; +print '
    '."\n"; +print '
    '."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''; +print "\n"; +print ''."\n"; + +print ''."\n"; + +// Show logo (search order: logo defined by ONLINE_SIGN_LOGO_suffix, then ONLINE_SIGN_LOGO_, then small company logo, large company logo, theme logo, common logo) +$width = 0; +// Define logo and logosmall +$logosmall = $mysoc->logo_small; +$logo = $mysoc->logo; +$paramlogo = 'ONLINE_RECRUITMENT_LOGO_'.$suffix; +if (!empty($conf->global->$paramlogo)) $logosmall = $conf->global->$paramlogo; +elseif (!empty($conf->global->ONLINE_RECRUITMENT_LOGO)) $logosmall = $conf->global->ONLINE_RECRUITMENT_LOGO_; +//print ''."\n"; +// Define urllogo +$urllogo = ''; +$urllogofull = ''; +if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) +{ + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); + $width = 150; +} elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) +{ + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); + $width = 150; +} +// Output html code for logo +if ($urllogo) +{ + print '
    '; + print '
    '; + print ''; + print '
    '; + if (empty($conf->global->MAIN_HIDE_POWERED_BY)) { + print ''; + } + print '
    '; +} + +// Output introduction text +$text = ''; +if (!empty($conf->global->RECRUITMENT_NEWFORM_TEXT)) +{ + $langs->load("recruitment"); + if (preg_match('/^\((.*)\)$/', $conf->global->RECRUITMENT_NEWFORM_TEXT, $reg)) $text .= $langs->trans($reg[1])."
    \n"; + else $text .= $conf->global->RECRUITMENT_NEWFORM_TEXT."
    \n"; + $text = ''."\n"; +} +if (empty($text)) +{ + $text .= ''."\n"; + $text .= ''."\n"; +} +print $text; + +// Output payment summary form +print ''."\n"; + +print '

    '.$text.'

    '.$langs->trans("JobOfferToBeFilled", $mysoc->name); + $text .= '   -   '.$mysoc->name.''; + $text .= '   -   '.dol_print_date($object->date_creation); + $text .= '

    '.$object->label.'


    '; + +print '
    '; +print '
    '.$langs->trans("ThisIsInformationOnJobPosition").' :
    '."\n"; + +$error = 0; +$var = false; +$found = true; + +print '
    '; + +// Label +print $langs->trans("Label").' : '; +print ''.$object->label.'
    '; + +// Date +print $langs->trans("DateExpected").' : '; +print ''; +if ($object->date_planned > $now) { + print dol_print_date($object->date_planned, 'day'); +} else { + print $langs->trans("ASAP"); +} +print '
    '; + +// Remuneration +print $langs->trans("Remuneration").' : '; +print ''; +print $object->remuneration_suggested; +print '
    '; + +// Contact +$tmpuser = new User($db); +$tmpuser->fetch($object->fk_user_recruiter); + +print $langs->trans("ContactForRecruitment").' : '; +$emailforcontact = $object->email_recruiter; +if (empty($emailforcontact)) { + $emailforcontact = $tmpuser->email; + if (empty($emailforcontact)) { + $emailforcontact = $mysoc->email; + } +} +print ''; +print $tmpuser->getFullName(-1); +print ' - '.img_picto('', 'email', 'class="paddingrightonly"').dol_print_email($emailforcontact); +print ''; +print '
    '; + + +print '
    '; + +// Description + +$text = $object->description; +print $text; +print ''; + +print '
    '."\n"; +print "\n"; + + +if ($action != 'dosubmit') +{ + if ($found && !$error) // We are in a management option and no error + { + } else { + dol_print_error_email('ERRORNEWONLINESIGN'); + } +} else { + // Print +} + +print '
    '."\n"; +print '
    '."\n"; +print '
    '."\n"; +print '
    '; + + +htmlPrintOnlinePaymentFooter($mysoc, $langs); + +llxFooter('', 'public'); + +$db->close(); diff --git a/htdocs/public/ticket/img/bg_ticket.png b/htdocs/public/ticket/img/bg_ticket.png deleted file mode 100644 index c5fd05c662a..00000000000 Binary files a/htdocs/public/ticket/img/bg_ticket.png and /dev/null differ diff --git a/htdocs/public/ticket/img/index.html b/htdocs/public/ticket/img/index.html deleted file mode 100644 index 8b137891791..00000000000 --- a/htdocs/public/ticket/img/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/htdocs/public/ticket/list.php b/htdocs/public/ticket/list.php index 40e6e55cb33..922cb498c5d 100644 --- a/htdocs/public/ticket/list.php +++ b/htdocs/public/ticket/list.php @@ -18,7 +18,7 @@ /** * \file htdocs/public/ticket/list.php * \ingroup ticket - * \brief Public file to add and manage ticket + * \brief Public file to list tickets */ if (!defined('NOCSRFCHECK')) { @@ -201,7 +201,7 @@ if ($action == "view_ticketlist") // fetch optionals attributes and labels $extrafields = new ExtraFields($db); - $extrafields->fetch_name_optionals_label('ticket'); + $extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); diff --git a/htdocs/public/ticket/view.php b/htdocs/public/ticket/view.php index ee8865170af..800141244f0 100644 --- a/htdocs/public/ticket/view.php +++ b/htdocs/public/ticket/view.php @@ -19,7 +19,7 @@ /** * \file htdocs/public/ticket/view.php * \ingroup ticket - * \brief Public file to add and manage ticket + * \brief Public file to show one ticket */ if (!defined('NOCSRFCHECK')) { diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index f4cbb08ee9e..826c61de815 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -400,6 +400,7 @@ class Reception extends CommonObject $this->date_reception = $this->db->jdate($obj->date_reception); // Date real $this->date_delivery = $this->db->jdate($obj->date_delivery); // Date planed $this->fk_delivery_address = $obj->fk_address; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->shipping_method_id = $obj->fk_shipping_method; $this->tracking_number = $obj->tracking_number; @@ -1157,6 +1158,8 @@ class Reception extends CommonObject $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { diff --git a/htdocs/recruitment/COPYING b/htdocs/recruitment/COPYING deleted file mode 100644 index 94a04532226..00000000000 --- a/htdocs/recruitment/COPYING +++ /dev/null @@ -1,621 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/htdocs/recruitment/admin/public_interface.php b/htdocs/recruitment/admin/public_interface.php new file mode 100644 index 00000000000..f8985507081 --- /dev/null +++ b/htdocs/recruitment/admin/public_interface.php @@ -0,0 +1,194 @@ + + * Copyright (C) 2006-2020 Laurent Destailleur + * Copyright (C) 2006-2012 Regis Houssin + * Copyright (C) 2011 Juanjo Menent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/recruitment/admin/public_interface.php + * \ingroup recruitment + * \brief File of main public page for open job position + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/lib/recruitment.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("admin", "recruitment")); + +$action = GETPOST('action', 'alpha'); + +if (!$user->admin) accessforbidden(); + +$error = 0; + + +/* + * Actions + */ + +if ($action == 'setRECRUITMENT_ENABLE_PUBLIC_INTERFACE') { + if (GETPOST('value')) dolibarr_set_const($db, 'RECRUITMENT_ENABLE_PUBLIC_INTERFACE', 1, 'chaine', 0, '', $conf->entity); + else dolibarr_set_const($db, 'RECRUITMENT_ENABLE_PUBLIC_INTERFACE', 0, 'chaine', 0, '', $conf->entity); +} + +if ($action == 'update') { + $public = GETPOST('RECRUITMENT_ENABLE_PUBLIC_INTERFACE'); + + $res = dolibarr_set_const($db, "RECRUITMENT_ENABLE_PUBLIC_INTERFACE", $public, 'chaine', 0, '', $conf->entity); + + if (!$res > 0) $error++; + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} + + +/* + * View + */ + +$form = new Form($db); + +//$help_url = 'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros'; +$help_url = ''; +llxHeader('', $langs->trans("RecruitmentSetup"), $help_url); + + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("RecruitmentSetup"), $linkback, 'title_setup'); + +$head = recruitmentAdminPrepareHead(); + + + +print '
    '; +print ''; +print ''; + +dol_fiche_head($head, 'publicurl', '', -1, ''); + + +print ''.$langs->trans("PublicInterfaceRecruitmentDesc").'

    '; + + +$enabledisablehtml = $langs->trans("EnablePublicRecruitmentPages").' '; +if (empty($conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE)) { + // Button off, click to enable + $enabledisablehtml .= ''; + $enabledisablehtml .= img_picto($langs->trans("Disabled"), 'switch_off'); + $enabledisablehtml .= ''; +} else { + // Button on, click to disable + $enabledisablehtml .= ''; + $enabledisablehtml .= img_picto($langs->trans("Activated"), 'switch_on'); + $enabledisablehtml .= ''; +} +print $enabledisablehtml; +print ''; + + +print '
    '; + +/* +if (!empty($conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE)) { + print '
    '; + + print ''; + + print ''; + print ''; + print ''; + print "\n"; + + // Force Type + $adht = new AdherentType($db); + print '\n"; + + // Amount + print '\n"; + + // Can edit + print '\n"; + + // Jump to an online payment page + print '\n"; + + print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '; + print $langs->trans("ForceMemberType"); + print ''; + $listofval = array(); + $listofval += $adht->liste_array(); + $forcetype = $conf->global->MEMBER_NEWFORM_FORCETYPE ?: -1; + print $form->selectarray("MEMBER_NEWFORM_FORCETYPE", $listofval, $forcetype, count($listofval) > 1 ? 1 : 0); + print "
    '; + print $langs->trans("DefaultAmount"); + print ''; + print ''; + print "
    '; + print $langs->trans("CanEditAmount"); + print ''; + print $form->selectyesno("MEMBER_NEWFORM_EDITAMOUNT", (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) ? $conf->global->MEMBER_NEWFORM_EDITAMOUNT : 0), 1); + print "
    '; + print $langs->trans("MEMBER_NEWFORM_PAYONLINE"); + print ''; + $listofval = array(); + $listofval['-1'] = $langs->trans('No'); + $listofval['all'] = $langs->trans('Yes').' ('.$langs->trans("VisitorCanChooseItsPaymentMode").')'; + if (!empty($conf->paybox->enabled)) $listofval['paybox'] = 'Paybox'; + if (!empty($conf->paypal->enabled)) $listofval['paypal'] = 'PayPal'; + if (!empty($conf->stripe->enabled)) $listofval['stripe'] = 'Stripe'; + print $form->selectarray("MEMBER_NEWFORM_PAYONLINE", $listofval, (!empty($conf->global->MEMBER_NEWFORM_PAYONLINE) ? $conf->global->MEMBER_NEWFORM_PAYONLINE : ''), 0); + print "
    '; + + print '
    '; + print ''; + print '
    '; +} +*/ + +dol_fiche_end(); + +print '
    '; + +/* +if (!empty($conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE)) { + print '
    '; + //print $langs->trans('FollowingLinksArePublic').'
    '; + print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').':
    '; + if ($conf->multicompany->enabled) { + $entity_qr = '?entity='.$conf->entity; + } else { + $entity_qr = ''; + } + + // Define $urlwithroot + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + print ''.$urlwithroot.'/public/members/new.php'.$entity_qr.''; +} +*/ + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/recruitment/admin/setup.php b/htdocs/recruitment/admin/setup.php index 7de9764c1aa..562531262f9 100644 --- a/htdocs/recruitment/admin/setup.php +++ b/htdocs/recruitment/admin/setup.php @@ -40,7 +40,7 @@ global $langs, $user; // Libraries require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; -require_once '../lib/recruitment.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/lib/recruitment.lib.php'; require_once DOL_DOCUMENT_ROOT."/recruitment/class/recruitmentjobposition.class.php"; // Translations @@ -194,10 +194,10 @@ print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); // Configuration header $head = recruitmentAdminPrepareHead(); -dol_fiche_head($head, 'settings', '', -1, "object_recruitment"); +dol_fiche_head($head, 'settings', '', -1, ''); // Setup page goes here -echo ''.$langs->trans("RecruitmentSetupPage").'

    '; +//echo ''.$langs->trans("RecruitmentSetupPage").'

    '; if ($action == 'edit') diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php new file mode 100644 index 00000000000..4a18ddf85fb --- /dev/null +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -0,0 +1,1044 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/recruitmentcandidature.class.php + * \ingroup recruitment + * \brief This file is a CRUD class file for RecruitmentCandidature (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for RecruitmentCandidature + */ +class RecruitmentCandidature extends CommonObject +{ + /** + * @var string ID to identify managed object. + */ + public $element = 'recruitmentcandidature'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'recruitment_recruitmentcandidature'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for recruitmentcandidature. Must be the part after the 'object_' into object_recruitmentcandidature.png + */ + public $picto = 'recruitmentcandidature@recruitment'; + + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_CANCELED = 9; + + + /** + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' is the CSS style to use on field. For example: 'maxwidth200' + * 'help' is a string visible as a tooltip on field + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), + 'fk_recruitmentjobposition' => array('type'=>'integer:RecruitmentJobPosition:recruitment/class/recruitment_recruitmentjobposition.class.php', 'label'=>'Job', 'enabled'=>'1', 'position'=>15, 'notnull'=>1, 'visible'=>1, 'index'=>1), + 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3,), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), + 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '9'=>'Canceled'),), + 'firstname' => array('type'=>'varchar(128)', 'label'=>'Firstname', 'enabled'=>'1', 'position'=>20, 'notnull'=>0, 'visible'=>1,), + 'lastname' => array('type'=>'varchar(128)', 'label'=>'Lastname', 'enabled'=>'1', 'position'=>21, 'notnull'=>0, 'visible'=>1,), + 'remuneration_requested' => array('type'=>'integer', 'label'=>'RequestedRemuneration', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>1,), + 'remuneration_proposed' => array('type'=>'integer', 'label'=>'ProposedRemuneration', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>1,), + 'fk_recruitment_origin' => array('type'=>'integer:CRecruitmentOrigin:recruitment/class/recruitment_crecruitmentorigin.class.php', 'label'=>'Origin', 'enabled'=>'1', 'position'=>45, 'visible'=>1, 'index'=>1), + ); + public $rowid; + public $ref; + public $fk_recruitmentjobposition; + public $description; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + public $model_pdf; + public $status; + public $firstname; + public $lastname; + public $remuneration_requested; + public $remuneration_proposed; + public $fk_recruitment_origin; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'recruitment_recruitmentcandidatureline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + //public $fk_element = 'fk_recruitmentcandidature'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'RecruitmentCandidatureline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables = array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + //protected $childtablesoncascade = array('recruitment_recruitmentcandidaturedet'); + + /** + * @var RecruitmentCandidatureLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->recruitment->recruitmentcandidature->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + return $this->createCommon($user, $notrigger); + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetchCommon($fromid); + if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines(); + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + + // Clear fields + $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default']; + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + $object->status = self::STATUS_DRAFT; + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) + { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) + { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) + { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->createCommon($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) + { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) + { + $error++; + } + } + + if (!$error) + { + // copy external contacts if same company + if (property_exists($this, 'socid') && $this->socid == $object->socid) + { + if ($this->copy_linked_contact($object, 'external') < 0) + $error++; + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key.'='.$value; + } elseif (strpos($key, 'date') !== false) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' '.$this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) + { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) + { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) + { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->recruitmentcandidature->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->recruitmentcandidature->recruitmentcandidature_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life + { + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."',"; + if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; + $sql .= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) + { + // Call trigger + $result = $this->call_trigger('RECRUITMENTCANDIDATURE_VALIDATE', $user); + if ($result < 0) $error++; + // End call triggers + } + } + + if (!$error) + { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) + { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { $error++; $this->error = $this->db->lasterror(); } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$oldref; + $dirdest = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref; + if (!$error && file_exists($dirsource)) + { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) + { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) + { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) + { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) + { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->status <= self::STATUS_DRAFT) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->recruitment_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTCANDIDATURE_UNVALIDATE'); + } + + /** + * Set cancel status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function cancel($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_VALIDATED) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->recruitment_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTCANDIDATURE_CLOSE'); + } + + /** + * Set back to validated status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, 0=Nothing done, >0 if OK + */ + public function reopen($user, $notrigger = 0) + { + // Protection + if ($this->status != self::STATUS_CANCELED) + { + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->recruitment->recruitment_advance->validate)))) + { + $this->error='Permission denied'; + return -1; + }*/ + + return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTCANDIDATURE_REOPEN'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + + $result = ''; + + $label = ''.$langs->trans("RecruitmentCandidature").''; + $label .= '
    '; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + if (isset($this->status)) { + $label .= '
    '.$langs->trans("Status").": ".$this->getLibStatut(5); + } + + $url = dol_buildpath('/recruitment/recruitmentcandidature_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; + if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; + } + + $linkclose = ''; + if (empty($notooltip)) + { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label = $langs->trans("ShowRecruitmentCandidature"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + + $linkstart = ''; + $linkend = ''; + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
    No photo
    '; + } else { + $result .= '
    No photo
    '; + } + + $result .= '
    '; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) $result .= $this->ref; + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('recruitmentcandidaturedao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $result = $hookmanager->resPrint; + else $result .= $hookmanager->resPrint; + + return $result; + } + + /** + * Return label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) + { + global $langs; + //$langs->load("recruitment@recruitment"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Enabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Disabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + if ($status == self::STATUS_CANCELED) $statusType = 'status6'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql .= ' fk_user_creat, fk_user_modif'; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql .= ' WHERE t.rowid = '.$id; + $result = $this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new RecruitmentCandidatureLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_recruitmentcandidature = '.$this->id)); + + if (is_numeric($result)) + { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("recruitment@recruitment"); + + if (empty($conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON)) { + $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON = 'mod_recruitmentcandidature_standard'; + } + + if (!empty($conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON)) + { + $mybool = false; + + $file = $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON.".php"; + $classname = $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/recruitment/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) + { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') + { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 1; + + $langs->load("recruitment@recruitment"); + + if (!dol_strlen($modele)) { + $modele = 'standard_recruitmentcandidature'; + + if ($this->modelpdf) { + $modele = $this->modelpdf; + } elseif (!empty($conf->global->RECRUITMENTCANDIDATURE_ADDON_PDF)) { + $modele = $conf->global->RECRUITMENTCANDIDATURE_ADDON_PDF; + } + } + + $modelpath = "core/modules/recruitment/doc/"; + + if ($includedocgeneration) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} + + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + +/** + * Class RecruitmentCandidatureLine. You can also remove this and generate a CRUD class for lines objects. + */ +class RecruitmentCandidatureLine extends CommonObjectLine +{ + // To complete with content of an object RecruitmentCandidatureLine + // We should have a field rowid, fk_recruitmentcandidature and position + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } +} diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index adc33ab638d..aab39e4e433 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -45,7 +45,7 @@ class RecruitmentJobPosition extends CommonObject * @var int Does this object support multicompany module ? * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table */ - public $ismultientitymanaged = 0; + public $ismultientitymanaged = 1; /** * @var int Does object support extrafields ? 0=No, 1=Yes @@ -96,14 +96,17 @@ class RecruitmentJobPosition extends CommonObject public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'comment'=>"Id"), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'position'=>5, 'notnull'=>1, 'default'=>'1', 'index'=>1), 'label' => array('type'=>'varchar(255)', 'label'=>'JobLabel', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth500', 'showoncombobox'=>'1', 'autofocusoncreate'=>1), 'qty' => array('type'=>'integer', 'label'=>'NbOfEmployeesExpected', 'enabled'=>'1', 'position'=>45, 'notnull'=>1, 'visible'=>1, 'default'=>'1', 'isameasure'=>'1', 'css'=>'maxwidth75imp',), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>'1', 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1,), - 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid',), + 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>1, 'visible'=>1, 'foreignkey'=>'user.rowid',), + 'email_recruiter' => array('type'=>'varchar(255)', 'label'=>'EmailRecruiter', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>-1, 'help'=>'ToUseAGenericEmail'), 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid',), 'fk_establishment' => array('type'=>'integer:Establishment:hrm/class/establishment.class.php', 'label'=>'Establishment', 'enabled'=>'$conf->hrm->enabled', 'position'=>56, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'establishment.rowid',), 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'WorkPlace', 'enabled'=>'1', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner",), 'date_planned' => array('type'=>'date', 'label'=>'DateExpected', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1,), + 'remuneration_suggested' => array('type'=>'varchar(255)', 'label'=>'Remuneration', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>1,), 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>3,), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>101, 'notnull'=>0, 'visible'=>0,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>102, 'notnull'=>0, 'visible'=>0,), @@ -118,11 +121,13 @@ class RecruitmentJobPosition extends CommonObject ); public $rowid; public $ref; + public $entity; public $label; public $qty; public $fk_soc; public $fk_project; public $fk_user_recruiter; + public $email_recruiter; public $fk_user_supervisor; public $fk_establishment; public $date_planned; @@ -799,11 +804,11 @@ class RecruitmentJobPosition extends CommonObject $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft'); $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated'); $this->labelStatus[self::STATUS_RECRUITED] = $langs->trans('Recruited'); - $this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); + $this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Canceled'); $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft'); $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Validated'); $this->labelStatusShort[self::STATUS_RECRUITED] = $langs->trans('Recruited'); - $this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Disabled'); + $this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Canceled'); } $statusType = 'status'.$status; @@ -884,18 +889,7 @@ class RecruitmentJobPosition extends CommonObject { $this->lines = array(); - $objectline = new RecruitmentJobPositionLine($this->db); - $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_recruitmentjobposition = '.$this->id)); - - if (is_numeric($result)) - { - $this->error = $this->error; - $this->errors = $this->errors; - return $result; - } else { - $this->lines = $result; - return $this->lines; - } + return $this->lines; } /** @@ -1026,12 +1020,3 @@ class RecruitmentJobPosition extends CommonObject return $error; } } - -/** - * Class RecruitmentJobPositionLine. You can also remove this and generate a CRUD class for lines objects. - */ -class RecruitmentJobPositionLine -{ - // To complete with content of an object RecruitmentJobPositionLine - // We should have a field rowid, fk_recruitmentjobposition and position -} diff --git a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php index 580b3141d5c..cc28ea8978b 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php @@ -358,10 +358,10 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio $pdf->SetDrawColor(128, 128, 128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("JobPosition")); + $pdf->SetSubject($object->label); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("JobPosition")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$object->label." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); // Set certificate @@ -872,11 +872,11 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio $pdf->SetFont('', 'B', $default_font_size + 3); $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("JobPosition"); - if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title = $object->label; + /*if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { $title .= ' - '; $title .= $outputlangsbis->transnoentities("JobPosition"); - } + }*/ $pdf->MultiCell($w, 3, $title, '', 'R'); $pdf->SetFont('', 'B', $default_font_size); diff --git a/htdocs/recruitment/lib/recruitment.lib.php b/htdocs/recruitment/lib/recruitment.lib.php index ad03a4b30d1..44f356e8061 100644 --- a/htdocs/recruitment/lib/recruitment.lib.php +++ b/htdocs/recruitment/lib/recruitment.lib.php @@ -40,12 +40,10 @@ function recruitmentAdminPrepareHead() $head[$h][2] = 'settings'; $h++; - /* - $head[$h][0] = dol_buildpath("/recruitment/admin/about.php", 1); - $head[$h][1] = $langs->trans("About"); - $head[$h][2] = 'about'; + $head[$h][0] = dol_buildpath("/recruitment/admin/public_interface.php", 1); + $head[$h][1] = $langs->trans("PublicUrl"); + $head[$h][2] = 'publicurl'; $h++; - */ // Show more tabs from modules // Entries must be declared in modules descriptor with line diff --git a/htdocs/recruitment/lib/recruitment_recruitmentjobposition.lib.php b/htdocs/recruitment/lib/recruitment_recruitmentjobposition.lib.php index 052f4274526..a5739a53153 100644 --- a/htdocs/recruitment/lib/recruitment_recruitmentjobposition.lib.php +++ b/htdocs/recruitment/lib/recruitment_recruitmentjobposition.lib.php @@ -43,7 +43,7 @@ function recruitmentjobpositionPrepareHead($object) $head[$h][0] = dol_buildpath("/recruitment/recruitmentjobposition_candidature.php", 1).'?id='.$object->id; $head[$h][1] = $langs->trans("Candidatures"); - $head[$h][2] = 'candidature'; + $head[$h][2] = 'candidatures'; $h++; if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) @@ -88,3 +88,40 @@ function recruitmentjobpositionPrepareHead($object) return $head; } + + +/** + * Return string with full Url + * + * @param int $mode 0=True url, 1=Url formated with colors + * @param string $ref Ref of object + * @param string $localorexternal 0=Url for browser, 1=Url for external access + * @return string Url string + */ +function getPublicJobPositionUrl($mode, $ref = '', $localorexternal = 0) +{ + global $conf, $dolibarr_main_url_root; + + $ref = str_replace(' ', '', $ref); + $out = ''; + + // Define $urlwithroot + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + $urltouse = DOL_MAIN_URL_ROOT; + if ($localorexternal) $urltouse = $urlwithroot; + + $out = $urltouse.'/public/recruitment/view.php?ref='.($mode ? '' : '').$ref.($mode ? '' : ''); + /*if (!empty($conf->global->RECRUITMENT_SECURITY_TOKEN)) + { + if (empty($conf->global->RECRUITMENT_SECURITY_TOKEN)) $out .= '&securekey='.$conf->global->RECRUITMENT_SECURITY_TOKEN; + else $out .= '&securekey='.dol_hash($conf->global->RECRUITMENT_SECURITY_TOKEN, 2); + }*/ + + // For multicompany + if (!empty($out) && !empty($conf->multicompany->enabled)) $out .= "&entity=".$conf->entity; // Check the entity because we may have the same reference in several entities + + return $out; +} diff --git a/htdocs/recruitment/modulebuilder.txt b/htdocs/recruitment/modulebuilder.txt index 24ea0d6eac5..670a1774929 100644 --- a/htdocs/recruitment/modulebuilder.txt +++ b/htdocs/recruitment/modulebuilder.txt @@ -1,3 +1,3 @@ # DO NOT DELETE THIS FILE MANUALLY # File to flag module built using official module template. -# When this file is present into a module directory, you can edit it with the module builder tool. Use ModuleBuilder if you want to delete module. \ No newline at end of file +# When this file is present into a module directory, you can edit it with the module builder tool. \ No newline at end of file diff --git a/htdocs/recruitment/recruitmentindex.php b/htdocs/recruitment/recruitmentindex.php index 71a4cedcc69..cf1f0e7dee4 100644 --- a/htdocs/recruitment/recruitmentindex.php +++ b/htdocs/recruitment/recruitmentindex.php @@ -24,25 +24,12 @@ * \brief Home page of recruitment top menu */ -// Load Dolibarr environment -$res = 0; -// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) -if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; -// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME -$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; -while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } -if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; -if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; -// Try main.inc.php using relative path -if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; -if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; -if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; -if (!$res) die("Include of main fails"); - +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Load translation files required by the page -$langs->loadLangs(array("recruitment")); +$langs->loadLangs(array("recruitment", "boxes")); $action = GETPOST('action', 'alpha'); @@ -73,6 +60,7 @@ $now = dol_now(); $form = new Form($db); $formfile = new FormFile($db); +$staticrecruitmentjobposition = new RecruitmentJobPosition($db); llxHeader("", $langs->trans("RecruitmentArea")); @@ -81,6 +69,91 @@ print load_fiche_titre($langs->trans("RecruitmentArea"), '', 'object_recruitment print '
    '; +/* + * Statistics + */ + +if ($conf->use_javascript_ajax) +{ + $sql = "SELECT COUNT(t.rowid) as nb, status"; + $sql .= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as t"; + $sql .= " GROUP BY t.status"; + $sql .= " ORDER BY t.status ASC"; + $resql = $db->query($sql); + + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + + $totalnb = 0; + $dataseries = array(); + $colorseries = array(); + $vals = array(); + + include_once DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; + + while ($i < $num) + { + $obj = $db->fetch_object($resql); + if ($obj) + { + $vals[$obj->status] = $obj->nb; + + $totalnb += $obj->nb; + } + $i++; + } + $db->free($resql); + + print '
    '; + print ''; + print ''."\n"; + $listofstatus = array(0, 1, 3, 9); + foreach ($listofstatus as $status) + { + $dataseries[] = array($staticrecruitmentjobposition->LibStatut($status, 1), (isset($vals[$status]) ? (int) $vals[$status] : 0)); + if ($status == RecruitmentJobPosition::STATUS_DRAFT) $colorseries[$status] = '-'.$badgeStatus0; + if ($status == RecruitmentJobPosition::STATUS_VALIDATED) $colorseries[$status] = $badgeStatus1; + if ($status == RecruitmentJobPosition::STATUS_RECRUITED) $colorseries[$status] = $badgeStatus4; + if ($status == RecruitmentJobPosition::STATUS_CANCELED) $colorseries[$status] = $badgeStatus9; + + if (empty($conf->use_javascript_ajax)) + { + print ''; + print ''; + print ''; + print "\n"; + } + } + if ($conf->use_javascript_ajax) + { + print ''; + } + print "
    '.$langs->trans("Statistics").' - '.$langs->trans("Recruitment").'
    '.$staticrecruitmentjobposition->LibStatut($status, 0).''.(isset($vals[$status]) ? $vals[$status] : 0).'
    '; + + include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; + $dolgraph = new DolGraph(); + $dolgraph->SetData($dataseries); + $dolgraph->SetDataColor(array_values($colorseries)); + $dolgraph->setShowLegend(2); + $dolgraph->setShowPercent(1); + $dolgraph->SetType(array('pie')); + $dolgraph->SetHeight('200'); + $dolgraph->draw('idgraphstatus'); + print $dolgraph->show($totalnb ? 0 : 1); + + print '
    "; + print "
    "; + + print "
    "; + } else { + dol_print_error($db); + } +} + +print '
    '; + /* BEGIN MODULEBUILDER DRAFT MYOBJECT // Draft MyObject if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->read) @@ -89,7 +162,7 @@ if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->read) $sql = "SELECT c.rowid, c.ref, c.ref_client, c.total_ht, c.tva as total_tva, c.total_ttc, s.rowid as socid, s.nom as name, s.client, s.canvas"; $sql.= ", s.code_client"; - $sql.= " FROM ".MAIN_DB_PREFIX."commande as c"; + $sql.= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as c"; $sql.= ", ".MAIN_DB_PREFIX."societe as s"; if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; $sql.= " WHERE c.fk_soc = s.rowid"; @@ -167,18 +240,16 @@ print '
    '; $NBMAX = 3; $max = 3; -/* BEGIN MODULEBUILDER LASTMODIFIED MYOBJECT +/* BEGIN MODULEBUILDER LASTMODIFIED MYOBJECT */ // Last modified myobject -if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->read) +if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->recruitmentjobposition->read) { - $sql = "SELECT s.rowid, s.nom as name, s.client, s.datec, s.tms, s.canvas"; - $sql.= ", s.code_client"; - $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; + $sql = "SELECT s.rowid, s.ref, s.label, s.date_creation, s.tms"; + $sql.= " FROM ".MAIN_DB_PREFIX."recruitment_recruitmentjobposition as s"; if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE s.client IN (1, 2, 3)"; - $sql.= " AND s.entity IN (".getEntity($companystatic->element).")"; - if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; - if ($socid) $sql.= " AND s.rowid = $socid"; + $sql.= " WHERE s.entity IN (".getEntity($staticrecruitmentjobposition->element).")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; + if ($socid) $sql.= " AND s.fk_soc = $socid"; $sql .= " ORDER BY s.tms DESC"; $sql .= $db->plimit($max, 0); @@ -191,9 +262,7 @@ if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->read) print ''; print ''; print ''; print ''; print ''; @@ -202,34 +271,31 @@ if (! empty($conf->recruitment->enabled) && $user->rights->recruitment->read) while ($i < $num) { $objp = $db->fetch_object($resql); - $companystatic->id=$objp->rowid; - $companystatic->name=$objp->name; - $companystatic->client=$objp->client; - $companystatic->code_client = $objp->code_client; - $companystatic->code_fournisseur = $objp->code_fournisseur; - $companystatic->canvas=$objp->canvas; + $staticrecruitmentjobposition->id=$objp->rowid; + $staticrecruitmentjobposition->ref=$objp->ref; + $staticrecruitmentjobposition->label=$objp->label; + $staticrecruitmentjobposition->status = $objp->status; + $staticrecruitmentjobposition->date_creation = $objp->date_creation; + print ''; - print ''; + print ''; print '"; - print '"; + print '"; print ''; $i++; - - } $db->free($resql); - } - else - { + } else { print ''; } print "
    '; - if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastCustomersOrProspects",$max); - else if (! empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastModifiedProspects",$max); - else print $langs->trans("BoxTitleLastModifiedCustomers",$max); + print $langs->trans("BoxTitleLatestModifiedJobPositions", $max); print ''.$langs->trans("DateModificationShort").'
    '.$companystatic->getNomUrl(1,'customer',48).''.$staticrecruitmentjobposition->getNomUrl(1, '').''; - print $companystatic->getLibCustProspStatut(); print "'.dol_print_date($db->jdate($objp->tms),'day')."'.dol_print_date($db->jdate($objp->tms), 'day')."
    '.$langs->trans("None").'

    "; + } else { + dol_print_error($db); } } -*/ + print '
    '; diff --git a/htdocs/recruitment/recruitmentjobposition_agenda.php b/htdocs/recruitment/recruitmentjobposition_agenda.php index d841636c437..d54cec57e9a 100644 --- a/htdocs/recruitment/recruitmentjobposition_agenda.php +++ b/htdocs/recruitment/recruitmentjobposition_agenda.php @@ -150,26 +150,27 @@ if ($object->id > 0) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + */ // Project if (! empty($conf->projet->enabled)) { $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; + $morehtmlref .= $langs->trans('Project') . ' '; if ($permissiontoadd) { if ($action != 'classify') //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; - $morehtmlref.=' : '; + $morehtmlref .=' : '; if ($action == 'classify') { //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; + $morehtmlref .= '
    '; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
    '; } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); } } else { if (! empty($object->fk_project)) { @@ -180,7 +181,7 @@ if ($object->id > 0) $morehtmlref .= ''; } } - }*/ + } $morehtmlref .= '
    '; diff --git a/htdocs/recruitment/recruitmentjobposition_candidature.php b/htdocs/recruitment/recruitmentjobposition_candidature.php new file mode 100644 index 00000000000..d0e15827c2e --- /dev/null +++ b/htdocs/recruitment/recruitmentjobposition_candidature.php @@ -0,0 +1,563 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file recruitmentjobposition_candidature.php + * \ingroup recruitment + * \brief Page to see/add candidatures + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK','1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT','auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE','aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP','none'); // Disable all Content Security Policies + + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +dol_include_once('/recruitment/class/recruitmentjobposition.class.php'); +dol_include_once('/recruitment/lib/recruitment_recruitmentjobposition.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("recruitment", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'recruitmentjobpositioncard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +//$lineid = GETPOST('lineid', 'int'); + +// Initialize technical objects +$object = new RecruitmentJobPosition($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->recruitment->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('recruitmentjobpositioncard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = trim(GETPOST("search_all", 'alpha')); +$search = array(); +foreach ($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key, 'alpha')) $search[$key] = GETPOST('search_'.$key, 'alpha'); +} + +if (empty($action) && empty($id) && empty($ref)) $action = 'view'; + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + + +$permissiontoread = $user->rights->recruitment->recruitmentjobposition->read; +$permissiontoadd = $user->rights->recruitment->recruitmentjobposition->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->recruitment->recruitmentjobposition->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); +$permissionnote = $user->rights->recruitment->recruitmentjobposition->write; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->recruitment->recruitmentjobposition->write; // Used by the include of actions_dellink.inc.php +$upload_dir = $conf->recruitment->multidir_output[isset($object->entity) ? $object->entity : 1]; + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->statut == $object::STATUS_DRAFT) ? 1 : 0); +//$result = restrictedArea($user, 'recruitment', $object->id, '', '', 'fk_soc', 'rowid', $isdraft); + +//if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + $error = 0; + + $backurlforlist = dol_buildpath('/recruitment/recruitmentjobposition_list.php', 1); + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist; + else $backtopage = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); + } + } + $triggermodname = 'RECRUITMENT_RECRUITMENTJOBPOSITION_MODIFY'; // Name of trigger action code to execute when we modify record + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Actions when linking object each other + include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + + // Action to move up and down lines of object + //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + if ($action == 'set_thirdparty' && $permissiontoadd) + { + $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, 'RECRUITMENTJOBPOSITION_MODIFY'); + } + if ($action == 'classin' && $permissiontoadd) + { + $object->setProject(GETPOST('projectid', 'int')); + } + + // Actions to send emails + $triggersendname = 'RECRUITMENTJOBPOSITION_SENTBYMAIL'; + $autocopy = 'MAIN_MAIL_AUTOCOPY_RECRUITMENTJOBPOSITION_TO'; + $trackid = 'recruitmentjobposition'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; +} + + + + +/* + * View + * + * Put here all code to build page + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$formproject = new FormProjets($db); + +$title = $langs->trans("PositionToBeFilled"); +$help_url = ''; +llxHeader('', $title, $help_url); + +// Part to create +if ($action == 'create') +{ + print load_fiche_titre($langs->trans("NewPositionToBeFilled"), '', 'object_'.$object->picto); + + print '
    '; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + // Set some default values + if (! GETPOSTISSET('fk_user_recruiter')) $_POST['fk_user_recruiter'] = $user->id; + + dol_fiche_head(array(), ''); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print '
    '."\n"; + + dol_fiche_end(); + + print '
    '; + print ''; + print '  '; + print ''; // Cancel for create does not post form if we don't know the backtopage + print '
    '; + + print '
    '; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') +{ + print load_fiche_titre($langs->trans("PositionToBeFilled"), '', 'object_'.$object->picto); + + print '
    '; + print ''; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + dol_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + + print '
    '; + + dol_fiche_end(); + + print '
    '; + print '   '; + print '
    '; + + print '
    '; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals(); + + $head = recruitmentjobpositionPrepareHead($object); + dol_fiche_head($head, 'candidatures', $langs->trans("RecruitmentCandidatures"), -1, $object->picto); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteRecruitmentJobPosition'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } + // Confirmation to delete line + if ($action == 'deleteline') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); + } + // Clone confirmation + if ($action == 'clone') { + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + } + + // Confirmation of action xxxx + if ($action == 'xxx') + { + $formquestion = array(); + /* + $forcecombo=0; + if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy + $formquestion = array( + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo)) + ); + */ + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + */ + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.=$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ''; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + } + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + print '
    '; + print ''."\n"; + + // Common attributes + $keyforbreak='description'; // We change column just after this field + unset($object->fields['fk_project']); // Hide field already shown in banner + //unset($object->fields['fk_soc']); // Hide field already shown in banner + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
    '; + print '
    '; + print '
    '; + + print '
    '; + + dol_fiche_end(); + + + /* + * Lines + */ + + if (!empty($object->table_element_line)) + { + // Show object lines + $result = $object->getLinesArray(); + + print '
    + + + + + '; + + if (!empty($conf->use_javascript_ajax) && $object->status == 0) { + include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; + } + + print '
    '; + if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) + { + print ''; + } + + if (!empty($object->lines)) + { + $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1); + } + + // Form to add new line + if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') + { + if ($action != 'editline') + { + // Add products/services form + $object->formAddObjectLine(1, $mysoc, $soc); + + $parameters = array(); + $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + } + } + + if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) + { + print '
    '; + } + print '
    '; + + print "
    \n"; + } + + + // Buttons for actions + + if ($action != 'presend' && $action != 'editline') { + print '
    '."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + // Send + if (empty($user->socid)) { + print ''.$langs->trans('SendMail').''."\n"; + } + + // Back to draft + if ($object->status == $object::STATUS_VALIDATED) + { + if ($permissiontoadd) + { + print ''.$langs->trans("SetToDraft").''; + } + } + + // Modify + if ($permissiontoadd) + { + print ''.$langs->trans("Modify").''."\n"; + } else { + print ''.$langs->trans('Modify').''."\n"; + } + + // Validate + if ($object->status == $object::STATUS_DRAFT) + { + if ($permissiontoadd) + { + if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) + { + print ''.$langs->trans("Validate").''; + } else { + $langs->load("errors"); + print ''.$langs->trans("Validate").''; + } + } + } + + // Clone + if ($permissiontoadd) + { + print ''.$langs->trans("ToClone").''."\n"; + } + + /* + if ($permissiontoadd) + { + if ($object->status == $object::STATUS_ENABLED) + { + print ''.$langs->trans("Disable").''."\n"; + } + else + { + print ''.$langs->trans("Enable").''."\n"; + } + } + if ($permissiontoadd) + { + if ($object->status == $object::STATUS_VALIDATED) + { + print ''.$langs->trans("Cancel").''."\n"; + } + else + { + print ''.$langs->trans("Re-Open").''."\n"; + } + } + */ + + // Delete (need delete permission, or if draft, just need create/modify permission) + if ($permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)) + { + print ''.$langs->trans('Delete').''."\n"; + } else { + print ''.$langs->trans('Delete').''."\n"; + } + } + print '
    '."\n"; + } + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') + { + print '
    '; + print ''; // ancre + + + print '
    '; + + + print '
    '; + } + + //Select mail models is same action as presend + if (GETPOST('modelselected')) $action = 'presend'; + + // Presend form + $modelmail = 'recruitmentjobposition'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->recruitment->dir_output; + $trackid = 'recruitmentjobposition'.$object->id; + + include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index 349624729e0..0763b5ca749 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -188,22 +188,6 @@ $title = $langs->trans("PositionToBeFilled"); $help_url = ''; llxHeader('', $title, $help_url); -// Example : Adding jquery code -print ''; - - // Part to create if ($action == 'create') { @@ -471,8 +455,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Back to draft - if ($object->status == $object::STATUS_VALIDATED) - { + if ($object->status == $object::STATUS_VALIDATED) { if ($permissiontoadd) { print ''.$langs->trans("SetToDraft").''; @@ -480,18 +463,15 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Modify - if ($permissiontoadd) - { + if ($permissiontoadd) { print ''.$langs->trans("Modify").''."\n"; } else { print ''.$langs->trans('Modify').''."\n"; } // Validate - if ($object->status == $object::STATUS_DRAFT) - { - if ($permissiontoadd) - { + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) { print ''.$langs->trans("Validate").''; @@ -503,39 +483,29 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Clone - if ($permissiontoadd) - { + if ($permissiontoadd) { print ''.$langs->trans("ToClone").''."\n"; } /* - if ($permissiontoadd) - { - if ($object->status == $object::STATUS_ENABLED) - { + if ($permissiontoadd) { + if ($object->status == $object::STATUS_ENABLED) { print ''.$langs->trans("Disable").''."\n"; - } - else - { + } else { print ''.$langs->trans("Enable").''."\n"; } - } + }*/ if ($permissiontoadd) { - if ($object->status == $object::STATUS_VALIDATED) - { - print ''.$langs->trans("Cancel").''."\n"; - } - else - { - print ''.$langs->trans("Re-Open").''."\n"; + if ($object->status == $object::STATUS_VALIDATED) { + print ''.$langs->trans("Cancel").''."\n"; + } else { + print ''.$langs->trans("Re-Open").''."\n"; } } - */ // Delete (need delete permission, or if draft, just need create/modify permission) - if ($permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)) - { + if ($permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)) { print ''.$langs->trans('Delete').''."\n"; } else { print ''.$langs->trans('Delete').''."\n"; @@ -572,6 +542,22 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $linktoelem = $form->showLinkToObjectBlock($object, null, array('recruitmentjobposition')); $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + // Show link to public job page + if ($object->status != RecruitmentJobPosition::STATUS_DRAFT) + { + print '
    '."\n"; + // Load translation files required by the page + $langs->loadLangs(array('recruitment')); + + $out = img_picto('', 'globe').' '.$langs->trans("PublicUrl").'
    '; + + $url = getPublicJobPositionUrl(0, $object->ref); + $out .= ''; + $out .= ''.img_picto('', 'globe').''; + $out .= ajax_autoselect("recruitmentjobpositionurl", 0); + + print $out; + } print '
    '; diff --git a/htdocs/recruitment/recruitmentjobposition_document.php b/htdocs/recruitment/recruitmentjobposition_document.php index be8be1bcf42..b549c22d632 100644 --- a/htdocs/recruitment/recruitmentjobposition_document.php +++ b/htdocs/recruitment/recruitmentjobposition_document.php @@ -136,37 +136,38 @@ if ($object->id) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; - if ($permissiontoadd) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref .= ': '.$proj->getNomUrl(); - } else { - $morehtmlref .= ''; - } - } - }*/ + */ + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref .= $langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref .=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
    '; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
    '; + } else { + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + } $morehtmlref .= '
    '; dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); diff --git a/htdocs/recruitment/recruitmentjobposition_list.php b/htdocs/recruitment/recruitmentjobposition_list.php index 1b6b978be8c..d97d4909ea8 100644 --- a/htdocs/recruitment/recruitmentjobposition_list.php +++ b/htdocs/recruitment/recruitmentjobposition_list.php @@ -127,7 +127,15 @@ $arrayfields = array(); foreach ($object->fields as $key => $val) { // If $val['visible']==0, then we never show the field - if (!empty($val['visible'])) $arrayfields['t.'.$key] = array('label'=>$val['label'], 'checked'=>(($val['visible'] < 0) ? 0 : 1), 'enabled'=>($val['enabled'] && ($val['visible'] != 3)), 'position'=>$val['position']); + if (!empty($val['visible'])) { + $visible = dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'] + ); + } } // Extra fields if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) diff --git a/htdocs/recruitment/recruitmentjobposition_note.php b/htdocs/recruitment/recruitmentjobposition_note.php index 41268ca1c6d..b8f873309d7 100644 --- a/htdocs/recruitment/recruitmentjobposition_note.php +++ b/htdocs/recruitment/recruitmentjobposition_note.php @@ -108,37 +108,38 @@ if ($id > 0 || !empty($ref)) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
    '.$langs->trans('Project') . ' '; - if ($permissiontoadd) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
    '; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.='
    '; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref .= ': '.$proj->getNomUrl(); - } else { - $morehtmlref .= ''; - } - } - }*/ + */ + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref .= $langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref .=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
    '; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
    '; + } else { + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + } $morehtmlref .= '
    '; diff --git a/htdocs/recruitment/test/phpunit/RecruitmentFunctionalTest.php b/htdocs/recruitment/test/phpunit/RecruitmentFunctionalTest.php deleted file mode 100644 index 0d4de50fe68..00000000000 --- a/htdocs/recruitment/test/phpunit/RecruitmentFunctionalTest.php +++ /dev/null @@ -1,304 +0,0 @@ - - * Copyright (C) 2020 Adminson Alicealalalamdskfldmjgdfgdfhfghgfh - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file test/phpunit/RecruitmentFunctionalTest.php - * \ingroup recruitment - * \brief Example Selenium test. - * - * Put detailed description here. - */ - -namespace test\functional; - -use PHPUnit_Extensions_Selenium2TestCase_WebDriverException; - -/** - * Class RecruitmentFunctionalTest - * - * Requires chromedriver for Google Chrome - * Requires geckodriver for Mozilla Firefox - * - * @fixme Firefox (Geckodriver/Marionette) support - * @todo Opera linux support - * @todo Windows support (IE, Google Chrome, Mozilla Firefox, Safari) - * @todo OSX support (Safari, Google Chrome, Mozilla Firefox) - * - * @package Testrecruitment - */ -class RecruitmentFunctionalTest extends \PHPUnit_Extensions_Selenium2TestCase -{ - // TODO: move to a global configuration file? - /** @var string Base URL of the webserver under test */ - protected static $base_url = 'http://dev.zenfusion.fr'; - /** - * @var string Dolibarr admin username - * @see authenticate - */ - protected static $dol_admin_user = 'admin'; - /** - * @var string Dolibarr admin password - * @see authenticate - */ - protected static $dol_admin_pass = 'admin'; - /** @var int Dolibarr module ID */ - private static $module_id = 500000; // TODO: autodetect? - - /** @var array Browsers to test with */ - public static $browsers = array( - array( - 'browser' => 'Google Chrome on Linux', - 'browserName' => 'chrome', - 'sessionStrategy' => 'shared', - 'desiredCapabilities' => array() - ), - // Geckodriver does not keep the session at the moment?! - // XPath selectors also don't seem to work - //array( - // 'browser' => 'Mozilla Firefox on Linux', - // 'browserName' => 'firefox', - // 'sessionStrategy' => 'shared', - // 'desiredCapabilities' => array( - // 'marionette' => true, - // ), - //) - ); - - /** - * Helper function to select links by href - * - * @param string $value Href - * @return mixed Helper string - */ - protected function byHref($value) - { - $anchor = null; - $anchors = $this->elements($this->using('tag name')->value('a')); - foreach ($anchors as $anchor) { - if (strstr($anchor->attribute('href'), $value)) { - break; - } - } - return $anchor; - } - - /** - * Global test setup - * @return void - */ - public static function setUpBeforeClass() - { - } - - /** - * Unit test setup - * @return void - */ - public function setUp() - { - $this->setSeleniumServerRequestsTimeout(3600); - $this->setBrowserUrl(self::$base_url); - } - - /** - * Verify pre conditions - * @return void - */ - protected function assertPreConditions() - { - } - - /** - * Handle Dolibarr authentication - * @return void - */ - private function authenticate() - { - try { - if ($this->byId('login')) { - $login = $this->byId('username'); - $login->clear(); - $login->value('admin'); - $password = $this->byId('password'); - $password->clear(); - $password->value('admin'); - $this->byId('login')->submit(); - } - } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { - // Login does not exist. Assume we are already authenticated - } - } - - /** - * Test enabling developer mode - * @return bool - */ - public function testEnableDeveloperMode() - { - $this->url('/admin/const.php'); - $this->authenticate(); - $main_features_level_path = '//input[@value="MAIN_FEATURES_LEVEL"]/following::input[@type="text"]'; - $main_features_level = $this->byXPath($main_features_level_path); - $main_features_level->clear(); - $main_features_level->value('2'); - $this->byName('update')->click(); - // Page reloaded, we need a new XPath - $main_features_level = $this->byXPath($main_features_level_path); - return $this->assertEquals('2', $main_features_level->value(), "MAIN_FEATURES_LEVEL value is 2"); - } - - /** - * Test enabling the module - * - * @depends testEnableDeveloperMode - * @return bool - */ - public function testModuleEnabled() - { - $this->url('/admin/modules.php'); - $this->authenticate(); - $module_status_image_path = '//a[contains(@href, "'.self::$module_id.'")]/img'; - $module_status_image = $this->byXPath($module_status_image_path); - if (strstr($module_status_image->attribute('src'), 'switch_off.png')) { - // Enable the module - $this->byHref('modRecruitment')->click(); - } else { - // Disable the module - $this->byHref('modRecruitment')->click(); - // Reenable the module - $this->byHref('modRecruitment')->click(); - } - // Page reloaded, we need a new Xpath - $module_status_image = $this->byXPath($module_status_image_path); - return $this->assertContains('switch_on.png', $module_status_image->attribute('src'), "Module enabled"); - } - - /** - * Test access to the configuration page - * - * @depends testModuleEnabled - * @return bool - */ - public function testConfigurationPage() - { - $this->url('/custom/recruitment/admin/setup.php'); - $this->authenticate(); - return $this->assertContains('recruitment/admin/setup.php', $this->url(), 'Configuration page'); - } - - /** - * Test access to the about page - * - * @depends testConfigurationPage - * @return bool - */ - public function testAboutPage() - { - $this->url('/custom/recruitment/admin/about.php'); - $this->authenticate(); - return $this->assertContains('recruitment/admin/about.php', $this->url(), 'About page'); - } - - /** - * Test about page is rendering Markdown - * - * @depends testAboutPage - * @return bool - */ - public function testAboutPageRendersMarkdownReadme() - { - $this->url('/custom/recruitment/admin/about.php'); - $this->authenticate(); - return $this->assertEquals( - 'Dolibarr Module Template (aka My Module)', - $this->byTag('h1')->text(), - "Readme title" - ); - } - - /** - * Test box is properly declared - * - * @depends testModuleEnabled - * @return bool - */ - public function testBoxDeclared() - { - $this->url('/admin/boxes.php'); - $this->authenticate(); - return $this->assertContains('recruitmentwidget1', $this->source(), "Box enabled"); - } - - /** - * Test trigger is properly enabled - * - * @depends testModuleEnabled - * @return bool - */ - public function testTriggerDeclared() - { - $this->url('/admin/triggers.php'); - $this->authenticate(); - return $this->assertContains( - 'interface_99_modRecruitment_RecruitmentTriggers.class.php', - $this->byTag('body')->text(), - "Trigger declared" - ); - } - - /** - * Test trigger is properly declared - * - * @depends testTriggerDeclared - * @return bool - */ - public function testTriggerEnabled() - { - $this->url('/admin/triggers.php'); - $this->authenticate(); - return $this->assertContains( - 'tick.png', - $this->byXPath('//td[text()="interface_99_modRecruitment_MyTrigger.class.php"]/following::img')->attribute('src'), - "Trigger enabled" - ); - } - - /** - * Verify post conditions - * @return void - */ - protected function assertPostConditions() - { - } - - /** - * Unit test teardown - * @return void - */ - public function tearDown() - { - } - - /** - * Global test teardown - * @return void - */ - public static function tearDownAfterClass() - { - } -} diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 52de4d190d1..c73020ae7ab 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1990,7 +1990,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''; } print ''; - if ($conf->browser->layout == 'phone') print ''; + print ''; print ''.$form->editfieldkey($langs->transcountry("LocalTax2IsUsed", $mysoc->country_code), 'localtax2assuj_value', '', $object, 0).''; print $form->selectyesno('localtax2assuj_value', $object->localtax2_assuj, 1); if (!isOnlyOneLocalTax(2)) diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 535d4e68967..1efe6287c66 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -490,6 +490,66 @@ class Thirdparties extends DolibarrApi } $this->company->oldcopy = clone $this->company; return $this->company->delete($id); + } + + /** + * Set new price level for the given thirdparty + * + * @param int $id ID of thirdparty + * @param int $priceLevel Price level to apply to thirdparty + * @return object Thirdparty data without useless information + * + * @url PUT {id}/setpricelevel + * + * @throws RestException 400 Price level out of bounds + * @throws RestException 401 Access not allowed for your login + * @throws RestException 404 Thirdparty not found + * @throws RestException 500 Error fetching/setting price level + * @throws RestException 501 Request needs modules "Thirdparties" and "Products" and setting Multiprices activated + */ + public function setThirdpartyPriceLevel($id, $priceLevel) + { + global $conf; + + if (empty($conf->societe->enabled)) { + throw new RestException(501, 'Module "Thirdparties" needed for this request'); + } + + if (empty($conf->product->enabled)) { + throw new RestException(501, 'Module "Products" needed for this request'); + } + + if (empty($conf->global->PRODUIT_MULTIPRICES)) { + throw new RestException(501, 'Multiprices features activation needed for this request'); + } + + if ($priceLevel < 1 || $priceLevel > $conf->global->PRODUIT_MULTIPRICES_LIMIT) { + throw new RestException(400, 'Price level must be between 1 and ' . $conf->global->PRODUIT_MULTIPRICES_LIMIT); + } + + if (empty(DolibarrApiAccess::$user->rights->societe->creer)) { + throw new RestException(401, 'Access to thirdparty ' . $id . ' not allowed for login '. DolibarrApiAccess::$user->login); + } + + $result = $this->company->fetch($id); + if ($result < 0) { + throw new RestException(404, 'Thirdparty ' . $id . ' not found'); + } + + if (empty($result)) { + throw new RestException(500, 'Error fetching thirdparty ' . $id, array_merge(array($this->company->error), $this->company->errors)); + } + + if (empty(DolibarrApi::_checkAccessToResource('societe', $this->company->id))) { + throw new RestException(401, 'Access to thirdparty ' . $id . ' not allowed for login ' . DolibarrApiAccess::$user->login); + } + + $result = $this->company->set_price_level($priceLevel, DolibarrApiAccess::$user); + if ($result <= 0) { + throw new RestException(500, 'Error setting new price level for thirdparty ' . $id, array($this->company->db->lasterror())); + } + + return $this->_cleanObjectDatas($this->company); } /** diff --git a/htdocs/societe/class/client.class.php b/htdocs/societe/class/client.class.php index be1d18836bc..f3cdd3c805b 100644 --- a/htdocs/societe/class/client.class.php +++ b/htdocs/societe/class/client.class.php @@ -1,6 +1,7 @@ * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2020 Open-Dsi * * 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 @@ -100,14 +101,14 @@ class Client extends Societe { global $langs; - $sql = "SELECT id, code, libelle as label FROM ".MAIN_DB_PREFIX."c_stcomm"; + $sql="SELECT id, code, libelle as label, picto FROM ".MAIN_DB_PREFIX."c_stcomm"; if ($active >= 0) $sql .= " WHERE active = ".$active; $resql = $this->db->query($sql); $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); - $this->cacheprospectstatus[$obj->id] = array('id'=>$obj->id, 'code'=>$obj->code, 'label'=> ($langs->trans("ST_".strtoupper($obj->code)) == "ST_".strtoupper($obj->code)) ? $obj->label : $langs->trans("ST_".strtoupper($obj->code))); + $this->cacheprospectstatus[$obj->id] = array('id'=>$obj->id, 'code'=>$obj->code, 'label'=>($langs->trans("ST_".strtoupper($obj->code))=="ST_".strtoupper($obj->code))?$obj->label:$langs->trans("ST_".strtoupper($obj->code)), 'picto'=>$obj->picto); $i++; } return 1; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index c3600ce75e0..a1b339ec297 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -16,6 +16,7 @@ * Copyright (C) 2018 Philippe Grand * Copyright (C) 2019-2020 Josep Lluís Amador * Copyright (C) 2019 Frédéric France + * Copyright (C) 2020 Open-Dsi * * 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 @@ -572,6 +573,12 @@ class Societe extends CommonObject */ public $stcomm_id; + /** + * Status prospect picto + * @var string + */ + public $stcomm_picto; + /** * Status prospect label * @var int @@ -1314,6 +1321,7 @@ class Societe extends CommonObject $sql .= ", fk_user_modif = ".($user->id > 0 ? $user->id : "null"); $sql .= ", fk_multicurrency = ".(int) $this->fk_multicurrency; $sql .= ", multicurrency_code = '".$this->db->escape($this->multicurrency_code)."'"; + $sql .= ", model_pdf = '".$this->db->escape($this->model_pdf)."'"; $sql .= " WHERE rowid = ".(int) $id; $resql = $this->db->query($sql); @@ -1488,10 +1496,10 @@ class Societe extends CommonObject $sql .= ', e.libelle as effectif'; $sql .= ', c.code as country_code, c.label as country'; $sql .= ', d.code_departement as state_code, d.nom as state'; - $sql .= ', st.libelle as stcomm'; + $sql .= ', st.libelle as stcomm, st.picto as stcomm_picto'; $sql .= ', te.code as typent_code'; $sql .= ', i.libelle as label_incoterms'; - $sql .= ', sr.remise_client'; + $sql .= ', sr.remise_client, model_pdf'; $sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_effectif as e ON s.fk_effectif = e.id'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid'; @@ -1561,6 +1569,7 @@ class Societe extends CommonObject $label = ($transcode != 'StatusProspect'.$obj->fk_stcomm ? $transcode : $obj->stcomm); $this->stcomm_id = $obj->fk_stcomm; // id status prospect $this->status_prospect_label = $label; // label status prospect + $this->stcomm_picto = $obj->stcomm_picto; // picto statut commercial $this->email = $obj->email; $this->socialnetworks = (array) json_decode($obj->socialnetworks, true); @@ -1627,6 +1636,7 @@ class Societe extends CommonObject $this->note = $obj->note_private; // TODO Deprecated for backward comtability $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->default_lang = $obj->default_lang; $this->logo = $obj->logo; @@ -1652,6 +1662,7 @@ class Societe extends CommonObject // multicurrency $this->fk_multicurrency = $obj->fk_multicurrency; $this->multicurrency_code = $obj->multicurrency_code; + $this->model_pdf = $obj->model_pdf; $result = 1; @@ -2732,7 +2743,7 @@ class Societe extends CommonObject * Return bank number property of thirdparty (label or rum) * * @param string $mode 'label' or 'rum' or 'format' - * @return string Bank number + * @return string Bank label or RUM or '' if no bank account found */ public function display_rib($mode = 'label') { @@ -2742,25 +2753,25 @@ class Societe extends CommonObject $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $this->id); - if ($mode == 'label') - { - return $bac->getRibLabel(true); - } elseif ($mode == 'rum') - { - if (empty($bac->rum)) - { - require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; - $prelevement = new BonPrelevement($this->db); - $bac->fetch_thirdparty(); - $bac->rum = $prelevement->buildRumNumber($bac->thirdparty->code_client, $bac->datec, $bac->id); + if ($bac->id > 0) { // If a bank account has been found for company $this->id + if ($mode == 'label') { + return $bac->getRibLabel(true); + } elseif ($mode == 'rum') { + if (empty($bac->rum)) { + require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; + $prelevement = new BonPrelevement($this->db); + $bac->fetch_thirdparty(); + $bac->rum = $prelevement->buildRumNumber($bac->thirdparty->code_client, $bac->datec, $bac->id); + } + return $bac->rum; + } elseif ($mode == 'format') { + return $bac->frstrecur; + } else { + return 'BadParameterToFunctionDisplayRib'; } - return $bac->rum; - } elseif ($mode == 'format') - { - return $bac->frstrecur; + } else { + return ''; } - - return 'BadParameterToFunctionDisplayRib'; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps @@ -3889,7 +3900,7 @@ class Societe extends CommonObject */ public function getLibProspCommStatut($mode = 0, $label = '') { - return $this->LibProspCommStatut($this->stcomm_id, $mode, $label); + return $this->LibProspCommStatut($this->stcomm_id, $mode, $label, $this->stcomm_picto); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps @@ -3899,45 +3910,45 @@ class Societe extends CommonObject * @param int|string $status Id or code for prospection status * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto * @param string $label Label to use for status for added status + * @param string $picto Name of image file to show ('filenew', ...) + * If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory. + * Example: picto.png if picto.png is stored into htdocs/theme/mytheme/img + * Example: picto.png@mymodule if picto.png is stored into htdocs/mymodule/img + * Example: /mydir/mysubdir/picto.png if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1) * @return string Label of prospection status */ - public function LibProspCommStatut($status, $mode = 0, $label = '') + public function LibProspCommStatut($status, $mode = 0, $label = '', $picto = '') { // phpcs:enable global $langs; $langs->load('customers'); - if ($mode == 2) - { - if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1).' '.$langs->trans("StatusProspect-1"); - elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0).' '.$langs->trans("StatusProspect0"); - elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1).' '.$langs->trans("StatusProspect1"); - elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2).' '.$langs->trans("StatusProspect2"); - elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3).' '.$langs->trans("StatusProspect3"); + if ($mode == 2) { + if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto).' '.$langs->trans("StatusProspect-1"); + elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto).' '.$langs->trans("StatusProspect0"); + elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto).' '.$langs->trans("StatusProspect1"); + elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto).' '.$langs->trans("StatusProspect2"); + elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto).' '.$langs->trans("StatusProspect3"); else { - return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label); + return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label); } - } - if ($mode == 3) - { - if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1); - elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0); - elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1); - elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2); - elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3); + } elseif ($mode == 3) { + if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto); + elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto); + elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto); + elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto); + elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto); else { - return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0); + return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto); } - } - if ($mode == 4) - { - if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1).' '.$langs->trans("StatusProspect-1"); - elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0).' '.$langs->trans("StatusProspect0"); - elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1).' '.$langs->trans("StatusProspect1"); - elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2).' '.$langs->trans("StatusProspect2"); - elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3).' '.$langs->trans("StatusProspect3"); + } elseif ($mode == 4) { + if ($status == '-1' || $status == 'ST_NO') return img_action($langs->trans("StatusProspect-1"), -1, $picto).' '.$langs->trans("StatusProspect-1"); + elseif ($status == '0' || $status == 'ST_NEVER') return img_action($langs->trans("StatusProspect0"), 0, $picto).' '.$langs->trans("StatusProspect0"); + elseif ($status == '1' || $status == 'ST_TODO') return img_action($langs->trans("StatusProspect1"), 1, $picto).' '.$langs->trans("StatusProspect1"); + elseif ($status == '2' || $status == 'ST_PEND') return img_action($langs->trans("StatusProspect2"), 2, $picto).' '.$langs->trans("StatusProspect2"); + elseif ($status == '3' || $status == 'ST_DONE') return img_action($langs->trans("StatusProspect3"), 3, $picto).' '.$langs->trans("StatusProspect3"); else { - return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label); + return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label); } } diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 4de868a1b27..71e214af5c0 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -10,6 +10,7 @@ * Copyright (C) 2017 Rui Strecht * Copyright (C) 2017 Juanjo Menent * Copyright (C) 2018 Nicolas ZABOURI + * Copyright (C) 2020 Open-Dsi * * This program is free software; you can redistribute it and/or modify @@ -392,7 +393,7 @@ if ($resql) $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.barcode, s.town, s.zip, s.datec, s.code_client, s.code_fournisseur, s.logo,"; $sql .= " s.entity,"; -$sql .= " st.libelle as stcomm, s.fk_stcomm as stcomm_id, s.fk_prospectlevel, s.prefix_comm, s.client, s.fournisseur, s.canvas, s.status as status,"; +$sql .= " st.libelle as stcomm, st.picto as stcomm_picto, s.fk_stcomm as stcomm_id, s.fk_prospectlevel, s.prefix_comm, s.client, s.fournisseur, s.canvas, s.status as status,"; $sql .= " s.email, s.phone, s.fax, s.url, s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4 as idprof4, s.idprof5 as idprof5, s.idprof6 as idprof6, s.tva_intra, s.fk_pays,"; $sql .= " s.tms as date_update, s.datec as date_creation,"; $sql .= " s.code_compta, s.code_compta_fournisseur, s.parent as fk_parent,"; @@ -1195,6 +1196,7 @@ while ($i < min($num, $limit)) print "".$obj->idprof6."\n"; if (!$i) $totalarray['nbfield']++; } + // VAT if (!empty($arrayfields['s.tva_intra']['checked'])) { print ""; @@ -1241,13 +1243,13 @@ while ($i < min($num, $limit)) { // Prospect status print '
    '; - print '
    '.$companystatic->LibProspCommStatut($obj->stcomm_id, 2, $prospectstatic->cacheprospectstatus[$obj->stcomm_id]['label']); + print '
    ' . $companystatic->LibProspCommStatut($obj->stcomm_id, 2, $prospectstatic->cacheprospectstatus[$obj->stcomm_id]['label'], $obj->stcomm_picto); print '
    -
    '; foreach ($prospectstatic->cacheprospectstatus as $key => $val) { $titlealt = 'default'; if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) $titlealt = $val['label']; - if ($obj->stcomm_id != $val['id']) print ''.img_action($titlealt, $val['code']).''; + if ($obj->stcomm_id != $val['id']) print '' . img_action($titlealt, $val['code'], $val['picto']) . ''; } print '
    '; if (!$i) $totalarray['nbfield']++; diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index d872c9dfef3..e02a41dab86 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -848,7 +848,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ''; print ''; print ''; - print ''; + print ''; print ''; } print ''; @@ -903,7 +903,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ''; print ''; print ''; - //print ''; + //print ''; print ''; } print ''; diff --git a/htdocs/societe/tpl/linesalesrepresentative.tpl.php b/htdocs/societe/tpl/linesalesrepresentative.tpl.php index 5b9078e6b76..9c6e485e97d 100644 --- a/htdocs/societe/tpl/linesalesrepresentative.tpl.php +++ b/htdocs/societe/tpl/linesalesrepresentative.tpl.php @@ -29,7 +29,7 @@ print $langs->trans('SalesRepresentatives'); print ''; if ($action != 'editsalesrepresentatives' && $user->rights->societe->creer) { print ''; - print 'id . '">' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; + print 'id . '">' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; print ''; } print ''; diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 907a741c288..6c268d40320 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -869,7 +869,7 @@ class SupplierProposal extends CommonObject } // Multicurrency - if (!empty($this->multicurrency_code)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code); + if (!empty($this->multicurrency_code)) list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $now); if (empty($this->fk_multicurrency)) { $this->multicurrency_code = $conf->currency; @@ -1244,6 +1244,7 @@ class SupplierProposal extends CommonObject $this->total_ttc = $obj->total; $this->socid = $obj->fk_soc; $this->fk_project = $obj->fk_project; + $this->model_pdf = $obj->model_pdf; $this->modelpdf = $obj->model_pdf; $this->note = $obj->note_private; // TODO deprecated $this->note_private = $obj->note_private; @@ -2284,6 +2285,8 @@ class SupplierProposal extends CommonObject $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE entity IN (".getEntity('product').")"; + $sql .= $this->db->plimit(100); + $resql = $this->db->query($sql); if ($resql) { @@ -2630,6 +2633,7 @@ class SupplierProposal extends CommonObject global $conf, $langs; $langs->load("supplier_proposal"); + $outputlangs->load("products"); if (!dol_strlen($modele)) { $modele = 'aurore'; diff --git a/htdocs/takepos/admin/bar.php b/htdocs/takepos/admin/bar.php index 3d4bd490dde..2ec623024c7 100644 --- a/htdocs/takepos/admin/bar.php +++ b/htdocs/takepos/admin/bar.php @@ -34,7 +34,8 @@ if (!$user->admin) accessforbidden(); $langs->loadLangs(array("admin", "cashdesk", "printing")); -global $db; +$res = 0; + /* * Actions @@ -44,9 +45,15 @@ if (GETPOST('action', 'alpha') == 'set') { $db->begin(); - dol_syslog("admin/cashdesk: level ".GETPOST('level', 'alpha')); + dol_syslog("admin/bar"); - if (!$res > 0) $error++; + $suplement_category = GETPOST('TAKEPOS_SUPPLEMENTS_CATEGORY', 'alpha'); + if ($suplement_category < 0) $suplement_category= 0; + + $res = dolibarr_set_const($db, "TAKEPOS_SUPPLEMENTS_CATEGORY", $suplement_category, 'chaine', 0, '', $conf->entity); + if ($res <= 0) { + $error++; + } if (!$error) { @@ -74,7 +81,6 @@ $linkback = ''.$langs->trans("BackT print load_fiche_titre($langs->trans("CashDeskSetup").' (TakePOS)', $linkback, 'title_setup'); $head = takepos_prepare_head(); dol_fiche_head($head, 'bar', 'TakePOS', -1, 'cash-register'); -print '
    '; // Mode @@ -93,120 +99,138 @@ function Floors() { '.$langs->trans("DefineTablePlan").'

    '; -print '

    '; - -print '
    '; -print ''; -print ''; -print ''; -print "\n"; - -if ($conf->global->TAKEPOS_BAR_RESTAURANT && $conf->global->TAKEPOS_PRINT_METHOD != "browser") { - print ''; - - print ''; -} - -print ''; - -print ''; - -if ($conf->global->TAKEPOS_SUPPLEMENTS) -{ - print '\n"; -} - -print ''; - -print ''; - -print '
    '.$langs->trans("Parameters").''.$langs->trans("Value").'
    '; - print $langs->trans("OrderPrinters").' ('.$langs->trans("Setup").')'; - print ''; - print ajax_constantonoff("TAKEPOS_ORDER_PRINTERS", array(), $conf->entity, 0, 0, 1, 0); - //print $form->selectyesno("TAKEPOS_ORDER_PRINTERS", $conf->global->TAKEPOS_ORDER_PRINTERS, 1); - print '
    '; - print $langs->trans("OrderNotes"); - print ''; - print ajax_constantonoff("TAKEPOS_ORDER_NOTES", array(), $conf->entity, 0, 0, 1, 0); - //print $form->selectyesno("TAKEPOS_ORDER_NOTES", $conf->global->TAKEPOS_ORDER_NOTES, 1); - print '
    '; -print $langs->trans("BasicPhoneLayout"); -print ''; -//print $form->selectyesno("TAKEPOS_PHONE_BASIC_LAYOUT", $conf->global->TAKEPOS_PHONE_BASIC_LAYOUT, 1); -print ajax_constantonoff("TAKEPOS_PHONE_BASIC_LAYOUT", array(), $conf->entity, 0, 0, 1, 0); -print '
    '; -print $langs->trans("ProductSupplements"); -print ''; -//print $form->selectyesno("TAKEPOS_SUPPLEMENTS", $conf->global->TAKEPOS_SUPPLEMENTS, 1); -print ajax_constantonoff("TAKEPOS_SUPPLEMENTS", array(), $conf->entity, 0, 0, 1, 0); -print '
    '; - print $langs->trans("SupplementCategory"); - print ''; - print $form->select_all_categories(Categorie::TYPE_PRODUCT, $conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, 'TAKEPOS_SUPPLEMENTS_CATEGORY', 64, 0, 0); - print ajax_combobox('TAKEPOS_SUPPLEMENTS_CATEGORY'); - print "
    '; -print 'QR - '.$langs->trans("AutoOrder"); -print ''; -print ajax_constantonoff("TAKEPOS_AUTO_ORDER", array(), $conf->entity, 0, 0, 1, 0); -print '
    '; -print 'QR - '.$langs->trans("CustomerMenu"); -print ''; -print ajax_constantonoff("TAKEPOS_QR_MENU", array(), $conf->entity, 0, 0, 1, 0); -print '
    '; - - -if ($conf->global->TAKEPOS_AUTO_ORDER) -{ - print '
    '; - print ''; - print ''; - print ''; - print "\n"; - - //global $dolibarr_main_url_root; - $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); - $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file - $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables"; - $resql = $db->query($sql); - $rows = array(); - while ($row = $db->fetch_array($resql)) { - print ''; - } - - print '
    '.$langs->trans("Table").''.$langs->trans("URL").''.$langs->trans("QR").'
    '; - print $langs->trans("Table")." ".$row['label']; - print ''; - print "".$urlwithroot."/takepos/public/auto_order.php?key=".dol_encode($row['rowid']).""; - print ''; - print ""; - print '
    '; -} - - -if ($conf->global->TAKEPOS_QR_MENU) -{ - $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); - $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file - print '
    '; - print ''; - print ''; - print ''; - print "\n"; - print ''; - print '
    '.$langs->trans("URL").''.$langs->trans("QR").'
    '; - print "".$urlwithroot."/takepos/public/menu.php"; - print ''; - print ""; - print '
    '; -} - -print '
    '; +print $langs->trans("EnableBarOrRestaurantFeatures"); +print ajax_constantonoff("TAKEPOS_BAR_RESTAURANT", array(), $conf->entity, 0, 0, 1, 0); print '
    '; -print '
    '; +if ($conf->global->TAKEPOS_BAR_RESTAURANT) { + print '
    '; + print ' '.$langs->trans("DefineTablePlan").'
    '; + print '

    '; + + print '
    '; + print ''; + print ''; + print ''; + print "\n"; + + if ($conf->global->TAKEPOS_PRINT_METHOD != "browser") { + print ''; + print ''; + + print ''; + print ''; + } + + print ''; + print ''; + + print ''; + print ''; + + if ($conf->global->TAKEPOS_SUPPLEMENTS) + { + print ''; + print '\n"; + } + + print ''; + print ''; + + print ''; + print ''; + + print '
    '.$langs->trans("Parameters").''.$langs->trans("Value").'
    '; + print $langs->trans("OrderPrinters").' ('.$langs->trans("Setup").')'; + print ''; + print ajax_constantonoff("TAKEPOS_ORDER_PRINTERS", array(), $conf->entity, 0, 0, 1, 0); + //print $form->selectyesno("TAKEPOS_ORDER_PRINTERS", $conf->global->TAKEPOS_ORDER_PRINTERS, 1); + print '
    '; + print $langs->trans("OrderNotes"); + print ''; + print ajax_constantonoff("TAKEPOS_ORDER_NOTES", array(), $conf->entity, 0, 0, 1, 0); + //print $form->selectyesno("TAKEPOS_ORDER_NOTES", $conf->global->TAKEPOS_ORDER_NOTES, 1); + print '
    '; + print $langs->trans("BasicPhoneLayout"); + print ''; + //print $form->selectyesno("TAKEPOS_PHONE_BASIC_LAYOUT", $conf->global->TAKEPOS_PHONE_BASIC_LAYOUT, 1); + print ajax_constantonoff("TAKEPOS_PHONE_BASIC_LAYOUT", array(), $conf->entity, 0, 0, 1, 0); + print '
    '; + print $langs->trans("ProductSupplements"); + print ''; + //print $form->selectyesno("TAKEPOS_SUPPLEMENTS", $conf->global->TAKEPOS_SUPPLEMENTS, 1); + print ajax_constantonoff("TAKEPOS_SUPPLEMENTS", array(), $conf->entity, 0, 0, 1, 0); + print '
    '; + print $langs->trans("SupplementCategory"); + print ''; + print $form->select_all_categories(Categorie::TYPE_PRODUCT, $conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, 'TAKEPOS_SUPPLEMENTS_CATEGORY', 64, 0, 0); + print ajax_combobox('TAKEPOS_SUPPLEMENTS_CATEGORY'); + print "
    '; + print 'QR - '.$langs->trans("CustomerMenu"); + print ''; + print ajax_constantonoff("TAKEPOS_QR_MENU", array(), $conf->entity, 0, 0, 1, 0); + print '
    '; + print 'QR - '.$langs->trans("AutoOrder"); + print ''; + print ajax_constantonoff("TAKEPOS_AUTO_ORDER", array(), $conf->entity, 0, 0, 1, 0); + print '
    '; + print '
    '; + + print '
    '; + + print '
    '; +} + +if ($conf->global->TAKEPOS_BAR_RESTAURANT) { + if ($conf->global->TAKEPOS_QR_MENU) + { + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + print '
    '; + print ''; + print ''; + print ''; + print "\n"; + print ''; + print ''; + print '
    '.$langs->trans("URL").''.$langs->trans("QR").'
    '; + print "".$urlwithroot."/takepos/public/menu.php"; + print ''; + print ""; + print '
    '; + } + + if ($conf->global->TAKEPOS_AUTO_ORDER) + { + print '
    '; + print ''; + print ''; + print ''; + print "\n"; + + //global $dolibarr_main_url_root; + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables"; + $resql = $db->query($sql); + $rows = array(); + while ($row = $db->fetch_array($resql)) { + print ''; + print ''; + print ''; + } + + print '
    '.$langs->trans("Table").''.$langs->trans("URL").''.$langs->trans("QR").'
    '; + print $langs->trans("Table")." ".$row['label']; + print ''; + print "".$urlwithroot."/takepos/public/auto_order.php?key=".dol_encode($row['rowid']).""; + print ''; + print ""; + print '
    '; + } +} + print "\n"; diff --git a/htdocs/takepos/admin/receipt.php b/htdocs/takepos/admin/receipt.php index af5b8fdf8db..252781ec635 100644 --- a/htdocs/takepos/admin/receipt.php +++ b/htdocs/takepos/admin/receipt.php @@ -87,9 +87,10 @@ print ''; print load_fiche_titre($langs->trans("PrintMethod"), '', ''); +print '
    '; print ''; print ''; -print ''; +print ''; print "\n"; // Browser method @@ -97,7 +98,7 @@ print '\n"; print '
    '.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status").''.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status").'
    '; print $langs->trans('Browser'); print ''; print $langs->trans('BrowserMethodDescription'); -print ''; +print ''; if ($conf->global->TAKEPOS_PRINT_METHOD == "browser") { print img_picto($langs->trans("Activated"), 'switch_on'); @@ -114,7 +115,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 1) { print $langs->trans('ReceiptPrinterMethodDescription'); print '
    '; print ''.$langs->trans("Setup").''; - print '
    '; + print ''; if ($conf->receiptprinter->enabled) { if ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter") { print img_picto($langs->trans("Activated"), 'switch_on'); @@ -134,7 +135,7 @@ print '
    '; print "TakePOS Connector"; print ''; print $langs->trans('TakeposConnectorMethodDescription'); -print ''; +print ''; if ($conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") { print img_picto($langs->trans("Activated"), 'switch_on'); @@ -143,14 +144,25 @@ if ($conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") } print "
    '; +print '
    '; + print load_fiche_titre($langs->trans("Setup"), '', ''); +print '
    '; print ''; print ''; print ''; print "\n"; +// VAT Grouped on ticket +print '\n"; + if ($conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") { print '\n"; print '
    '.$langs->trans("Parameters").''.$langs->trans("Value").'
    '; +print $langs->trans('TicketVatGrouped'); +print ''; +print ajax_constantonoff("TAKEPOS_TICKET_VAT_GROUPPED", array(), $conf->entity, 0, 0, 1, 0); +//print $form->selectyesno("TAKEPOS_TICKET_VAT_GROUPPED", $conf->global->TAKEPOS_TICKET_VAT_GROUPPED, 1); +print "
    '; print $langs->trans("URL")." / ".$langs->trans("IPAddress").' ('.$langs->trans("TakeposConnectorNecesary").')'; @@ -214,6 +226,7 @@ print $form->selectyesno("TAKEPOS_AUTO_PRINT_TICKETS", $conf->global->TAKEPOS_AU print "
    '; +print '
    '; print '
    '; diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index 830e5d203d3..52df6df9b79 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -274,14 +274,6 @@ print img_object('', 'category', 'class="paddingright"').$form->select_all_categ print ajax_combobox('TAKEPOS_ROOT_CATEGORY_ID'); print "\n"; -// VAT Grouped on ticket -print ''; -print $langs->trans('TicketVatGrouped'); -print ''; -print ajax_constantonoff("TAKEPOS_TICKET_VAT_GROUPPED", array(), $conf->entity, 0, 0, 1, 0); -//print $form->selectyesno("TAKEPOS_TICKET_VAT_GROUPPED", $conf->global->TAKEPOS_TICKET_VAT_GROUPPED, 1); -print "\n"; - // Sort product print ''; print $langs->trans("SortProductField"); @@ -365,6 +357,20 @@ print ''; print ajax_constantonoff("TAKEPOS_CONTROL_CASH_OPENING", array(), $conf->entity, 0, 0, 1, 0); print "\n"; +// Gift receipt +print ''; +print $langs->trans('GiftReceiptButton'); +print ''; +print ajax_constantonoff("TAKEPOS_GIFT_RECEIPT", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// Delayed Pay Button +print ''; +print $langs->trans('AllowDelayedPayment'); +print ''; +print ajax_constantonoff("TAKEPOS_DELAYED_PAYMENT", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + // Numbering module //print ''; //print $langs->trans("BillsNumberingModule"); @@ -422,14 +428,6 @@ print "\n"; //print $form->selectarray('TAKEPOS_ADDON', $array, (empty($conf->global->TAKEPOS_ADDON) ? '0' : $conf->global->TAKEPOS_ADDON), 0); //print "\n"; -print ''; -print $langs->trans("EnableBarOrRestaurantFeatures"); -print ''; -print ''; -print ajax_constantonoff("TAKEPOS_BAR_RESTAURANT", array(), $conf->entity, 0, 0, 1, 0); -//print $form->selectyesno("TAKEPOS_BAR_RESTAURANT", $conf->global->TAKEPOS_BAR_RESTAURANT, 1); -print "\n"; - print ''; print '
    '; diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index ab5acc1ac50..ee304b7438e 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -529,8 +529,19 @@ function Search2(keyCodeForEnter) { ClickProduct(0); } } + if (eventKeyCode == keyCodeForEnter){ + if (data.length == 0) { + $('#search').val('load('errors'); + echo dol_escape_js($langs->trans("ErrorRecordNotFound")); + ?>'); + $('#search').select(); + } + else ClearSearch(); + } }); } + } function Edit(number) { @@ -631,7 +642,7 @@ function TakeposPrintingTemp(){ } function OpenDrawer(){ - console.log("OpenDrawer"); + console.log("OpenDrawer call ajax url http://global->TAKEPOS_PRINT_SERVER; ?>:8111/print"); $.ajax({ type: "POST", url: 'http://global->TAKEPOS_PRINT_SERVER; ?>:8111/print', @@ -640,7 +651,7 @@ function OpenDrawer(){ } function DolibarrOpenDrawer() { - console.log("DolibarrOpenDrawer"); + console.log("DolibarrOpenDrawer call ajax url /takepos/ajax/ajax.php?action=opendrawer&term="); $.ajax({ type: "GET", url: "", diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index c6b7bb2c734..d4274d90444 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -156,7 +156,7 @@ if ($action == 'valid' && $user->rights->facture->creer) } } - if ($bankaccount <= 0) { + if ($bankaccount <= 0 && $pay != "delayed") { $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")); $error++; } @@ -249,8 +249,10 @@ if ($action == 'valid' && $user->rights->facture->creer) $payment->paiementid = $paiementid; $payment->num_payment = $invoice->ref; - $payment->create($user); - $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + if ($pay != "delayed") { + $payment->create($user); + $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', ''); + } $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded if ($remaintopay == 0) { @@ -348,6 +350,7 @@ if ($action == "addline") } } if ($idoflineadded <= 0) { + $invoice->fetch_thirdparty(); $idoflineadded = $invoice->addline($prod->description, $price, 1, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, $parent_line, null, '', '', 0, 100, '', null, 0); } @@ -397,6 +400,7 @@ if ($action == "deleteline") { $invoice->deleteline($deletelineid); $invoice->fetch($placeid); } + if (count($invoice->lines)==0) $invoice->delete($user); } if ($action == "delete") { @@ -597,6 +601,9 @@ if ($action == "valid" || $action == "history") $sectionwithinvoicelink .= ' '; } else { $sectionwithinvoicelink .= ' '; + if ($conf->global->TAKEPOS_GIFT_RECEIPT) { + $sectionwithinvoicelink .= '
    '; + } } if ($conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE > 0) { @@ -700,8 +707,8 @@ function SendTicket(id) $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:"trans("SendTicket"); ?>"}); } -function Print(id){ - $.colorbox({href:"receipt.php?facid="+id, width:"40%", height:"90%", transition:"none", iframe:"true", title:"trans("PrintTicket"); ?>"}); } @@ -718,6 +725,7 @@ function TakeposPrinting(id){ } function TakeposConnector(id){ + console.log("TakeposConnector" + id); var invoice='" + id, diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index 0f47c7f2b04..0a1c60a5a57 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -375,6 +375,10 @@ foreach ($action_buttons as $button) { $newclass = $class.($button["class"] ? " ".$button["class"] : ""); print ''; } + +if ($conf->global->TAKEPOS_DELAYED_PAYMENT) { + print ''; +} ?>
    diff --git a/htdocs/takepos/public/menu.php b/htdocs/takepos/public/menu.php index c051ae4d673..217da157c2f 100644 --- a/htdocs/takepos/public/menu.php +++ b/htdocs/takepos/public/menu.php @@ -45,7 +45,7 @@ if (!$conf->global->TAKEPOS_QR_MENU) accessforbidden(); // If Restaurant Menu is
    diff --git a/htdocs/takepos/receipt.php b/htdocs/takepos/receipt.php index 1da92de8827..99000c278de 100644 --- a/htdocs/takepos/receipt.php +++ b/htdocs/takepos/receipt.php @@ -34,6 +34,8 @@ $place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is $facid = GETPOST('facid', 'int'); +$gift = GETPOST('gift', 'int'); + if (empty($user->rights->takepos->run)) { accessforbidden(); } @@ -125,8 +127,8 @@ if ($conf->global->TAKEPOS_SHOW_CUSTOMER) trans("Label"); ?> trans("Qty"); ?> - trans("Price"); ?> - trans("TotalTTC"); ?> + trans("Price"); ?> + trans("TotalTTC"); ?> @@ -140,8 +142,8 @@ if ($conf->global->TAKEPOS_SHOW_CUSTOMER) else echo $line->description; ?> qty; ?> - total_ttc / $line->qty, 'MT'), 1); ?> - total_ttc, 1); ?> + total_ttc / $line->qty, 'MT'), 1); ?> + total_ttc, 1); ?> global->TAKEPOS_SHOW_CUSTOMER)
    - - + + global->TAKEPOS_TICKET_VAT_GROUPPED) { $vat_groups = array(); @@ -166,18 +168,18 @@ if ($conf->global->TAKEPOS_SHOW_CUSTOMER) foreach ($vat_groups as $key => $val) { ?> - - + + - + - +
    trans("TotalHT"); ?>total_ht, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>trans("TotalHT"); ?>total_ht, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>
    trans("VAT").' '.vatrate($key, 1); ?>currency)."\n"; ?>trans("VAT").' '.vatrate($key, 1); ?>currency)."\n"; ?>
    trans("TotalVAT").''.price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>trans("TotalVAT").''.price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>
    trans("TotalTTC").''.price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>trans("TotalTTC").''.price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency)."\n"; ?>
    diff --git a/htdocs/theme/eldy/badges.inc.php b/htdocs/theme/eldy/badges.inc.php index d2a59447bb9..36296bb0b8a 100644 --- a/htdocs/theme/eldy/badges.inc.php +++ b/htdocs/theme/eldy/badges.inc.php @@ -24,6 +24,18 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); font-size: 0.95em; padding: .19em .35em; /* more than 0.19 generate a change into heigth of lines */ } +.tabBar .arearef .statusref .badge-status, .tabBar .arearefnobottom .statusref .badge-status { + font-size: 1.1em; + padding: .4em .4em; +} +/* Force values for small screen 767 */ +@media only screen and (max-width: 767px) +{ + .tabBar .arearef .statusref .badge-status, .tabBar .arearefnobottom .statusref .badge-status { + font-size: 0.95em; + padding: .3em .2em; + } +} .badge-pill, .tabs .badge { padding-right: .5em; diff --git a/htdocs/theme/eldy/btn.inc.php b/htdocs/theme/eldy/btn.inc.php index e78d82592bb..dc3245abc4c 100644 --- a/htdocs/theme/eldy/btn.inc.php +++ b/htdocs/theme/eldy/btn.inc.php @@ -9,14 +9,18 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> --btncolorborder: #FFF; --butactiondeletebg: rgb(234,228,225); /* tertiary color */ - --butactionbg:rgb(218, 235, 225); + /* --butactionbg:rgb(218, 235, 225); */ /* --butactionbg:rgb(228, 218, 235); */ + --butactionbg:rgb(118, 145, 225); } global->MAIN_THEME_DARKMODEENABLED)) { +if (!empty($conf->global->THEME_DARKMODEENABLED)) { + print "/* For dark mode */\n"; + if ($conf->global->THEME_DARKMODEENABLED != 2) { + print "@media (prefers-color-scheme: dark) {"; + } print " - @media (prefers-color-scheme: dark) { :root { --btncolortext: ; @@ -26,8 +30,10 @@ if (!empty($conf->global->MAIN_THEME_DARKMODEENABLED)) { --butactionbg:rgb(173,140,79); --butactiondeletebg: rgb(252,84,91); - } - }"; + }\n"; + if ($conf->global->THEME_DARKMODEENABLED != 2) { + print "}"; + } } ?> @@ -53,6 +59,8 @@ span.butAction, span.butActionDelete { .butAction { background: var(--butactionbg); + color: #FFF !important; + border-radius: 3px; /* background: rgb(230, 232, 239); */ } .butActionRefused, .butAction, .butAction:link, .butAction:visited, .butAction:hover, .butAction:active, .butActionDelete, .butActionDelete:link, .butActionDelete:visited, .butActionDelete:hover, .butActionDelete:active { @@ -72,10 +80,10 @@ span.butAction, span.butActionDelete { /* border: 1px solid #aaa; */ /* border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25); */ - border-top-right-radius: 0 !important; + /*border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; border-top-left-radius: 0 !important; - border-bottom-left-radius: 0 !important; + border-bottom-left-radius: 0 !important;*/ } .butActionNew, .butActionNewRefused, .butActionNew:link, .butActionNew:visited, .butActionNew:hover, .butActionNew:active { text-decoration: none; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 4ef3bef90d1..972221079c9 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -34,7 +34,7 @@ --oddevencolor: #202020; --colorboxstatsborder: #e0e0e0; --dolgraphbg: rgba(255,255,255,0); - --fieldrequiredcolor: #000055; + --fieldrequiredcolor: #804000; --colortextbacktab: #; --colorboxiconbg: #eee; --refidnocolor:#444; @@ -45,10 +45,12 @@ } global->MAIN_THEME_DARKMODEENABLED)) { - print "@media (prefers-color-scheme: dark) { - :root { - +if (!empty($conf->global->THEME_DARKMODEENABLED)) { + print "/* For dark mode */\n"; + if ($conf->global->THEME_DARKMODEENABLED != 2) { + print "@media (prefers-color-scheme: dark) {"; + } + print ":root { --colorbackhmenu1: #1d1e20; --colorbackvmenu1: #2b2c2e; --colorbacktitle1: #2b2d2f; @@ -84,8 +86,10 @@ if (!empty($conf->global->MAIN_THEME_DARKMODEENABLED)) { --amountremaintopaycolor:rgb(252,84,91); --amountpaymentcomplete:rgb(101,184,77); --amountremaintopaybackcolor:rbg(245,130,46); - } - }"; + }\n"; + if ($conf->global->THEME_DARKMODEENABLED != 2) { + print "}\n"; + } } ?> @@ -186,9 +190,18 @@ input, select { } #mainbody input.button:not(.buttongen):not(.bordertransp) { background: var(--butactionbg); + color: #FFF !important; + + /* -webkit-box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); + box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); */ + + border-radius: 3px; border-collapse: collapse; border: none; } +#mainbody span.websitetools input.button:not(.buttongen):not(.bordertransp) { + color: #000 !important; +} #mainbody input.buttongen, #mainbody button.buttongen { padding: 3px 4px; } @@ -372,6 +385,9 @@ input.pageplusone { .colorwhite { color: #fff; } +.colorgrey { + color: #888 !important; +} .colorblack { color: #000; } @@ -1796,6 +1812,9 @@ img.photoref, div.photoref { width: 80px; object-fit: contain; } +div.photoref .fa, div.photoref .fas, div.photoref .far { + font-size: 2.5em; +} img.fitcontain { object-fit: contain; } @@ -3245,11 +3264,7 @@ div.pagination li:first-child span { /*border-top-left-radius: 4px; border-bottom-left-radius: 4px;*/ } -div.pagination li:last-child a, -div.pagination li:last-child span { - /*border-top-right-radius: 4px; - border-bottom-right-radius: 4px;*/ -} + div.pagination li a:hover, div.pagination li:not(.paginationafterarrows,.title-button) span:hover, div.pagination li a:focus, @@ -3972,10 +3987,11 @@ div.boximport { .product_line_stock_ok { color: #002200; } .product_line_stock_too_low { color: #884400; } -.fieldrequired { font-weight: bold; color: var(--fieldrequiredcolor); } +.fieldrequired { font-weight: bold; color: var(--fieldrequiredcolor) !important; } td.widthpictotitle { width: 26px; text-align: ; } -span.widthpictotitle { font-size: 1.7em; }; +span.widthpictotitle { font-size: 1.7em; } +table.titlemodulehelp tr td img.widthpictotitle { width: 80px; } .dolgraphtitle { margin-top: 6px; margin-bottom: 4px; } .dolgraphtitlecssboxes { /* margin: 0px; */ } @@ -4040,6 +4056,8 @@ div.titre { } div.fiche > table.table-fiche-title:first-of-type div { color: var(--colortexttitlenotab); + font-size: 1.05em; + /* text-transform: uppercase; */ /* font-weight: 600; */ } div.titre { diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index cceb8af9bf7..f2d82e83e62 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -77,7 +77,12 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> text-align: center; font-size: 45px; line-height: 90px; - background: rgba(0, 0, 0, 0.08) !important + background: rgba(0, 0, 0, 0.08) !important; +} + +.info-box-module .info-box-icon { + padding-top: 5px; + padding-bottom: 5px; } .info-box-sm .info-box-icon { height: 80px; @@ -101,6 +106,13 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> max-width: 60%; } +a.info-box-text.info-box-text-a { + display: table-cell; +} +a.info-box-text-a i.fa.fa-exclamation-triangle { + font-size: 0.9em; +} + .info-box-icon-text{ box-sizing: border-box; display: block; @@ -166,15 +178,21 @@ if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?> padding: 5px 10px; margin-left: 84px; } - .info-box-sm .info-box-content{ margin-left: 80px; } -/*.info-box-setup span { - color: var(--colortexttitlenotab2); +.info-box-sm .info-box-module-enabled { + /* background: linear-gradient(0.35turn, #fff, #fff, #f6faf8, #e4efe8) */ + background: linear-gradient(0.4turn, #fff, #fff, #fff, #e4efe8); } -.tdsetuppicto span { - color: var(--colortexttitlenotab2); +.info-box-content-warning span.font-status4 { + color: #bc9526 !important; +} +/*.info-box-sm .info-box-content-warning { + background: #ffd7a3; +}*/ +/*.info-box-icon.info-box-icon-module-enabled { + background: #e4f0e4 !important; }*/ .info-box-number { @@ -212,6 +230,8 @@ a.info-box-text{ text-decoration: none;} + + /* ICONS INFO BOX */ global->THEME_SATURATE_RATIO = } .customer-back { - background-color: #99a17d !important; + background-color: #95a55d !important; color: #FFF !important; padding: 2px; margin: 2px; @@ -248,14 +268,16 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = border-radius: 3px; } + + .bg-infobox-project{ color: #6c6aa8 !important; } .bg-infobox-action{ - color: #a47080 !important; + color: #b06080 !important; } .bg-infobox-propal, .bg-infobox-facture, .bg-infobox-commande { - color: #99a17d !important; + color: #95a55d !important; } .bg-infobox-supplier_proposal, .bg-infobox-invoice_supplier, .bg-infobox-order_supplier { color: #599caf !important; @@ -264,7 +286,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = color: #46a676 !important; } .bg-infobox-bank_account{ - color: #b0a53e !important; + color: #b0bb39 !important; } .bg-infobox-adherent, .bg-infobox-member { color: #79633f !important; @@ -283,12 +305,12 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = color: #6c6aa8 !important; } .infobox-action{ - color: #a47080 !important; + color: #b06080 !important; } .infobox-propal, .infobox-facture, .infobox-commande{ - color: #99a17d !important; + color: #95a55d !important; } .infobox-supplier_proposal, .infobox-invoice_supplier, @@ -299,7 +321,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = color: #46a676 !important; } .infobox-bank_account{ - color: #b0a53e !important; + color: #b0bb39 !important; } .infobox-adherent, .infobox-member { color: #79633f !important; @@ -398,12 +420,18 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = height: 0; } +.info-box-title { + width: calc(100% - 20px); +} .info-box-module { min-width: 350px; max-width: 350px; } -.info-box-title { - width: calc(100% - 20px); +@media only screen and (max-width: 1740px) { + .info-box-module { + min-width: 315px; + max-width: 315px; + } } @media only screen and (max-width: 767px) { .info-box-module { @@ -413,7 +441,7 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = .info-box-module .info-box-content { - height: 6.4em; + height: 98px; } /* Disabled. This break the responsive on smartphone .box{ diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 98f9e311274..b9f630872ae 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -66,6 +66,7 @@ else header('Cache-Control: no-cache'); if (GETPOST('theme', 'alpha')) $conf->theme = GETPOST('theme', 'alpha'); // If theme was forced on URL if (GETPOST('lang', 'aZ09')) $langs->setDefaultLang(GETPOST('lang', 'aZ09')); // If language was forced on URL +if (GETPOST('THEME_DARKMODEENABLED', 'int')) $conf->global->THEME_DARKMODEENABLED = GETPOST('THEME_DARKMODEENABLED', 'int'); // If darkmode was forced on URL $langs->load("main", 0, 1); $right = ($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right'); diff --git a/htdocs/theme/eldy/theme_vars.inc.php b/htdocs/theme/eldy/theme_vars.inc.php index 3ce29206c0d..293dc6a2c39 100644 --- a/htdocs/theme/eldy/theme_vars.inc.php +++ b/htdocs/theme/eldy/theme_vars.inc.php @@ -65,13 +65,13 @@ $colorbacklinepairhover = '230,237,244'; // line hover $colorbacklinepairchecked = '230,237,244'; // line checked $colorbacklinebreak = '248,247,244'; // line break $colorbackbody = '255,255,255'; -$colortexttitlenotab = '0,123,140'; // 150,90,121 140,80,10 or 10,140,80 #875a7b green=0,123,140, violet: 0,50,120 +$colortexttitlenotab = '10,120,140'; // 150,90,121 140,80,10 or 10,140,80 #875a7b green=0,123,140, violet: 0,50,120 $colortexttitlenotab2 = '100,0,100'; // 150,90,121 140,80,10 or 10,140,80 #875a7b green=0,123,140, violet: 0,50,120 $colortexttitle = '0,0,0'; $colortexttitlelink = '10, 20, 100'; $colortext = '0,0,0'; $colortextlink = '10, 20, 100'; -$fontsize = '0.86em'; +$fontsize = '0.90em'; $fontsizesmaller = '0.75em'; $topMenuFontSize = '1.1em'; $toolTipBgColor = 'rgba(255, 255, 255, 0.96)'; @@ -87,11 +87,11 @@ $colorblind_deuteranopes_textWarning = $textWarning; // currently not tested wit // Badges colors $badgePrimary = '#007bff'; -$badgeSecondary = '#cccccc'; +$badgeSecondary = '#aaaabb'; +$badgeInfo = '#aaaabb'; $badgeSuccess = '#55a580'; $badgeWarning = '#bc9526'; // See $textWarning bc9526 $badgeDanger = '#9f4705'; // See $textDanger -$badgeInfo = '#aaaabb'; $badgeDark = '#343a40'; $badgeLight = '#f8f9fa'; diff --git a/htdocs/theme/md/dropdown.inc.php b/htdocs/theme/md/dropdown.inc.php index aae84a27c1b..b86b935c5d1 100644 --- a/htdocs/theme/md/dropdown.inc.php +++ b/htdocs/theme/md/dropdown.inc.php @@ -147,7 +147,7 @@ button.dropdown-item.global-search-item { * MENU Dropdown */ .login_block.usedropdown .logout-btn{ - display: none; + /* display: none; */ } .tmenu .open.dropdown, .tmenu .open.dropdown { diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index 949c8218e0a..926e59aef51 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -108,6 +108,13 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = background: #bbb; } +a.info-box-text.info-box-text-a { + display: table-cell; +} +a.info-box-text-a i.fa.fa-exclamation-triangle { + font-size: 0.9em; +} + .info-box { display: block; position: relative; @@ -455,6 +462,18 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) $conf->global->THEME_SATURATE_RATIO = min-width: 350px; max-width: 350px; } +@media only screen and (max-width: 1740px) { + .info-box-module { + min-width: 315px; + max-width: 315px; + } +} +@media only screen and (max-width: 767px) { + .info-box-module { + min-width: 260px; + } +} + .info-box-module .info-box-content { height: 6.3em; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 6c20f4d66c1..fb9f0239d10 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -3862,6 +3862,7 @@ div.boximport { .fieldrequired { font-weight: bold; color: #000055; } .widthpictotitle { width: 40px; font-size: 1.4em; text-align: ; } +table.titlemodulehelp tr td img.widthpictotitle { width: 80px; } .dolgraphtitle { margin-top: 6px; margin-bottom: 4px; } .dolgraphtitlecssboxes { /* margin: 0px; */ } diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index 3d1b89e6c65..13874eb7ecb 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -235,6 +235,8 @@ if (!empty($object->id)) $messagingUrl = DOL_URL_ROOT.'/ticket/messaging.php?track_id='.$object->track_id; $morehtmlright .= dolGetButtonTitle($langs->trans('ShowAsConversation'), '', 'fa fa-comments imgforviewmode', $messagingUrl, '', 1); + $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id; + $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-list-alt imgforviewmode', $messagingUrl, '', 1, array('morecss'=>'btnTitleSelected')); // Show link to add a message (if read and not closed) $btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage"; @@ -246,7 +248,6 @@ if (!empty($object->id)) $url = dol_buildpath('/comm/action/card.php', 1).'?action=create&datep='.date('YmdHi').'&origin=ticket&originid='.$object->id.'&projectid='.$object->fk_project.'&backtopage='.urlencode($_SERVER["PHP_SELF"]); $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus); - print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1); // List of all actions diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index b7d4c3d7b21..fc0bce96cb8 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -232,9 +232,12 @@ if (!empty($object->id)) $morehtmlright = ''; + $messagingUrl = DOL_URL_ROOT.'/ticket/messaging.php?track_id='.$object->track_id; + $morehtmlright .= dolGetButtonTitle($langs->trans('ShowAsConversation'), '', 'fa fa-comments imgforviewmode', $messagingUrl, '', 1, array('morecss'=>'btnTitleSelected')); $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id; $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-list-alt imgforviewmode', $messagingUrl, '', 1); + // Show link to add a message (if read and not closed) $btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage"; $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init'; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index d74467a14b7..eb3cd67cf50 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -44,6 +44,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; @@ -253,6 +254,8 @@ if (empty($reshook)) { $object->fk_warehouse = GETPOST('fk_warehouse', 'int'); + $object->lang = GETPOST('default_lang', 'aZ09'); + // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object); if ($ret < 0) { @@ -415,6 +418,8 @@ if (empty($reshook)) { $object->fk_warehouse = GETPOST('fk_warehouse', 'int'); } + $object->lang = GETPOST('default_lang', 'aZ09'); + if (!empty($conf->multicompany->enabled)) { if (!empty($_POST["superadmin"])) @@ -671,6 +676,7 @@ if (empty($reshook)) { $form = new Form($db); $formother = new FormOther($db); $formcompany = new FormCompany($db); +$formadmin = new FormAdmin($db); $formfile = new FormFile($db); if (!empty($conf->stock->enabled)) $formproduct = new FormProduct($db); @@ -1113,6 +1119,14 @@ if ($action == 'create' || $action == 'adduserldap') print ""; } + if (!empty($conf->global->MAIN_MULTILANGS)) + { + print ''.$form->editfieldkey('DefaultLang', 'default_lang', '', $object, 0).''."\n"; + print $formadmin->select_language(GETPOST('default_lang', 'alpha') ?GETPOST('default_lang', 'alpha') : ($object->lang ? $object->lang : ''), 'default_lang', 0, 0, 1, 0, 0, 'maxwidth200onsmartphone'); + print ''; + print ''; + } + // Multicompany if (!empty($conf->multicompany->enabled) && is_object($mc)) { @@ -1654,6 +1668,19 @@ if ($action == 'create' || $action == 'adduserldap') print ''; } + // Default language + if (!empty($conf->global->MAIN_MULTILANGS)) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + print ''.$langs->trans("DefaultLang").''; + //$s=picto_from_langcode($object->default_lang); + //print ($s?$s.' ':''); + $langs->load("languages"); + $labellang = ($object->lang ? $langs->trans('Language_'.$object->lang) : ''); + print $form->textwithpicto($labellang, $langs->trans("WarningNotLangOfInterface", $langs->transnoentitiesnoconv("UserGUISetup"))); + print ''; + } + if (isset($conf->file->main_authentication) && preg_match('/openid/', $conf->file->main_authentication) && !empty($conf->global->MAIN_OPENIDURL_PERUSER)) { print ''.$langs->trans("OpenIDURL").''; @@ -2446,6 +2473,15 @@ if ($action == 'create' || $action == 'adduserldap') print ""; } + // Default language + if (!empty($conf->global->MAIN_MULTILANGS)) + { + print ''.$form->editfieldkey('DefaultLang', 'default_lang', '', $object, 0).''."\n"; + print $formadmin->select_language($object->lang, 'default_lang', 0, 0, 1); + print ''; + print ''; + } + // Status print ''.$langs->trans("Status").''; print ''; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index cc794db045b..fdda769c5f4 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1549,6 +1549,7 @@ class User extends CommonObject $sql .= ", default_range = ".($this->default_range > 0 ? $this->default_range : 'null'); $sql .= ", default_c_exp_tax_cat = ".($this->default_c_exp_tax_cat > 0 ? $this->default_c_exp_tax_cat : 'null'); $sql .= ", fk_warehouse = ".($this->fk_warehouse ? "'".$this->db->escape($this->fk_warehouse)."'" : "null"); + $sql .= ", lang = ".($this->lang ? "'".$this->db->escape($this->lang)."'" : "null"); $sql .= " WHERE rowid = ".$this->id; @@ -2996,7 +2997,7 @@ class User extends CommonObject public function build_path_from_id_user($id_user, $protection = 0) { // phpcs:enable - dol_syslog(get_class($this)."::build_path_from_id_user id_user=".$id_user." protection=".$protection, LOG_DEBUG); + //dol_syslog(get_class($this)."::build_path_from_id_user id_user=".$id_user." protection=".$protection, LOG_DEBUG); if (!empty($this->users[$id_user]['fullpath'])) { diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 1f0880b0fb3..2cb4f174b23 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -264,19 +264,6 @@ if ($action == 'edit') print ''; print ''; - // Landing page - print ''; - print ''; - print ''; - print ''; - // Language by default print ''; print ''; print ''; + print '> '; print ''; + // Landing page + print ''; + print ''; + print ''; + print ''; + + // Landing page for Agenda - AGENDA_DEFAULT_VIEW + print ''."\n"; + print ''."\n"; + print ''."\n"; + print ''; + print ''."\n"; + // Max size of lists print ''; print ''; print ''; + print '> '; print ''; - // AGENDA_DEFAULT_VIEW - print ''."\n"; - print ''."\n"; - print ''."\n"; - print ''; - print ''."\n"; - print '
    '.$langs->trans("Parameter").''.$langs->trans("DefaultValue").' '.$langs->trans("PersonalValue").'
    '.$langs->trans("LandingPage").''; - print (empty($conf->global->MAIN_LANDING_PAGE) ? '' : $conf->global->MAIN_LANDING_PAGE); - print 'conf->MAIN_LANDING_PAGE) ? " checked" : ""); - print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo - print '> '.$langs->trans("UsePersonalValue").''; - print $form->selectarray('MAIN_LANDING_PAGE', $tmparray, (!empty($object->conf->MAIN_LANDING_PAGE) ? $object->conf->MAIN_LANDING_PAGE : ''), 0, 0, 0, '', 1); - //print info_admin($langs->trans("WarningYouMayLooseAccess"), 0, 0, 0); - print '
    '.$langs->trans("Language").''; @@ -286,31 +273,44 @@ if ($action == 'edit') print 'conf->MAIN_LANG_DEFAULT) ? " checked" : ""); print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo - print '> '.$langs->trans("UsePersonalValue").''; print $formadmin->select_language((!empty($object->conf->MAIN_LANG_DEFAULT) ? $object->conf->MAIN_LANG_DEFAULT : ''), 'main_lang_default', 1, null, 0, 0, (!empty($dolibarr_main_demo))); print '
    '.$langs->trans("LandingPage").''; + print (empty($conf->global->MAIN_LANDING_PAGE) ? '' : $conf->global->MAIN_LANDING_PAGE); + print 'conf->MAIN_LANDING_PAGE) ? " checked" : ""); + print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo + print '> '; + print $form->selectarray('MAIN_LANDING_PAGE', $tmparray, (!empty($object->conf->MAIN_LANDING_PAGE) ? $object->conf->MAIN_LANDING_PAGE : ''), 0, 0, 0, '', 1); + //print info_admin($langs->trans("WarningYouMayLooseAccess"), 0, 0, 0); + print '
    '.$langs->trans("AGENDA_DEFAULT_VIEW").' conf->AGENDA_DEFAULT_VIEW) ? " checked" : ""); + print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo + print '> '."\n"; + $tmplist = array(''=>' ', 'show_list'=>$langs->trans("ViewList"), 'show_month'=>$langs->trans("ViewCal"), 'show_week'=>$langs->trans("ViewWeek"), 'show_day'=>$langs->trans("ViewDay"), 'show_peruser'=>$langs->trans("ViewPerUser")); + print $form->selectarray('AGENDA_DEFAULT_VIEW', $tmplist, $object->conf->AGENDA_DEFAULT_VIEW, 0, 0, 0, ''); + print '
    '.$langs->trans("MaxSizeList").''.$conf->global->MAIN_SIZE_LISTE_LIMIT.'conf->MAIN_SIZE_LISTE_LIMIT) ? " checked" : ""); print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo - print '> '.$langs->trans("UsePersonalValue").'
    '.$langs->trans("AGENDA_DEFAULT_VIEW").' conf->AGENDA_DEFAULT_VIEW) ? " checked" : ""); - print empty($dolibarr_main_demo) ? '' : ' disabled="disabled"'; // Disabled for demo - print '> '.$langs->trans("UsePersonalValue").''."\n"; - $tmplist = array(''=>' ', 'show_list'=>$langs->trans("ViewList"), 'show_month'=>$langs->trans("ViewCal"), 'show_week'=>$langs->trans("ViewWeek"), 'show_day'=>$langs->trans("ViewDay"), 'show_peruser'=>$langs->trans("ViewPerUser")); - print $form->selectarray('AGENDA_DEFAULT_VIEW', $tmplist, $object->conf->AGENDA_DEFAULT_VIEW, 0, 0, 0, ''); - print '

    '; // Theme @@ -334,6 +334,20 @@ if ($action == 'edit') print ''; print ''; + // Language + print ''; + print ''; + print ''; + print ''; + // Landing page print ''; print ''; - // Language - print ''; - print ''; - print ''; - print ''; - - // Max size for lists - print ''; - print ''; - print ''; - print ''; - - // AGENDA_DEFAULT_VIEW + // Landing page for Agenda - AGENDA_DEFAULT_VIEW print ''."\n"; print ''."\n"; print ''."\n"; @@ -380,6 +374,12 @@ if ($action == 'edit') if (!empty($object->conf->AGENDA_DEFAULT_VIEW)) print $form->selectarray('AGENDA_DEFAULT_VIEW', $tmplist, $object->conf->AGENDA_DEFAULT_VIEW, 0, 0, 0, '', 0, 0, 1); print ''."\n"; + // Max size for lists + print ''; + print ''; + print ''; + print ''; + print '
    '.$langs->trans("Parameter").''.$langs->trans("DefaultValue").' '.$langs->trans("PersonalValue").'
    '.$langs->trans("Language").''; + $s = picto_from_langcode($conf->global->MAIN_LANG_DEFAULT); + print ($s ? $s.' ' : ''); + print (isset($conf->global->MAIN_LANG_DEFAULT) && $conf->global->MAIN_LANG_DEFAULT == 'auto' ? $langs->trans("AutoDetectLang") : $langs->trans("Language_".$conf->global->MAIN_LANG_DEFAULT)); + print 'conf->MAIN_LANG_DEFAULT) ? " checked" : "").'> '.$langs->trans("UsePersonalValue").''; + $s = (isset($object->conf->MAIN_LANG_DEFAULT) ? picto_from_langcode($object->conf->MAIN_LANG_DEFAULT) : ''); + print ($s ? $s.' ' : ''); + print (isset($object->conf->MAIN_LANG_DEFAULT) && $object->conf->MAIN_LANG_DEFAULT == 'auto' ? $langs->trans("AutoDetectLang") : (!empty($object->conf->MAIN_LANG_DEFAULT) ? $langs->trans("Language_".$object->conf->MAIN_LANG_DEFAULT) : '')); + print '
    '.$langs->trans("LandingPage").''; @@ -350,27 +364,7 @@ if ($action == 'edit') //print $form->selectarray('MAIN_LANDING_PAGE', $tmparray, (! empty($object->conf->MAIN_LANDING_PAGE)?$object->conf->MAIN_LANDING_PAGE:''), 0, 0, 0, '', 1); print '
    '.$langs->trans("Language").''; - $s = picto_from_langcode($conf->global->MAIN_LANG_DEFAULT); - print ($s ? $s.' ' : ''); - print (isset($conf->global->MAIN_LANG_DEFAULT) && $conf->global->MAIN_LANG_DEFAULT == 'auto' ? $langs->trans("AutoDetectLang") : $langs->trans("Language_".$conf->global->MAIN_LANG_DEFAULT)); - print 'conf->MAIN_LANG_DEFAULT) ? " checked" : "").'> '.$langs->trans("UsePersonalValue").''; - $s = (isset($object->conf->MAIN_LANG_DEFAULT) ? picto_from_langcode($object->conf->MAIN_LANG_DEFAULT) : ''); - print ($s ? $s.' ' : ''); - print (isset($object->conf->MAIN_LANG_DEFAULT) && $object->conf->MAIN_LANG_DEFAULT == 'auto' ? $langs->trans("AutoDetectLang") : (!empty($object->conf->MAIN_LANG_DEFAULT) ? $langs->trans("Language_".$object->conf->MAIN_LANG_DEFAULT) : '')); - print '
    '.$langs->trans("MaxSizeList").''.(!empty($conf->global->MAIN_SIZE_LISTE_LIMIT) ? $conf->global->MAIN_SIZE_LISTE_LIMIT : ' ').'conf->MAIN_SIZE_LISTE_LIMIT) ? " checked" : "").'> '.$langs->trans("UsePersonalValue").''.(!empty($object->conf->MAIN_SIZE_LISTE_LIMIT) ? $object->conf->MAIN_SIZE_LISTE_LIMIT : ' ').'
    '.$langs->trans("AGENDA_DEFAULT_VIEW").' 
    '.$langs->trans("MaxSizeList").''.(!empty($conf->global->MAIN_SIZE_LISTE_LIMIT) ? $conf->global->MAIN_SIZE_LISTE_LIMIT : ' ').'conf->MAIN_SIZE_LISTE_LIMIT) ? " checked" : "").'> '.$langs->trans("UsePersonalValue").''.(!empty($object->conf->MAIN_SIZE_LISTE_LIMIT) ? $object->conf->MAIN_SIZE_LISTE_LIMIT : ' ').'

    '; diff --git a/htdocs/variants/card.php b/htdocs/variants/card.php index 0669964ba57..6d077e85ad1 100644 --- a/htdocs/variants/card.php +++ b/htdocs/variants/card.php @@ -90,9 +90,9 @@ if ($confirm == 'yes') { if ($action == 'confirm_delete') { $db->begin(); - $res = $objectval->deleteByFkAttribute($object->id); + $res = $objectval->deleteByFkAttribute($object->id, $user); - if ($res < 1 || ($object->delete() < 1)) { + if ($res < 1 || ($object->delete($user) < 1)) { $db->rollback(); setEventMessages($langs->trans('CoreErrorMessage'), $object->errors, 'errors'); header('Location: '.dol_buildpath('/variants/card.php?id='.$object->id, 2)); @@ -105,7 +105,7 @@ if ($confirm == 'yes') { } elseif ($action == 'confirm_deletevalue') { if ($objectval->fetch($valueid) > 0) { - if ($objectval->delete() < 1) { + if ($objectval->delete($user) < 1) { setEventMessages($langs->trans('CoreErrorMessage'), $objectval->errors, 'errors'); } else { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); diff --git a/htdocs/variants/class/ProductAttribute.class.php b/htdocs/variants/class/ProductAttribute.class.php index 36b4823b51b..6e2335c2f99 100644 --- a/htdocs/variants/class/ProductAttribute.class.php +++ b/htdocs/variants/class/ProductAttribute.class.php @@ -16,17 +16,18 @@ * along with this program. If not, see . */ +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; /** * Class ProductAttribute * Used to represent a product attribute */ -class ProductAttribute +class ProductAttribute extends CommonObject { /** * Database handler * @var DoliDB */ - private $db; + public $db; /** * Id of the product attribute @@ -119,7 +120,8 @@ class ProductAttribute $return[] = $tmp; } - } else dol_print_error($this->db); + } + else dol_print_error($this->db); return $return; } @@ -127,11 +129,21 @@ class ProductAttribute /** * Creates a product attribute * - * @param User $user Object user that create + * @param User $user Object user + * @param int $notrigger Do not execute trigger * @return int <0 KO, Id of new variant if OK */ - public function create(User $user) + public function create(User $user, $notrigger = 0) { + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_CREATE', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + //Ref must be uppercase $this->ref = strtoupper($this->ref); @@ -152,11 +164,21 @@ class ProductAttribute /** * Updates a product attribute * - * @param User $user Object user + * @param User $user Object user + * @param int $notrigger Do not execute trigger * @return int <0 KO, >0 OK */ - public function update(User $user) + public function update(User $user, $notrigger = 0) { + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_MODIFY', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + //Ref must be uppercase $this->ref = trim(strtoupper($this->ref)); $this->label = trim($this->label); @@ -173,11 +195,21 @@ class ProductAttribute /** * Deletes a product attribute * - * @param User $user Object user - * @return int <0 KO, >0 OK + * @param User $user Object user + * @param int $notrigger Do not execute trigger + * @return int <0 KO, >0 OK */ - public function delete($user = null) + public function delete(User $user, $notrigger = 0) { + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_DELETE', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute WHERE rowid = ".(int) $this->id; if ($this->db->query($sql)) { diff --git a/htdocs/variants/class/ProductAttributeValue.class.php b/htdocs/variants/class/ProductAttributeValue.class.php index 0a26b3eace2..ab998c6752b 100644 --- a/htdocs/variants/class/ProductAttributeValue.class.php +++ b/htdocs/variants/class/ProductAttributeValue.class.php @@ -16,17 +16,18 @@ * along with this program. If not, see . */ +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; /** * Class ProductAttributeValue * Used to represent a product attribute value */ -class ProductAttributeValue +class ProductAttributeValue extends CommonObject { /** * Database handler * @var DoliDB */ - private $db; + public $db; /** * Attribute value id @@ -144,10 +145,11 @@ class ProductAttributeValue /** * Creates a value for a product attribute * - * @param User $user Object user - * @return int <0 KO >0 OK + * @param User $user Object user + * @param int $notrigger Do not execute trigger + * @return int <0 KO >0 OK */ - public function create(User $user) + public function create(User $user, $notrigger = 0) { if (!$this->fk_product_attribute) { return -1; @@ -155,15 +157,25 @@ class ProductAttributeValue // Ref must be uppercase $this->ref = strtoupper($this->ref); + $this->value = $this->db->escape($this->value); $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute_value (fk_product_attribute, ref, value, entity) VALUES ('".(int) $this->fk_product_attribute."', '".$this->db->escape($this->ref)."', - '".$this->db->escape($this->value)."', ".(int) $this->entity.")"; + '".$this->value."', ".(int) $this->entity.")"; $query = $this->db->query($sql); if ($query) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute_value'); + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_CREATE', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + return 1; } @@ -173,11 +185,21 @@ class ProductAttributeValue /** * Updates a product attribute value * - * @param User $user Object user - * @return int <0 if KO, >0 if OK + * @param User $user Object user + * @param int $notrigger Do not execute trigger + * @return int <0 if KO, >0 if OK */ - public function update(User $user) + public function update(User $user, $notrigger = 0) { + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_MODIFY', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + //Ref must be uppercase $this->ref = trim(strtoupper($this->ref)); $this->value = trim($this->value); @@ -196,33 +218,62 @@ class ProductAttributeValue /** * Deletes a product attribute value * + * @param User $user Object user + * @param int $notrigger Do not execute trigger * @return int <0 KO, >0 OK */ - public function delete() + public function delete(User $user, $notrigger = 0) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE rowid = ".(int) $this->id; - if ($this->db->query($sql)) { - return 1; - } + if (empty($notrigger)) { + // Call trigger + $result = $this->call_trigger('PRODUCT_ATTRIBUTE_VALUE_DELETE', $user); + if ($result < 0) { + return -1; + } + // End call triggers + } + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE rowid = ".(int) $this->id; + if ($this->db->query($sql)) { + return 1; + } - return -1; + return -1; } /** * Deletes all product attribute values by a product attribute id * - * @param int $fk_attribute Product attribute id + * @param int $fk_attribute Product attribute id + * @param User $user Object user * @return int <0 KO, >0 OK */ - public function deleteByFkAttribute($fk_attribute) + public function deleteByFkAttribute($fk_attribute, User $user) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE fk_product_attribute = ".(int) $fk_attribute; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE fk_product_attribute = ".(int) $fk_attribute; - if ($this->db->query($sql)) { - return 1; - } + $query = $this->db->query($sql); - return -1; + if (!$query) { + return -1; + } + + if (!$this->db->num_rows($query)) { + return 1; + } + + while ($obj = $this->db->fetch_object($query)) { + $tmp = new ProductAttributeValue($this->db); + if ($tmp->fetch($obj->rowid) > 0) { + $result = $tmp->delete($user); + if ($result < 0) { + return -1; + } + } else { + return -1; + } + } + + return 1; } } diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index 3bb4f7312ee..50c0dedaced 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -71,6 +71,12 @@ class ProductCombination */ public $entity; + /** + * Combination price level + * @var ProductCombinationLevel[] + */ + public $combination_price_levels; + /** * Constructor * @@ -87,11 +93,13 @@ class ProductCombination /** * Retrieves a combination by its rowid * - * @param int $rowid Row id - * @return int <0 KO, >0 OK + * @param int $rowid Row id + * @return int <0 KO, >0 OK */ public function fetch($rowid) { + global $conf; + $sql = "SELECT rowid, fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight FROM ".MAIN_DB_PREFIX."product_attribute_combination WHERE rowid = ".(int) $rowid." AND entity IN (".getEntity('product').")"; $query = $this->db->query($sql); @@ -113,9 +121,118 @@ class ProductCombination $this->variation_price_percentage = $obj->variation_price_percentage; $this->variation_weight = $obj->variation_weight; + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $this->fetchCombinationPriceLevels(); + } + return 1; } + + /** + * Retrieves combination price levels + * + * @param int $fk_price_level The price level to fetch, use 0 for all + * @param bool $useCache To use cache or not + * @return int <0 KO, >0 OK + */ + public function fetchCombinationPriceLevels($fk_price_level = 0, $useCache = true) + { + global $conf; + + // Check cache + if (!empty($this->combination_price_levels) && $useCache){ + if ((!empty($fk_price_level) && isset($this->combination_price_levels[$fk_price_level])) || empty($fk_price_level)){ + return 1; + } + } + + if (!is_array($this->combination_price_levels) + || empty($fk_price_level) // if fetch an unique level dont erase all already fetched + ){ + $this->combination_price_levels = array(); + } + + $staticProductCombinationLevel = new ProductCombinationLevel($this->db); + $combination_price_levels = $staticProductCombinationLevel->fetchAll($this->id, $fk_price_level); + + if (!is_array($combination_price_levels)) { + return -1; + } + + if (empty($combination_price_levels)){ + + /** + * for auto retrocompatibility with last behavior + */ + $productCombinationLevel = new ProductCombinationLevel($this->db); + $productCombinationLevel->fk_price_level = intval($fk_price_level); + $productCombinationLevel->fk_product_attribute_combination = $this->id; + $productCombinationLevel->variation_price = $this->variation_price; + $productCombinationLevel->variation_price_percentage = $this->variation_price_percentage; + + if ($fk_price_level>0){ + $combination_price_levels[$fk_price_level] = $productCombinationLevel; + } + else { + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){ + $combination_price_levels[$i] = $productCombinationLevel; + } + } + } + + $this->combination_price_levels = $combination_price_levels; + + return 1; + } + + /** + * Retrieves combination price levels + * + * @param int $clean Levels of PRODUIT_MULTIPRICES_LIMIT + * @return int <0 KO, >0 OK + */ + public function saveCombinationPriceLevels($clean = 1) + { + global $conf; + + $error = 0; + + $staticProductCombinationLevel = new ProductCombinationLevel($this->db); + + // Delete all + if (empty($this->combination_price_levels)) { + return $staticProductCombinationLevel->deleteAllForCombination($this->id); + } + + // Clean not needed price levels (level higher than number max defined into setup) + if ($clean) { + $res = $staticProductCombinationLevel->clean($this->id); + if ($res < 0) { + $this->errors[] = 'Fail to clean not needed price levels'; + return -1; + } + } + + foreach ($this->combination_price_levels as $fk_price_level => $combination_price_level) { + $res = $combination_price_level->save(); + if ($res < 1) { + $this->error = 'Error saving combination price level '.$fk_price_level . ' : '.$combination_price_level->error; + $this->errors[] = $this->error; + $error++; + break; + } + } + + if ($error){ + return $error * -1; + } + else { + return 1; + } + } + + /** * Retrieves a product combination by a child product row id * @@ -124,6 +241,8 @@ class ProductCombination */ public function fetchByFkProductChild($fk_child) { + global $conf; + $sql = "SELECT rowid, fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight FROM ".MAIN_DB_PREFIX."product_attribute_combination WHERE fk_product_child = ".(int) $fk_child." AND entity IN (".getEntity('product').")"; $query = $this->db->query($sql); @@ -145,6 +264,10 @@ class ProductCombination $this->variation_price_percentage = $result->variation_price_percentage; $this->variation_weight = $result->variation_weight; + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $this->fetchCombinationPriceLevels(); + } + return 1; } @@ -156,6 +279,8 @@ class ProductCombination */ public function fetchAllByFkProductParent($fk_product_parent) { + global $conf; + $sql = "SELECT rowid, fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight FROM ".MAIN_DB_PREFIX."product_attribute_combination WHERE fk_product_parent = ".(int) $fk_product_parent." AND entity IN (".getEntity('product').")"; $query = $this->db->query($sql); @@ -175,6 +300,10 @@ class ProductCombination $tmp->variation_price_percentage = $result->variation_price_percentage; $tmp->variation_weight = $result->variation_weight; + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $tmp->fetchCombinationPriceLevels(); + } + $return[] = $tmp; } @@ -209,19 +338,30 @@ class ProductCombination */ public function create($user) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute_combination - (fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight, entity) - VALUES (".(int) $this->fk_product_parent.", ".(int) $this->fk_product_child.", - ".(float) $this->variation_price.", ".(int) $this->variation_price_percentage.", - ".(float) $this->variation_weight.", ".(int) $this->entity.")"; + global $conf; - $query = $this->db->query($sql); + /* $this->fk_product_child may be empty and will be filled later after subproduct has been created */ - if (!$query) { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_attribute_combination"; + $sql .= " (fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight, entity)"; + $sql .= " VALUES (".((int) $this->fk_product_parent).", ".((int) $this->fk_product_child).","; + $sql .= (float) $this->variation_price.", ".(int) $this->variation_price_percentage.","; + $sql .= (float) $this->variation_weight.", ".(int) $this->entity.")"; + + $resql = $this->db->query($sql); + if ($resql) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute_combination'); + } else { + $this->error = $this->db->lasterror(); return -1; } - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'product_attribute_combination'); + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $res = $this->saveCombinationPriceLevels(); + if ($res < 0) { + return -2; + } + } return 1; } @@ -234,17 +374,25 @@ class ProductCombination */ public function update(User $user) { - $sql = "UPDATE ".MAIN_DB_PREFIX."product_attribute_combination - SET fk_product_parent = ".(int) $this->fk_product_parent.", fk_product_child = ".(int) $this->fk_product_child.", - variation_price = ".(float) $this->variation_price.", variation_price_percentage = ".(int) $this->variation_price_percentage.", - variation_weight = ".(float) $this->variation_weight." WHERE rowid = ".(int) $this->id; + global $conf; - $query = $this->db->query($sql); + $sql = "UPDATE ".MAIN_DB_PREFIX."product_attribute_combination"; + $sql .= " SET fk_product_parent = ".(int) $this->fk_product_parent.", fk_product_child = ".(int) $this->fk_product_child.","; + $sql .= " variation_price = ".(float) $this->variation_price.", variation_price_percentage = ".(int) $this->variation_price_percentage.","; + $sql .= " variation_weight = ".(float) $this->variation_weight." WHERE rowid = ".((int) $this->id); - if (!$query) { + $resql = $this->db->query($sql); + if (! $resql) { return -1; } + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + $res = $this->saveCombinationPriceLevels(); + if ($res < 0) { + return -2; + } + } + $parent = new Product($this->db); $parent->fetch($this->fk_product_parent); @@ -266,6 +414,12 @@ class ProductCombination $comb2val = new ProductCombination2ValuePair($this->db); $comb2val->deleteByFkCombination($this->id); + // remove combination price levels + if (!$this->db->query("DELETE FROM ".MAIN_DB_PREFIX."product_attribute_combination_price_level WHERE fk_product_attribute_combination = ".(int) $this->id)) { + $this->db->rollback(); + return -1; + } + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_combination WHERE rowid = ".(int) $this->id; if ($this->db->query($sql)) { @@ -341,6 +495,7 @@ class ProductCombination $child->label = $parent->label.$varlabel;; } + if ($child->update($child->id, $user) > 0) { $new_vat = $parent->tva_tx; $new_npr = $parent->tva_npr; @@ -349,9 +504,12 @@ class ProductCombination if (!empty($conf->global->PRODUIT_MULTIPRICES)) { for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) { - if ($parent->multiprices[$i] != '') { + if ($parent->multiprices[$i] != '' || isset($this->combination_price_levels[$i]->variation_price)) { $new_type = $parent->multiprices_base_type[$i]; $new_min_price = $parent->multiprices_min[$i]; + $variation_price = doubleval(!isset($this->combination_price_levels[$i]->variation_price) ? $this->variation_price : $this->combination_price_levels[$i]->variation_price); + $variation_price_percentage = doubleval(!isset($this->combination_price_levels[$i]->variation_price_percentage) ? $this->variation_price_percentage : $this->combination_price_levels[$i]->variation_price_percentage); + if ($parent->prices_by_qty_list[$i]) { $new_psq = 1; } else { @@ -364,12 +522,12 @@ class ProductCombination $new_price = $parent->multiprices[$i]; } - if ($this->variation_price_percentage) { + if ($variation_price_percentage) { if ($new_price != 0) { - $new_price *= 1 + ($this->variation_price / 100); + $new_price *= 1 + ($variation_price / 100); } } else { - $new_price += $this->variation_price; + $new_price += $variation_price; } $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, $i, $new_npr, $new_psq); @@ -445,10 +603,10 @@ class ProductCombination } /** - * Retrieves all unique attributres for a parent product + * Retrieves all unique attributes for a parent product * - * @param int $productid Product rowid - * @return ProductAttribute[] + * @param int $productid Product rowid + * @return ProductAttribute[] Array of attributes */ public function getUniqueAttributesAndValuesByFkProductParent($productid) { @@ -458,13 +616,11 @@ class ProductCombination $variants = array(); //Attributes - $sql = "SELECT DISTINCT fk_prod_attr, a.rang -FROM ".MAIN_DB_PREFIX."product_attribute_combination2val c2v LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination c - ON c2v.fk_prod_combination = c.rowid - LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = c.fk_product_child - LEFT JOIN ".MAIN_DB_PREFIX."product_attribute a ON a.rowid = fk_prod_attr -WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; - + $sql = "SELECT DISTINCT fk_prod_attr, a.rang"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_attribute_combination2val c2v LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination c ON c2v.fk_prod_combination = c.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = c.fk_product_child"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute a ON a.rowid = fk_prod_attr"; + $sql .= " WHERE c.fk_product_parent = ".((int) $productid)." AND p.tosell = 1"; $sql .= $this->db->order('a.rang', 'asc'); $query = $this->db->query($sql); @@ -493,7 +649,6 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; /** * Creates a product combination. Check usages to find more about its use - * * Format of $combinations array: * array( * 0 => array( @@ -504,15 +659,15 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; * [...] * ) * - * @param User $user Object user - * @param Product $product Parent product - * @param array $combinations Attribute and value combinations. - * @param array $variations Price and weight variations - * @param bool $price_var_percent Is the price variation a relative variation? - * @param bool|float $forced_pricevar If the price variation is forced - * @param bool|float $forced_weightvar If the weight variation is forced - * @param bool|string $forced_refvar If the reference is forced - * @return int <0 KO, >0 OK + * @param User $user Object user + * @param Product $product Parent product + * @param array $combinations Attribute and value combinations. + * @param array $variations Price and weight variations + * @param bool|array $price_var_percent Is the price variation a relative variation? + * @param bool|float $forced_pricevar If the price variation is forced + * @param bool|float $forced_weightvar If the weight variation is forced + * @param bool|string $forced_refvar If the reference is forced + * @return int <0 KO, >0 OK */ public function createProductCombination(User $user, Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false, $forced_refvar = false) { @@ -523,6 +678,8 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $db->begin(); + $price_impact = array(1=>0); // init level price impact + $forced_refvar = trim($forced_refvar); if (!empty($forced_refvar) && $forced_refvar != $product->ref) { @@ -545,7 +702,12 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $weight_impact = (float) $forced_weightvar; // If false, return 0 //Final price impact - $price_impact = (float) $forced_pricevar; // If false, return 0 + if (!is_array($forced_pricevar)) { + $price_impact[1] = (float) $forced_pricevar; // If false, return 0 + } + else { + $price_impact = $forced_pricevar; + } $newcomb = new ProductCombination($db); $existingCombination = $newcomb->fetchByProductCombination2ValuePairs($product->id, $combinations); @@ -554,7 +716,12 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $newcomb = $existingCombination; } else { $newcomb->fk_product_parent = $product->id; - if ($newcomb->create($user) < 0) { // Create 1 entry into product_attribute_combination (1 entry for all combinations) + + // Create 1 entry into product_attribute_combination (1 entry for each combinations). This init also $newcomb->id + $result = $newcomb->create($user); + if ($result < 0) { + $this->error = $newcomb->error; + $this->errors = $newcomb->errors; $db->rollback(); return -1; } @@ -578,6 +745,8 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $tmp->fk_prod_combination = $newcomb->id; if ($tmp->create($user) < 0) { // Create 1 entry into product_attribute_combination2val + $this->error = $tmp->error; + $this->errors = $tmp->errors; $db->rollback(); return -1; } @@ -587,7 +756,15 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; $weight_impact += (float) price2num($variations[$currcombattr][$currcombval]['weight']); } if ($forced_pricevar === false) { - $price_impact += (float) price2num($variations[$currcombattr][$currcombval]['price']); + $price_impact[1] += (float) price2num($variations[$currcombattr][$currcombval]['price']); + + // Manage Price levels + if ($conf->global->PRODUIT_MULTIPRICES){ + for ($i = 2; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) + { + $price_impact[$i] += (float) price2num($variations[$currcombattr][$currcombval]['price']); + } + } } if ($forced_refvar === false) { @@ -606,9 +783,28 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; } $newcomb->variation_price_percentage = $price_var_percent; - $newcomb->variation_price = $price_impact; + $newcomb->variation_price = $price_impact[1]; $newcomb->variation_weight = $weight_impact; + // Init price level + if ($conf->global->PRODUIT_MULTIPRICES){ + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){ + $productCombinationLevel = new ProductCombinationLevel($this->db); + $productCombinationLevel->fk_product_attribute_combination = $newcomb->id; + $productCombinationLevel->fk_price_level = $i; + $productCombinationLevel->variation_price = $price_impact[$i]; + + if (is_array($price_var_percent)){ + $productCombinationLevel->variation_price_percentage = !empty($price_var_percent[$i]) ? $price_var_percent[$i] : 0; + }else { + $productCombinationLevel->variation_price_percentage = $price_var_percent; + } + + $newcomb->combination_price_levels[$i] = $productCombinationLevel; + } + } + //var_dump($newcomb->combination_price_levels); + $newproduct->weight += $weight_impact; // Now create the product @@ -676,6 +872,8 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; if ($newcomb->update($user) < 0) { + $this->error = $newcomb->error; + $this->errors = $newcomb->errors; $db->rollback(); return -1; } @@ -764,3 +962,253 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1"; return $label; } } + + + +/** + * Class ProductCombinationLevel + * Used to represent a product combination Level + */ +class ProductCombinationLevel +{ + /** + * Database handler + * @var DoliDB + */ + private $db; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'product_attribute_combination_price_level'; + + /** + * Rowid of combination + * @var int + */ + public $id; + + /** + * Rowid of parent product combination + * @var int + */ + public $fk_product_attribute_combination; + + /** + * Combination price level + * @var int + */ + public $fk_price_level; + + /** + * Price variation + * @var float + */ + public $variation_price; + + /** + * Is the price variation a relative variation? + * @var bool + */ + public $variation_price_percentage = false; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } + + /** + * Retrieves a combination level by its rowid + * + * @param int $rowid Row id + * @return int <0 KO, >0 OK + */ + public function fetch($rowid) + { + $sql = "SELECT rowid, fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage FROM " . MAIN_DB_PREFIX . $this->table_element." WHERE rowid = " . (int) $rowid; + + $obj = $this->db->getRow($sql); + + if ($obj){ + return $this->fetchFormObj($obj); + } + + return -1; + } + + + /** + * Retrieves combination price levels + * + * @param int $fk_product_attribute_combination Id of product combination + * @param int $fk_price_level The price level to fetch, use 0 for all + * @return mixed self[] | -1 on KO + */ + public function fetchAll($fk_product_attribute_combination, $fk_price_level = 0) + { + + $sql = "SELECT rowid, fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " WHERE fk_product_attribute_combination = ".intval($fk_product_attribute_combination); + + if (!empty($fk_price_level)){ + $sql.= ' AND fk_price_level = '.intval($fk_price_level); + } + + $combination_price_levels = $this->db->getRows($sql); + + if (!is_array($combination_price_levels)) { + return -1; + } + + $result = array(); + + if (!empty($combination_price_levels)) { + // For more simple usage set level as array key + foreach ($combination_price_levels as $k => $row){ + $productCombinationLevel = new ProductCombinationLevel($this->db); + $productCombinationLevel->fetchFormObj($row); + $result[$row->fk_price_level] = $productCombinationLevel; + } + } + + return $result; + } + + /** + * assign vars form an stdclass like sql obj + * + * @param int $obj Object resultset + * @return int <0 KO, >0 OK + */ + public function fetchFormObj($obj) + { + if (!$obj) { + return -1; + } + + $this->id = $obj->rowid; + $this->fk_product_attribute_combination = doubleval($obj->fk_product_attribute_combination); + $this->fk_price_level = intval($obj->fk_price_level); + $this->variation_price = doubleval($obj->variation_price); + $this->variation_price_percentage = (bool) $obj->variation_price_percentage; + + return 1; + } + + + /** + * Save a price impact of a product combination for a price level + * + * @return int <0 KO, >0 OK + */ + public function save() + { + if (($this->id > 0 && empty($this->fk_product_attribute_combination)) || empty($this->fk_price_level)) { + return -1; + } + + // Check if level exist in DB before add + if ($this->fk_product_attribute_combination > 0 && empty($this->id)) { + $sql = "SELECT rowid id"; + $sql .= " FROM ".MAIN_DB_PREFIX . $this->table_element; + $sql .= " WHERE fk_product_attribute_combination = ".(int) $this->fk_product_attribute_combination; + $sql .= ' AND fk_price_level = '.intval($this->fk_price_level); + + $existObj = $this->db->getRow($sql); + if ($existObj) { + $this->id = $existObj->id; + } + } + + // Update + if (!empty($this->id)) { + $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element; + $sql .= ' SET variation_price = '.doubleval($this->variation_price).' , variation_price_percentage = '.intval($this->variation_price_percentage); + $sql .= ' WHERE rowid = '.((int) $this->id); + + $res = $this->db->query($sql); + if ($res > 0) { + return $this->id; + } else { + $this->error = $this->db->error(); + $this->errors[] = $this->error; + return -1; + } + } else { + // Add + $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " ("; + $sql .= "fk_product_attribute_combination, fk_price_level, variation_price, variation_price_percentage"; + $sql .= ") VALUES ("; + $sql .= (int) $this->fk_product_attribute_combination; + $sql .= ", ".intval($this->fk_price_level); + $sql .= ", ".doubleval($this->variation_price); + $sql .= ", ".intval($this->variation_price_percentage); + $sql .= ")"; + + $res = $this->db->query($sql); + if ($res) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); + } else { + $this->error = $this->db->error(); + $this->errors[] = $this->error; + return -1; + } + } + + return $this->id; + } + + + /** + * delete + * + * @return int <0 KO, >0 OK + */ + public function delete() + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".(int) $this->id; + $res = $this->db->query($sql); + + return $res ? 1 : -1; + } + + + /** + * delete all for a combination + * + * @param int $fk_product_attribute_combination Id of combination + * @return int <0 KO, >0 OK + */ + public function deleteAllForCombination($fk_product_attribute_combination) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE fk_product_attribute_combination = ".(int) $fk_product_attribute_combination; + $res = $this->db->query($sql); + + return $res ? 1 : -1; + } + + + /** + * Clean not needed price levels for a combination + * + * @param int $fk_product_attribute_combination Id of combination + * @return int <0 KO, >0 OK + */ + public function clean($fk_product_attribute_combination) + { + global $conf; + + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " WHERE fk_product_attribute_combination = ".(int) $fk_product_attribute_combination; + $sql .= " AND fk_price_level > ".intval($conf->global->PRODUIT_MULTIPRICES_LIMIT); + $res = $this->db->query($sql); + + return $res ? 1 : -1; + } +} diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index 3886a8fcdce..9b9a2ba6680 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -33,6 +33,10 @@ $ref = GETPOST('ref', 'alpha'); $weight_impact = GETPOST('weight_impact', 'alpha'); $price_impact = GETPOST('price_impact', 'alpha'); $price_impact_percent = (bool) GETPOST('price_impact_percent'); + +$level_price_impact = GETPOST('level_price_impact', 'array'); +$level_price_impact_percent = GETPOST('level_price_impact_percent', 'array'); + $reference = GETPOST('reference', 'alpha'); $form = new Form($db); @@ -112,6 +116,17 @@ if ($_POST) { } $weight_impact = price2num($weight_impact); $price_impact = price2num($price_impact); + + // for conf PRODUIT_MULTIPRICES + if ($conf->global->PRODUIT_MULTIPRICES) { + $level_price_impact = array_map('price2num', $level_price_impact); + $level_price_impact_percent = array_map('price2num', $level_price_impact_percent); + } + else { + $level_price_impact = array(1 => $weight_impact); + $level_price_impact_percent = array(1 => $price_impact_percent); + } + $sanit_features = array(); //First, sanitize @@ -141,11 +156,9 @@ if ($_POST) { // sanit_feature is an array with 1 (and only 1) value per attribute. // For example: Color->blue, Size->Small, Option->2 //var_dump($sanit_features); - //var_dump($productCombination2ValuePairs1); exit; - if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features)) { - $result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact, $reference); + $result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $level_price_impact_percent, $level_price_impact, $weight_impact, $reference); if ($result > 0) { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); @@ -156,7 +169,7 @@ if ($_POST) { exit(); } else { $langs->load("errors"); - setEventMessages('', $prodcomb->errors, 'errors'); + setEventMessages($prodcomb->error, $prodcomb->errors, 'errors'); } } else { setEventMessages($langs->trans('ErrorRecordAlreadyExists'), null, 'errors'); @@ -227,6 +240,32 @@ if ($_POST) { $prodcomb->variation_price = $price_impact; $prodcomb->variation_weight = $weight_impact; + // for conf PRODUIT_MULTIPRICES + if ($conf->global->PRODUIT_MULTIPRICES) { + $level_price_impact = array_map('price2num', $level_price_impact); + $level_price_impact_percent = array_map(function ($a) { + return !empty($a);}, $level_price_impact_percent); + + $prodcomb->variation_price = $level_price_impact[1]; + $prodcomb->variation_price_percentage = (bool) $level_price_impact_percent[1]; + } + else { + $level_price_impact = array(1 => $weight_impact); + $level_price_impact_percent = array(1 => $price_impact_percent); + } + + if ($conf->global->PRODUIT_MULTIPRICES){ + $prodcomb->combination_price_levels = array(); + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++){ + $productCombinationLevel = new ProductCombinationLevel($db); + $productCombinationLevel->fk_product_attribute_combination = $prodcomb->id; + $productCombinationLevel->fk_price_level = $i; + $productCombinationLevel->variation_price = $level_price_impact[$i]; + $productCombinationLevel->variation_price_percentage = $level_price_impact_percent[$i]; + $prodcomb->combination_price_levels[$i] = $productCombinationLevel; + } + } + if ($prodcomb->update($user) > 0) { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); header('Location: '.dol_buildpath('/variants/combinations.php?id='.$id, 2)); @@ -505,8 +544,8 @@ if (!empty($id) || !empty($ref)) dol_fiche_head(); - print ''; if ($action == 'add') { + print '
    '; print "\n"; print ''; print ''; @@ -527,9 +566,9 @@ if (!empty($id) || !empty($ref)) print $langs->trans("Create"); print '';*/ + print ''; + print ''; ?> - - @@ -553,64 +592,117 @@ if (!empty($id) || !empty($ref)) "> - '; print ''; + print '
    - '; + print $listofvariantselected; print '
    '; + print '
    '; } if (is_array($productCombination2ValuePairs1)) { - ?> -
    - - - - '; print ''; print ''; print '
    -
    + print ''; + + // When in edit mode + if (is_array($productCombination2ValuePairs1) && count($productCombination2ValuePairs1)) + { + ?> + + + - - + + + + + + + global->PRODUIT_MULTIPRICES)) { + ?> + > + - fetchCombinationPriceLevels(); + + for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) + { + print ''; + print ''; + print ''; + print ''; + } + } + if ($object->isProduct()) { print ''; print ''; print ''; print ''; } + print '
    +
    $val) { - $result1 = $prodattr->fetch($val->fk_prod_attr); - $result2 = $prodattr_val->fetch($val->fk_prod_attr_val); - if ($result1 > 0 && $result2 > 0) - { - print $prodattr->label.' - '.$prodattr_val->value.'
    '; - // TODO Add delete link - } - } + foreach ($productCombination2ValuePairs1 as $key => $val) { + $result1 = $prodattr->fetch($val->fk_prod_attr); + $result2 = $prodattr_val->fetch($val->fk_prod_attr_val); + //print 'rr'.$result1.' '.$result2; + if ($result1 > 0 && $result2 > 0) + { + print $prodattr->label.' - '.$prodattr_val->value.'
    '; + // TODO Add delete link + } } ?> -
    - -
    -
    +
    - >
    '; + if ($i===1){ + print ' ('.$langs->trans('ApplyToAllPriceImpactLevel').')'; + } + print ''; + print 'combination_price_levels[$i]->variation_price_percentage) ? ' checked' : '' ).'> '; + + print '
    '; } + if (!empty($conf->global->PRODUIT_MULTIPRICES)){ + ?> + + + ?>
    value="trans('Create') : $langs->trans('Save') ?>" class="button"> @@ -667,7 +759,8 @@ if (!empty($id) || !empty($ref)) }); - '; @@ -779,7 +872,7 @@ if (!empty($id) || !empty($ref)) print '
    '.$prodstatic->getLibStatut(2, 0).''.$prodstatic->getLibStatut(2, 1).''; - print 'id.'">'.img_edit().''; + print 'id.'">'.img_edit().''; print 'id.'">'.img_delete().''; print ''; diff --git a/htdocs/variants/list.php b/htdocs/variants/list.php index 53fa3ee70ec..971533bdd25 100644 --- a/htdocs/variants/list.php +++ b/htdocs/variants/list.php @@ -18,7 +18,6 @@ require '../main.inc.php'; require DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php'; -$id = GETPOST('id', 'int'); $action = GETPOST('action', 'aZ09'); $object = new ProductAttribute($db); @@ -66,7 +65,7 @@ print load_fiche_titre($title, $newcardbutton, 'product'); $forcereloadpage = empty($conf->global->MAIN_FORCE_RELOAD_PAGE) ? 0 : 1; ?> -