diff --git a/.tx/config b/.tx/config index b98bf7828f2..dae10d60866 100644 --- a/.tx/config +++ b/.tx/config @@ -128,6 +128,12 @@ source_file = htdocs/langs/en_US/errors.lang source_lang = en_US type = MOZILLAPROPERTIES +[dolibarr.eventorganization] +file_filter = htdocs/langs//eventorganization.lang +source_file = htdocs/langs/en_US/eventorganization.lang +source_lang = en_US +type = MOZILLAPROPERTIES + [dolibarr.exports] file_filter = htdocs/langs//exports.lang source_file = htdocs/langs/en_US/exports.lang @@ -182,6 +188,12 @@ source_file = htdocs/langs/en_US/interventions.lang source_lang = en_US type = MOZILLAPROPERTIES +[dolibarr.knowledgemanagement] +file_filter = htdocs/langs//knowledgemanagement.lang +source_file = htdocs/langs/en_US/knowledgemanagement.lang +source_lang = en_US +type = MOZILLAPROPERTIES + [dolibarr.languages-not-res] file_filter = htdocs/langs//languages.lang source_file = htdocs/langs/en_US/languages.lang @@ -278,6 +290,12 @@ source_file = htdocs/langs/en_US/other.lang source_lang = en_US type = MOZILLAPROPERTIES +[dolibarr.partnership] +file_filter = htdocs/langs//partnership.lang +source_file = htdocs/langs/en_US/partnership.lang +source_lang = en_US +type = MOZILLAPROPERTIES + [dolibarr.paybox] file_filter = htdocs/langs//paybox.lang source_file = htdocs/langs/en_US/paybox.lang diff --git a/COPYRIGHT b/COPYRIGHT index b133b05b2cf..c43d77581a7 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,52 +1,63 @@ -License -------- +Copyright and license +---------------------- -Dolibarr is released 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 (GPL-3+). -More information: https://www.gnu.org/licenses/gpl-3.0.txt +The Dolibarr software as a whole is distributed under 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 (GPL-3+). More information: https://www.gnu.org/licenses/gpl-3.0.txt. +A copy of this license is available in the COPYING file. +Dolibarr depends on third-party components and code snippets released under their own license (obviously, all compatible with the one of Dolibarr). +These dependencies are listed in the bottom of this file. -Dolibarr uses some external libraries released under different licenses. This is compatibility summary: + +The Dolibarr images resources (available in the doc directory) is distributed under the Creative Commons Attribution 4.0 International license (CC BY 4.0). + + +The name Dolibarr is a trademark initially registered by Laurent Destailleur and ceased to the Dolibarr foundation. You can use the name Dolibarr +for your own need as long as you follow the rules defined on the page https://wiki.dolibarr.org/index.php/Rules_to_use_the_brand_name_%22Dolibarr%22 +The use of the name DoliStore is also restricted to the same rules defined on https://wiki.dolibarr.org/index.php/Rules_to_use_the_brand_name_%22Dolibarr%22 + + + +Licence of dependencies of third-party components used by Dolibarr (all compatible with the Licence of Dolibarr): Component Version License GPL Compatible Usage ------------------------------------------------------------------------------------- PHP libraries: -AdoDb-Date 0.36 Modified BSD License Yes Date convertion (not into rpm package) +ADOdb-Date 0.36 Modified BSD License Yes Date convertion (not into rpm package) CKEditor 4.12.1 LGPL-2.1+ Yes Editor WYSIWYG EvalMath 1.0 BSD Yes Safe math expressions evaluation Escpos-php 2.2 MIT License Yes Thermal receipt printer library, for use with ESC/POS compatible printers -GeoIP2 0.2.0 LGPL-2.1+ Yes Lib to make geoip convert +GeoIP2 0.2.0 Apache License 2.0 Yes Lib to make geoip convert Mobiledetect 2.8.34 MIT License Yes Detect mobile devices browsers NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) PEAR Mail_MIME 1.8.9 BSD Yes NuSoap dependency ParseDown 1.6 MIT License Yes Markdown parser PCLZip 2.8.4 LGPL-3+ Yes Library to zip/unzip files -PHPDebugBar 1.15.1 MIT License Yes Used only by the module "debugbar" for developers +PHPDebugBar 1.15.1 MIT License Yes Used only by the module "debugbar" for developers PHPSpreadSheet 1.8.2 LGPL-2.1+ Yes Read/Write XLS files, read ODS files php-iban 1.4.7 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP PHPoAuthLib 0.8.2 MIT License Yes Library to provide oauth1 and oauth2 to different service PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests -PSR/Logs 1.0 Library for logs (used by DebugBar) -PSR/simple-cache ? Library for cache (used by PHPSpreadSheet) +PSR/Logs 1.0 Library for logs (used by DebugBar) +PSR/simple-cache ? MIT License Yes Library for cache (used by PHPSpreadSheet) Restler 3.1.1 LGPL-3+ Yes Library to develop REST Web services (+ swagger-ui js lib into dir explorer) Sabre 3.2.2 BSD Yes DAV support -Swift Mailer 5.4.2-DEV MIT license Yes Comprehensive mailing tools for PHP -Stripe 7.67.0 MIT licence Yes Library for Stripe module +Swift Mailer 5.4.2-DEV MIT License Yes Comprehensive mailing tools for PHP +Stripe 7.67.0 MIT Licence Yes Library for Stripe module TCPDF 6.3.2 LGPL-3+ Yes PDF generation TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes FPDI replacement JS libraries: Ace 1.4.8 BSD Yes JS library to get code syntaxique coloration in a textarea. -ChartJS 2.9.4 MIT License Yes JS library for graph +ChartJS 2.9.4 MIT License Yes JS library for graph 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 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) jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors jQuery JCrop 0.9.8 GPL and MIT License Yes JS library plugin Crop (to crop images) jQuery Jeditable 1.7.1 GPL and MIT License Yes JS library plugin jeditable (to edit in place) -jQuery jNotify 1.1.00 Apache Software License 2.0 Yes JS library plugin jNotify (to use ajax popups) +jQuery jNotify 1.1.00 Apache License 2.0 Yes JS library plugin jNotify (to use ajax popups) jQuery jPicker 1.1.6 GPL and MIT License Yes JS library for color picker with not defined list of colors jQuery jqueryFileTree 1.0.1 GPL and MIT License Yes JS library for filetree jQuery jquerytreeview 1.4.1 MIT License Yes JS library for filetree @@ -54,20 +65,19 @@ jQuery TableDnD 0.6 GPL and MIT License Yes jQuery Timepicker 1.1.0 GPL and MIT License Yes JS library Timepicker addon for Datepicker jsGanttImproved 2.7.3 BSD License Yes JS library (to build Gantt reports) JsTimezoneDetect 1.0.6 MIT License Yes JS library to detect user timezone -SwaggerUI 2.0.24 GPL-2+ Yes JS library to offer the REST API explorer +SwaggerUI 2.2.10 GPL-2+ Yes JS library to offer the REST API explorer Image libraries: Octicons 8.1 MIT Yes Font libraries: -Fontawesome 5.13 Font Awesome Free licence Yes +Fontawesome 5.13 Font Awesome Free Licence Yes -For licenses compatibility informations: -https://www.gnu.org/licenses/licenses.en.html +For more licenses compatibility informations: https://www.gnu.org/licenses/licenses.en.html -Copyright / Authors +Authors ------------------- See page https://github.com/Dolibarr/dolibarr/graphs/contributors diff --git a/ChangeLog b/ChangeLog index 4734605b7d2..f52fbb55668 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,19 +7,160 @@ English Dolibarr ChangeLog For users: ---------- -NEW: Several security issues after a second private bug bounty campaign. - +NEW: Module Recruitement to follow application to job positions is now stable. +NEW: Feature to make Stock Inventories +NEW: Several security issues after a second private bug hunting campaign. +NEW: Add a security center page with all information and advices related to the security of your instance +NEW: Add a performance center page with all information and advices related to the performance of your instance +NEW: A lot of fix into english text after a small proofreading campaign (still not perfect, but really better) +NEW: All main menu entries are using the picto of the module +NEW: Add a copy to clipboard button on some fields +NEW: Add an example of scheduled job to send email reminder for unpaid invoices +NEW: Can make massive stock transfers from a CSV file. +NEW: Accountancy - Add FEC import +NEW: Accountancy - Add a confirmation form with options on export +NEW: Accountancy - Add select date from/to in already bind customer and supplier list +NEW: Accountancy - Format FEC - Add new field DateLimitReglmt +NEW: Accountancy - In ledger & journals, show link on bank transaction +NEW: Accountancy - Possibility to filter on journals in balance +NEW: Accountancy - Add a page to list subledger accounts +NEW: add the Channel column into the list of orders +NEW: Add a check to avoid an invoice date in the future +NEW: Add some color and picto for the direction of movement +NEW: Add the column "alias" of company in the list of proposal, order, invoice +NEW: Add the column "Office phone" and "User mobile" in user list +NEW: Add the column "Price level"in thirdparty list +NEW: Add some company information in the dropdown login menu +NEW: Add constant MAIN_BUGTRACK_URL to set a custom url to redirect to when clicking on link "declare a bug" +NEW: Add contact tag and bulk email status on the thirparty+contact create form +NEW: Add db fields note_public and note_private for ECM module +NEW: Support down payment on supplier invoice (& somes ajustments) +NEW: Add edit/delete action icons on categories list pages +NEW: Add hidden option to auto load input line extrafield into new lines +NEW: Add import profile to import BOM +NEW: Add last date of modification for website pages in the list of pages +NEW: Add link picto to the stock movement on the detail of production +NEW: Add mass action "Set tag" for product/service, user, thirdparty, warehouse, project, bank account, members +NEW: Add bulk action Validate and Set to billed on order list. +NEW: add bulk action to set a commercial proposal to status "Refused" +NEW: Add option CONTRACT_ALLOW_EXTERNAL_DOWNLOAD and SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD to make generated doc automatically shared. +NEW: Add option MAIN_SECURITY_ANTI_SSRF_SERVER_IP to define list of IPs that are local IPs +NEW: Add option SOCIETE_DISABLE_WORKFORCE to hide staff field +NEW: Add a new permission "Export website" +NEW: Add possibility to exports userGroups fields on user exports +NEW: Add price min and price min including tax into product export +NEW: Can search on lots or serials into the quick search bar +NEW: Add support for Friday as a non working day +NEW: Add a total in page of margin by user +NEW: Add the total of margin in invoice list +NEW: Can set a Warehouse on a Thirparty +NEW: auto notification with module Notification can use templated emails +NEW: Bank Entries : display user linked to a salary or a taxes +NEW: Can set a warehouse in a proposal +NEW: Can clone a cron job. +NEW: Can create a lot from the list view (Look and feel standardization). +NEW: Can filter files in GED on status Shared/Not shared +NEW: Can filter on extrafields date on lists +NEW: Can filter on rowid in list of blocked logs. +NEW: Can hide columns "time consumed" on timesheet per week. +NEW: Can set an employee on each social contribution +NEW: Can set a percentage when creating an invoice from another object +NEW: Can set if a ticket group is visible on public interface or not. +NEW: Can set order of execution of hooks +NEW: Can show the leave dates/holidays on the agenda view. +NEW: Can show the project ref into PDF documents +NEW: Can toggle FCKeditor on public/private notes +NEW: Can use captcha on public page to create a ticket +NEW: Check update availability for externals modules using a button on module page +NEW: Choose lines to use while creating intervention card from origin +NEW: Column shipment method, payment mode, payment term in proposal and order list +NEW: Conf for default actioncomm status +NEW: customer ref for product customer prices +NEW: date and user signature on proposal (Issue 16062) +NEW: Dictionary for availability - Add a column position +NEW: TAKEPOS delayed payment in TakePOS +NEW: TAKEPOS display date range if exist in TakePOS +NEW: TAKEPOS display resiliate status in TakePOS for member +NEW: TAKEPOS Edit sales lines rights in TakePOS +NEW: TAKEPOS Option for Takepos to show the total price without tax +NEW: TAKEPOS More permission in TakePOS (Can edit added line, can modify once order sent to kitchen) +NEW: Can set a user related to a social contribution +NEW: ICS Direct debit can be set with a different value for each bank account +NEW: LDAP: usergroup search can be filtered +NEW: Make public bookmarks editable by admin users only +NEW: If main logo not defined, can use the squarred logo on login page +NEW: The manifest file can use the squared image if available +NEW: Add bulk actions for Bank Transfer +NEW: Enhance the multicurrency rate editor +NEW: Multiselect ledger account code filter on book keeping list +NEW: Normalyse Type company field with ajax combobox +NEW: option to automatically close an open project when all its tasks are done (=progress 100%) +NEW: option to select membership type on the online payment page for membership subscription or renewal +NEW: preload product description on selection for customer propal/order/invoice +NEW: Add a ref in product customer price +NEW: Save old page with .old extension on disk when editing a website page +NEW: Search usergroups & resources +NEW: Set status of all variants when changing status of parent +NEW: Setup Page for module creation with module builder enhancement #FoundationFunding +NEW: Show picto of module into the list of dictionaries +NEW: Show the total of payment on the payment confirmation page +NEW: Stock movement list - Add more complete date field +NEW: Support color for types of event +NEW: The global setup for Mandatory fields can now be done on combo list too. +NEW: translate in "en_US" to complete PR 16980 +NEW: Update the list of taxes available by default for France +NEW: Add captcha on public page to create a ticket +NEW: Salary payment request and Salary payment are 2 different steps in workflow on Salary payment recording +NEW: VAT payment request and VAT payment are now 2 different steps in workflow on VAT payment recording +NEW: VAT report - Optimisation & collapse by rate +NEW: When we add contacts/users to a project, ask to also affect them on tasks. +NEW: When a doc file is shared, link is visible from the main page of doc. +NEW: Add option in Workflow module to set a shipment as closed. +NEW: Option to automatically create a login/user when a new subscription of a member is done online +NEW: #16378 More E-Mail Contact substitution Values for better salutation +NEW: option to keep the "Automatically create a total payment" checkbox empty on the tax creation page +NEW: #17113 Can upload a favicon in website module +NEW: #17292 default subscription amount by adherent type +NEW: start new experimental module Event Organization Management +NEW: start new experimental module Partnership Management +NEW: start new experimental module Knowledge Management +NEW: start new experimental module Workstations management For developers: --------------- -* start new module EventOrganization - +NEW: Can edit an object property in module builder +NEW: hook printFieldListTitle for cabyprodserv.php +NEW: Hook to allow external modules to add their own shortlist of recent objects +NEW: SQL-altering hooks in the turnover by product report +NEW: Add data-eec=1 for EEC countries on select for js interaction +NEW: Add experimental repair script to switch to dynamic row format and utf8mb4 encoding +NEW: add form confirm hook on company card +NEW: Add function showValueWithClipboardCPButton() to add a copy/paste +NEW: Add hook addSectionECMAuto method to add custom diretory into ECM auto files +NEW: Add native compression in rest apis +NEW: Product Variants API, add variant stock to response by parameter +NEW: Upgrade Stripe PHP lib to 7.67.0 +NEW: Add link to OpenAPI specifications xml file in REST API module setup: swagger.json file can be included into external tools like redoc +NEW: Support sepa_debit in stripe paymentmethods list +NEW: Update doleditor.class.php for easily activate SCAYT +NEW: Add triggers in the function add_object_linked(), updateObjectLinked() and deleteObjectLinked() +NEW: Add triggers OBJECT_LINK_INSERT, OBJECT_LINK_UPDATE et OBJECT_LINK_DELETE in the function add_object_linked(), updateObjectLinked() and deleteObjectLinked() +NEW: API Add option $includeifobjectisused to get a product +NEW: API Get the list of product ids only +NEW: Can set a target image in dolcropresize function. +NEW: Can set a label as placeholder for combo lists. +NEW: Add pagination on Get Products response API +NEW: Add the DefaultValues CRUD class +NEW: Extrafields of documents lines are inside the lines, not any more on separate TR +NEW: unit selection on object edit line +NEW: #13739 #17390 Product API route added to get product stock and product with or without variants WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: +* Module SimplePOS is deprecated. If you need a POS module, please use the module TakePOS. * The ICS value for direct debit or credit transfer is now store on each bank account instead of into the global setup. * API /setup/shipment_methods has been replaced with API /setup/shipping_methods * Field "total" renamed into to "total_ht" for table llx_facture, llx_facture_rec for better field name consistency @@ -28,6 +169,64 @@ Following changes may create regressions for some external modules, but were nec * If your database is PostgreSql, you must use version 9.1.0 or more (Dolibarr need the SQL function CONCAT) * If your database is MySql or MariaDB, you need at least version 5.1 * Function set_price_level() has been renamed into setPriceLevel() to follow camelcase rules +* Remove deprecated subtituion key __REFCLIENT__ (Replaced with __REF_CLIENT__) + +***** ChangeLog for 13.0.3 compared to 13.0.2 ***** + +FIX: 13.0 warning - missing quotes around 'label' +FIX: #16143 Old PG requires "()" on DROP FUNCTION +FIX: #16843 +FIX: #17060 +FIX: #17192 - With tz < 0, event is show in bad day on calendar views +FIX: #17363 +FIX: #17476 releve.php: Fix SQL statement +FIX: Accountancy - Import in general ledger +FIX: Accountancy - Quadra export - wrong data on credit +FIX: Accountancy - Warning on the pages of the preparatory statements of accounting entries +FIX: Add function price2num for rounding values in productAlertStock box +FIX: Add parameter to function price2num() +FIX: Cannot delete a batch material from item receipts +FIX: cast int +FIX: Change parameters MF to MS for price2num() function +FIX: create event from contact card preselect contact correctly +FIX: create sociales : keep values error form +FIX: dol_print_date for %a and %b with some timezone +FIX: email is not case sensitive +FIX: error for duplicate thirdparty found correctly returned by ws +FIX: Espadon PDF shippment model with long public note now wroking +FIX: esupplier order: error 500 when using packaging with product where it is not defined +FIX: Filter on debit/credit +FIX: Filter on supplier payment list +FIX: fix checkbox displayed according to module project setup parameters - work in progress +FIX: inconsistency in margin recording with option "Force to sale price" +FIX: invoice PDF generation after payment +FIX: mask selector fournisseur if module not activate +FIX: merge thirparty also work for bank URL entry +FIX: Missing extrafields into export of agenda record +FIX: missing parameter in select for POP +FIX: missing return edit if update error +FIX: missing token on dolGetButtonAction for action delete +FIX: payment creation: re-generate invoice PDF with correct display options +FIX: payment validation: invoices PDF were no re-generated, make it with correct display options +FIX: Periodicity by default on fiscal year, according to the now date, we have plus 1 year added +FIX: pgsql: prevent 'WHERE 1' +FIX: PHP version requirement in composer.json +FIX: project visibility field with two option +FIX: saving template email +FIX: search accented words in product description (consumption page) +FIX: Search on date in accountancy +FIX: selection of project for reception must use +FIX: shhhhhh ! There is nothing here... +FIX: Show input field checkbox selection +FIX: Show Ref.Supplier in LinkToObjectBlock +FIX: SQL Error show_contacts : socialnetworks +FIX: Start hour on ACCOUNTING_DATE_START_BINDING +FIX: supplier order: error 500 when using packaging with product where it is not defined +FIX: test must be === and not == +FIX: test on link type +FIX: type link extrafield case for advanced target emailing +FIX: Write right on document +>>>>>>> branch '13.0' of git@github.com:Dolibarr/dolibarr.git ***** ChangeLog for 13.0.2 compared to 13.0.1 ***** diff --git a/README-FR.md b/README-FR.md index 77bb5a3e27a..81fdff13047 100644 --- a/README-FR.md +++ b/README-FR.md @@ -8,10 +8,12 @@ Il est simple d'utilisation et modulaire, vous permettant de n'activez que les f ![ScreenShot](https://www.dolibarr.org/medias/dolibarr_screenshot1_1920x1080.jpg) + ## LICENCE Dolibarr est distribué sous les termes de la licence GNU General Public License v3+ ou supérieure. + ## INSTALLER DOLIBARR ### Configuration simple @@ -52,6 +54,7 @@ Vous pouvez aussi utiliser un serveur Web et une base de données prise en charg - Suivez les instructions de l'installateur + ## METTRE A JOUR DOLIBARR Pour mettre à jour Dolibarr depuis une vieille version vers celle ci: @@ -64,9 +67,11 @@ Pour mettre à jour Dolibarr depuis une vieille version vers celle ci: *Note: Le processus de migration peut être lancé manuellement et plusieurs fois, sans risque, en appelant la page /install/* + ## CE QUI EST NOUVEAU -Voir fichier ChangeLog. +See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) file. + ## CE QUE DOLIBARR PEUT FAIRE @@ -82,15 +87,17 @@ Voir fichier ChangeLog. - Calendrier/Agenda partagé (avec export ical, vcal) - Suivi des opportunités et/ou projets (suivi de rentabilité incluant les factures, notes de frais, temps consommé valorisé, ...) - Gestion de contrats de services -- Gestion de stock +- Gestion de stock et inventaires - Gestion des expéditions - Gestion des demandes de congès - Gestion des notes de frais +- Gestion de recrutement - GED (Gestion Electronique de Documents) - EMailings de masse - Réalisation de sondages +- Gestion d'adhérents - Point de vente/Caisse enregistreuse -- … +- … (près de 100 modules disponibles en standard, près de 1000 autre sur la place de marché d'extensions) ### Autres modules @@ -135,31 +142,36 @@ Voir fichier ChangeLog. Dolibarr peut aussi être étendu à volonté avec l'ajout de module/applications externes développées par des développeus tiers, disponible sur [DoliStore](https://www.dolistore.com). + ## CE QUE DOLIBARR NE PEUT PAS (ENCORE) FAIRE Voici un liste de fonctionnalités pas encore gérées par Dolibarr: -- Dolibarr ne contient pas de module de Gestion de la paie. +- Dolibarr ne contient pas de module de génération de feuille de paie. - Les tâches du module de gestion de projets n'ont pas de dépendances entre elle. - Dolibarr n'embarque pas de Webmail intégré nativement. - Dolibarr ne fait pas le café (pas encore). + ## DOCUMENTATION La documentation utilisateur, développeur et traducteur est disponible sous forme de ressources de la communauté via le site [Wiki](https://wiki.dolibarr.org). + ## CONTRIBUER Ce projet existe grâce à ses nombreux contributeurs [[Contribuer](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md)]. + ## CREDITS Dolibarr est le résultat du travail de nombreux contributeurs depuis des années et utilise des librairies d'autres contributeurs. Voir le fichier [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) + ## ACTUALITES ET RESEAUX SOCIAUX Suivez le projet Dolibarr project sur les réseaux francophones diff --git a/README.md b/README.md index 0a3aeecb9f4..736925bec72 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ 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 access it from the Internet or a LAN. -Dolibarr has a large community ready to help you, free forums and [officially preferred partners ready to offer commercial support should you need it](https://partners.dolibarr.org) +Dolibarr has a large community ready to help you, free forums and [preferred partners ready to offer commercial support should you need it](https://partners.dolibarr.org) ![ScreenShot](https://www.dolibarr.org/medias/dolibarr_screenshot1_1920x1080.jpg) @@ -97,40 +97,68 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) ### Main application/modules (all optional) -- Customers, Prospects (Leads) and/or Suppliers directory + Contacts -- Members/Membership management -- Products and/or Services catalog -- Commercial proposals management -- Customer & Supplier Orders management -- Invoices and payment management -- Shipping management -- Warehouse/Stock management -- Manufacturing Orders -- Bank accounts management -- Direct debit orders management (European SEPA) -- Accounting management -- Shared calendar/agenda (with ical and vcal export for third party tools integration) -- Opportunities or Leads management -- Projects & Tasks management -- Ticket System -- Contracts management -- Interventions management -- Employee's leave requests management -- Expense reports -- Timesheets -- Electronic Document Management (EDM) -- Foundations members management -- Point of Sale (POS) -- … +- Third-Parties Management: Customers, Prospects (Leads) and/or Suppliers + Contacts +- Members/Membership/Foundation management + + Product Management +- Products and/or Services catalog +- Stock / Warehouse management + Inventory +- Barcodes +- Batches / Lots / Serials +- Product Variants +- Bill of Materials +- Manufacturing Orders + + Customer/Sales Management +- Customers/Prospects + Contacts management +- Opportunities or Leads management +- Commercial proposals management +- Customer Orders management +- Contracts/Subscription management +- Interventions management +- Ticket System +- Shipping management +- Customer Invoices/Credit notes and payment management +- Point of Sale (POS) + + Supplier/Purchase Management +- Suppliers/Vendors + Contacts +- Supplier (price) requests +- Purchase Order management +- Delivery/Receiption +- Supplier Invoices/credit notes and payment management + + Finance / Accounting +- Invoices / Payments +- Bank accounts management +- Direct debit orders management (European SEPA) +- Accounting management +- Donations management +- Loan management +- Margins +- Reports + + +- Shared calendar/agenda (with ical and vcal export for third party tools integration) +- Projects & Tasks management +- Ticket System + +- Employee's leave requests management +- Expense reports +- Recruitment management +- Timesheets + +- (around 100 modules available by default, 1000+ on the addon market place) + ### Other application/modules +- Electronic Document Management (EDM) - Bookmarks management -- Donations management - Reporting - Surveys - Data export/import -- Barcodes support +- Barcodes - Margin calculations - LDAP connectivity - ClickToDial integration @@ -138,7 +166,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) - RSS integration - Skype integration - Payment platforms integration (PayPal, Stripe, Paybox...) -- … +- ### Other general features diff --git a/build/debian/README.howto b/build/debian/README.howto index c38a53718ae..45df1e9df70 100644 --- a/build/debian/README.howto +++ b/build/debian/README.howto @@ -51,16 +51,17 @@ export DEBEMAIL="eldy@destailleur.fr" export QUILT_PATCHES=debian/patches -# To use Alioth.debian.org -* Create an account login -* Update your ~/.ssh/config file to add: -Host svn.debian.org git.debian.org bzr.debian.org hg.debian.org darcs.debian.org arch.debian.org + +# Note: alioth.debian.org is outdated --> https://alioth-archive.debian.org/ --> https://salsa.debian.org/public + * Create an account login + * Update your ~/.ssh/config file to add: + Host svn.debian.org git.debian.org bzr.debian.org hg.debian.org darcs.debian.org arch.debian.org User eldy-guest IdentityFile ~/.ssh/id_rsa -* Check login on page https://alioth.debian.org/users/login -Ex: https://alioth.debian.org/users/eldy-guest -* Setup your ssh as described into page: http://wiki.debian.org/Alioth/SSH -* Ask to be included into project collab-maint: http://alioth.debian.org/projects/collab-maint/ + * Check login on page https://alioth.debian.org/users/login + Ex: https://alioth.debian.org/users/eldy-guest + * Setup your ssh as described into page: http://wiki.debian.org/Alioth/SSH + * Ask to be included into project collab-maint: http://alioth.debian.org/projects/collab-maint/ @@ -82,7 +83,7 @@ Ex: https://alioth.debian.org/users/eldy-guest # dpkg -c package.deb List content of package # dpkg -I package.deb Give informations on package # dpkg -i package.deb Install a package -# dpkg-reconfigure -plow package Reconfigure package +# dpkg-reconfigure -plow package Reconfigure package # dpkg -L packagename List content of installed package # dpkg -r packagename Remove config files and interactive saved answers # dpkg -s packagename Give status of installed package @@ -90,7 +91,7 @@ Ex: https://alioth.debian.org/users/eldy-guest # # dpkg-buildpackage -us -uc Build a source and binary package # -# gdebi package.deb Install a package + dependencies +# gdebi package.deb Install a package + dependencies @@ -98,21 +99,21 @@ Ex: https://alioth.debian.org/users/eldy-guest - Post an ITP with reportbugs : > reportbug -B debian --email username@domain.tld wnpp -See page http://www.debian.org/devel/wnpp/#l1 for example of ITP requests contents. +See page https://www.debian.org/devel/wnpp/#l1 for example of ITP requests contents. - Wait until you received bug number. For first ITP submission of Dolibarr, bug id was 634783. - Check bug is into database by searching with id on - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634783 + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634783 - Add a line for upstream into file changelog with bug number - Call for a mentor on ML debian-mentors to upload packages - Once package is uploaded, following URL are available: -http://packages.qa.debian.org/package.html -http://bugs.debian.org/package +https://packages.qa.debian.org/package.html +https://bugs.debian.org/package ##### Modify severity of a bug ticket diff --git a/build/exe/doliwamp/config.inc.php.install b/build/exe/doliwamp/config.inc.php.install index 19a3d36a45e..6ad04752766 100644 --- a/build/exe/doliwamp/config.inc.php.install +++ b/build/exe/doliwamp/config.inc.php.install @@ -542,7 +542,7 @@ $cfg['ThemePerServer'] = FALSE; // allow diferent theme for each co * %f will be replaced by a list of field names. * (%t and %f only applies to DefaultQueryTable) */ -$cfg['DefaultQueryTable'] = 'SELECT * FROM %t WHERE 1'; +$cfg['DefaultQueryTable'] = 'SELECT * FROM %t WHERE 1 = 1'; $cfg['DefaultQueryDatabase'] = ''; /** diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index 63562f1f4f3..f5d9f64e518 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -157,8 +157,9 @@ $iterator1 = new RecursiveIteratorIterator($dir_iterator1); // Need to ignore document custom etc. Note: this also ignore natively symbolic links. $files = new RegexIterator($iterator1, '#^(?:[A-Z]:)?(?:/(?!(?:'.($includecustom?'':'custom\/|').'documents\/|conf\/|install\/))[^/]+)+/[^/]+\.(?:php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$#i'); */ -$regextoinclude='\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$'; -$regextoexclude='('.($includecustom?'':'custom|').'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs +// Define qualified files (must be same than into generate_filelist_xml.php and in api_setup.class.php) +$regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$'; +$regextoexclude = '('.($includecustom?'':'custom|').'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs $files = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir=''; diff --git a/build/phpstan/README b/build/phpstan/README new file mode 100644 index 00000000000..4ecde9baca5 --- /dev/null +++ b/build/phpstan/README @@ -0,0 +1,9 @@ +PHPStan + +https://phpstan.org + +PHPStan requires PHP >= 7.1 + +Install: composer require --dev phpstan/phpstan + +Config File: phpstan.neon diff --git a/build/rpm/README b/build/rpm/README index 99f871e882a..ab7be252ccb 100644 --- a/build/rpm/README +++ b/build/rpm/README @@ -3,48 +3,54 @@ README (English) RPM Package tools ################################################## -This directory contains files used by makepack-dolibarr.pl -script to build a package, ready to be distributed, -with format RPM (for Redhat, OpenSuse, Mandriva, ...). +This directory contains files used by makepack-dolibarr.pl script to build a package, +ready to be distributed with format RPM (https://rpm.org) +for Linux Distributions like Redhat, Fedora, CentOS, OpenSuse, OpenMandriva, Mageia ... # This is standard command to work on RPM packaging: -# + # To install all packagers tools: -# Fedora: yum -y install rpmlint fedora-packager mock koji hunspell-en hunspell-es hunspell-fr hunspell-it -# OpenSuse: yast --install update-desktop-files -# + - Fedora: yum -y install rpmlint fedora-packager mock koji hunspell-en hunspell-es hunspell-fr hunspell-it + - OpenSuse: yast --install update-desktop-files + # rpmlint file.rpm Test a package # mock -r fedora-15-i386 --rebuild ../SRPMS/hello-2.7-1.fc15.src.rpm -# + + # On Fedora -# rpm -i --test dolibarr-...rpm To list dependencies of RPM -# yum -v install dolibarr-...rpm To install package and dependencies -# yum -v erase dolibarr To remove package -# chcon -R -h -t httpd_sys_script_rw_t /file To add temporary context rw for httpd on /file -# semanage fcontext -a -t httpd_sys_script_rw_t "/dir/(.*)?" To add persistent context rw for httpd on /dir (this add file_contexts.local) -# restorecon -R -v /file Restore values into files (cancel chcon, validate semanage) -# +# ========= +# rpm -i --test dolibarr-...rpm to list dependencies of RPM +# yum -v install dolibarr-...rpm to install package and dependencies +# yum -v erase dolibarr to remove package +# chcon -R -h -t httpd_sys_script_rw_t /file to add temporary context rw for httpd on /file +# restorecon -R -v /file to restore values into files (cancel chcon, validate semanage) +# semanage fcontext -a -t httpd_sys_script_rw_t "/dir/(.*)?" to add persistent context rw for httpd on /dir (this add file_contexts.local) + + # On OpenSuse -# zypper install dolibarr-...rpm To install package and dependencies -# zypper remove dolibarr To remove package -# zypper search xxx To search a package -# +# =========== +# zypper install dolibarr-...rpm to install package and dependencies +# zypper remove dolibarr to remove package +# zypper search xxx to search a package + + # On Mageia (after su - root) -# urpmi dolibarr-...rpm To install package and dependencies -# urpme dolibarr To remove package +# =========================== +# urpmi dolibarr-...rpm to install package and dependencies +# urpme dolibarr to remove package # -# More on rpm on page http://www.trustonme.net/didactels/273.html To submit a package to Fedora: -- Create account on bugzilla.redhat.com -- Create account on fedoraproject.org -- Create SRPMS package. -- Upload package onf http://fedorapeople.org -- Create a bug with form https://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Fedora&format=fedora-review +- Create account on https://bugzilla.redhat.com +- Create account on https://developer.fedoraproject.org/ +- Create SRPMS package +- Upload package on https://fedorapeople.org +- Create a bug with form https://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Fedora&format=fedora-review + This is example of content of review field (used for Bug 723326 - https://bugzilla.redhat.com/show_bug.cgi?id=723326): -SRPMS URL: http://www.dolibarr.org/files/fedora/dolibarr-x.y.z-xxx.src.rpm +SRPMS URL: https://www.dolibarr.org/files/fedora/dolibarr-x.y.z-xxx.src.rpm Description: Dolibarr ERP & CRM is an easy to use open source/free software for small and medium companies, foundations or freelances. It includes different features for Enterprise Resource Planning (ERP) and Customer @@ -56,4 +62,4 @@ is my first package to maintain myself. So i'm seeking a sponsor. - Install fedora packager tools: yum install fedora-packager - Setup fedora packagers tools: fedora-packager-setup - Send your package: koji build --scratch f16 path_to_source_RPM -- Check if package is available: http://koji.fedoraproject.org/koji/ \ No newline at end of file +- Check if package is available: https://koji.fedoraproject.org/koji/ diff --git a/build/rpm/dolibarr_fedora.spec b/build/rpm/dolibarr_fedora.spec index d50c91d1f05..dc23cff5486 100755 --- a/build/rpm/dolibarr_fedora.spec +++ b/build/rpm/dolibarr_fedora.spec @@ -185,6 +185,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/don %_datadir/dolibarr/htdocs/ecm %_datadir/dolibarr/htdocs/emailcollector +%_datadir/dolibarr/htdocs/eventorganization %_datadir/dolibarr/htdocs/expedition %_datadir/dolibarr/htdocs/expensereport %_datadir/dolibarr/htdocs/exports @@ -198,6 +199,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/includes %_datadir/dolibarr/htdocs/install %_datadir/dolibarr/htdocs/intracommreport +%_datadir/dolibarr/htdocs/knowledgemanagement %_datadir/dolibarr/htdocs/langs/HOWTO-Translation.txt %_datadir/dolibarr/htdocs/loan %_datadir/dolibarr/htdocs/mailmanspip @@ -206,6 +208,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/mrp %_datadir/dolibarr/htdocs/multicurrency %_datadir/dolibarr/htdocs/opensurvey +%_datadir/dolibarr/htdocs/partnership %_datadir/dolibarr/htdocs/paybox %_datadir/dolibarr/htdocs/paypal %_datadir/dolibarr/htdocs/printing @@ -227,6 +230,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices %_datadir/dolibarr/htdocs/website +%_datadir/dolibarr/htdocs/workstation %_datadir/dolibarr/htdocs/zapier %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch diff --git a/build/rpm/dolibarr_generic.spec b/build/rpm/dolibarr_generic.spec index 4541868a04f..a446a7bd5d6 100755 --- a/build/rpm/dolibarr_generic.spec +++ b/build/rpm/dolibarr_generic.spec @@ -67,7 +67,8 @@ Requires: httpd, php >= 5.3.0, php-cli, php-gd, php-ldap, php-imap, php-mbstring Requires: mysql-server, mysql Requires: php-mysqli >= 4.1.0 %endif -%endif +%endif%_datadir/dolibarr/htdocs/eventorganization + %endif # Set yes to build test package, no for release (this disable need of /usr/bin/php not found by OpenSuse) @@ -265,6 +266,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/don %_datadir/dolibarr/htdocs/ecm %_datadir/dolibarr/htdocs/emailcollector +%_datadir/dolibarr/htdocs/eventorganization %_datadir/dolibarr/htdocs/expedition %_datadir/dolibarr/htdocs/expensereport %_datadir/dolibarr/htdocs/exports @@ -278,6 +280,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/includes %_datadir/dolibarr/htdocs/install %_datadir/dolibarr/htdocs/intracommreport +%_datadir/dolibarr/htdocs/knowledgemanagement %_datadir/dolibarr/htdocs/langs/HOWTO-Translation.txt %_datadir/dolibarr/htdocs/loan %_datadir/dolibarr/htdocs/mailmanspip @@ -286,6 +289,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/mrp %_datadir/dolibarr/htdocs/multicurrency %_datadir/dolibarr/htdocs/opensurvey +%_datadir/dolibarr/htdocs/partnership %_datadir/dolibarr/htdocs/paybox %_datadir/dolibarr/htdocs/paypal %_datadir/dolibarr/htdocs/printing @@ -307,6 +311,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices %_datadir/dolibarr/htdocs/website +%_datadir/dolibarr/htdocs/workstation %_datadir/dolibarr/htdocs/zapier %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch diff --git a/build/rpm/dolibarr_mandriva.spec b/build/rpm/dolibarr_mandriva.spec index d618b5729d5..78d90080258 100755 --- a/build/rpm/dolibarr_mandriva.spec +++ b/build/rpm/dolibarr_mandriva.spec @@ -182,6 +182,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/don %_datadir/dolibarr/htdocs/ecm %_datadir/dolibarr/htdocs/emailcollector +%_datadir/dolibarr/htdocs/eventorganization %_datadir/dolibarr/htdocs/expedition %_datadir/dolibarr/htdocs/expensereport %_datadir/dolibarr/htdocs/exports @@ -195,6 +196,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/includes %_datadir/dolibarr/htdocs/install %_datadir/dolibarr/htdocs/intracommreport +%_datadir/dolibarr/htdocs/knowledgemanagement %_datadir/dolibarr/htdocs/langs/HOWTO-Translation.txt %_datadir/dolibarr/htdocs/loan %_datadir/dolibarr/htdocs/mailmanspip @@ -203,6 +205,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/mrp %_datadir/dolibarr/htdocs/multicurrency %_datadir/dolibarr/htdocs/opensurvey +%_datadir/dolibarr/htdocs/partnership %_datadir/dolibarr/htdocs/paybox %_datadir/dolibarr/htdocs/paypal %_datadir/dolibarr/htdocs/printing @@ -224,6 +227,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices %_datadir/dolibarr/htdocs/website +%_datadir/dolibarr/htdocs/workstation %_datadir/dolibarr/htdocs/zapier %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch diff --git a/build/rpm/dolibarr_opensuse.spec b/build/rpm/dolibarr_opensuse.spec index 230a8946e99..edae0126653 100755 --- a/build/rpm/dolibarr_opensuse.spec +++ b/build/rpm/dolibarr_opensuse.spec @@ -193,6 +193,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/don %_datadir/dolibarr/htdocs/ecm %_datadir/dolibarr/htdocs/emailcollector +%_datadir/dolibarr/htdocs/eventorganization %_datadir/dolibarr/htdocs/expedition %_datadir/dolibarr/htdocs/expensereport %_datadir/dolibarr/htdocs/exports @@ -206,6 +207,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/includes %_datadir/dolibarr/htdocs/install %_datadir/dolibarr/htdocs/intracommreport +%_datadir/dolibarr/htdocs/knowledgemanagement %_datadir/dolibarr/htdocs/langs/HOWTO-Translation.txt %_datadir/dolibarr/htdocs/loan %_datadir/dolibarr/htdocs/mailmanspip @@ -214,6 +216,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/mrp %_datadir/dolibarr/htdocs/multicurrency %_datadir/dolibarr/htdocs/opensurvey +%_datadir/dolibarr/htdocs/partnership %_datadir/dolibarr/htdocs/paybox %_datadir/dolibarr/htdocs/paypal %_datadir/dolibarr/htdocs/printing @@ -235,6 +238,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices %_datadir/dolibarr/htdocs/website +%_datadir/dolibarr/htdocs/workstation %_datadir/dolibarr/htdocs/zapier %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index e207afa5658..4f80f06d444 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -225,9 +225,6 @@ JQUERYFILETREE: RESTLER: -------- -Change content of file htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html - -+With swagger 2: * Add line into Util.php to complete function @@ -248,6 +245,21 @@ Change content of file htdocs/includes/restler/framework/Luracast/Restler/explor // @CHANGE LDR if (!is_string($haystack)) return false; +* Replace + + $loaders = array_unique(static::$rogueLoaders); + + with + + $loaders = array_unique(static::$rogueLoaders, SORT_REGULAR); + + ++With swagger 2 provided into /explorer: +---------------------------------------- + +Change content of file htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html + + PARSEDOWN --------- diff --git a/dev/examples/zapier/creates/contact.js b/dev/examples/zapier/creates/contact.js new file mode 100644 index 00000000000..bcb849ad63d --- /dev/null +++ b/dev/examples/zapier/creates/contact.js @@ -0,0 +1,74 @@ +/*jshint esversion: 6 */ +// create a particular contact by name +const createContact = async (z, bundle) => { + const apiurl = bundle.authData.url + '/api/index.php/contacts'; + + const response = await z.request({ + method: 'POST', + url: apiurl, + body: { + name: bundle.inputData.name, + name_alias: bundle.inputData.name_alias, + ref_ext: bundle.inputData.ref_ext, + ref_int: bundle.inputData.ref_int, + address: bundle.inputData.address, + zip: bundle.inputData.zip, + town: bundle.inputData.town, + country_code: bundle.inputData.country_code, + country_id: bundle.inputData.country_id, + country: bundle.inputData.country, + phone: bundle.inputData.phone, + email: bundle.inputData.email, + sens: 'fromzapier' + } + }); + const result = z.JSON.parse(response.content); + // api returns an integer when ok, a json when ko + return result.response || {id: response}; +}; + +module.exports = { + key: 'contact', + noun: 'Contact', + + display: { + label: 'Create Contact', + description: 'Creates a contact.' + }, + + operation: { + inputFields: [ + {key: 'name', required: true}, + {key: 'name_alias', required: false}, + {key: 'address', required: false}, + {key: 'zip', required: false}, + {key: 'town', required: false}, + {key: 'email', required: false} + ], + perform: createContact, + + sample: { + id: 1, + name: 'DUPOND', + name_alias: 'DUPOND Ltd', + address: 'Rue des Canaries', + zip: '34090', + town: 'MONTPELLIER', + phone: '0123456789', + fax: '2345678901', + email: 'robot@domain.com' + }, + + outputFields: [ + {key: 'id', type: "integer", label: 'ID'}, + {key: 'name', label: 'Name'}, + {key: 'name_alias', label: 'Name alias'}, + {key: 'address', label: 'Address'}, + {key: 'zip', label: 'Zip'}, + {key: 'town', label: 'Town'}, + {key: 'phone', label: 'Phone'}, + {key: 'fax', label: 'Fax'}, + {key: 'email', label: 'Email'} + ] + } +}; diff --git a/dev/examples/zapier/creates/member.js b/dev/examples/zapier/creates/member.js new file mode 100644 index 00000000000..152f1129e79 --- /dev/null +++ b/dev/examples/zapier/creates/member.js @@ -0,0 +1,74 @@ +/*jshint esversion: 6 */ +// create a particular member by name +const createMember = async (z, bundle) => { + const apiurl = bundle.authData.url + '/api/index.php/members'; + + const response = await z.request({ + method: 'POST', + url: apiurl, + body: { + name: bundle.inputData.name, + name_alias: bundle.inputData.name_alias, + ref_ext: bundle.inputData.ref_ext, + ref_int: bundle.inputData.ref_int, + address: bundle.inputData.address, + zip: bundle.inputData.zip, + town: bundle.inputData.town, + country_code: bundle.inputData.country_code, + country_id: bundle.inputData.country_id, + country: bundle.inputData.country, + phone: bundle.inputData.phone, + email: bundle.inputData.email, + sens: 'fromzapier' + } + }); + const result = z.JSON.parse(response.content); + // api returns an integer when ok, a json when ko + return result.response || {id: response}; +}; + +module.exports = { + key: 'member', + noun: 'Member', + + display: { + label: 'Create Member', + description: 'Creates a member.' + }, + + operation: { + inputFields: [ + {key: 'name', required: true}, + {key: 'name_alias', required: false}, + {key: 'address', required: false}, + {key: 'zip', required: false}, + {key: 'town', required: false}, + {key: 'email', required: false} + ], + perform: createMember, + + sample: { + id: 1, + name: 'DUPOND', + name_alias: 'DUPOND Ltd', + address: 'Rue des Canaries', + zip: '34090', + town: 'MONTPELLIER', + phone: '0123456789', + fax: '2345678901', + email: 'robot@domain.com' + }, + + outputFields: [ + {key: 'id', type: "integer", label: 'ID'}, + {key: 'name', label: 'Name'}, + {key: 'name_alias', label: 'Name alias'}, + {key: 'address', label: 'Address'}, + {key: 'zip', label: 'Zip'}, + {key: 'town', label: 'Town'}, + {key: 'phone', label: 'Phone'}, + {key: 'fax', label: 'Fax'}, + {key: 'email', label: 'Email'} + ] + } +}; diff --git a/dev/examples/zapier/creates/thirdparty.js b/dev/examples/zapier/creates/thirdparty.js index 3e20fd10e41..2abeef6ae4c 100644 --- a/dev/examples/zapier/creates/thirdparty.js +++ b/dev/examples/zapier/creates/thirdparty.js @@ -6,7 +6,7 @@ const createThirdparty = async (z, bundle) => { const response = await z.request({ method: 'POST', url: apiurl, - body: JSON.stringify({ + body: { name: bundle.inputData.name, name_alias: bundle.inputData.name_alias, ref_ext: bundle.inputData.ref_ext, @@ -24,7 +24,7 @@ const createThirdparty = async (z, bundle) => { code_client: bundle.inputData.code_client, code_fournisseur: bundle.inputData.code_fournisseur, sens: 'fromzapier' - }) + } }); const result = z.JSON.parse(response.content); // api returns an integer when ok, a json when ko diff --git a/dev/examples/zapier/index.js b/dev/examples/zapier/index.js index d1897673b39..fdd1ed29a53 100644 --- a/dev/examples/zapier/index.js +++ b/dev/examples/zapier/index.js @@ -2,12 +2,18 @@ const triggerAction = require('./triggers/action'); const triggerOrder = require('./triggers/order'); const triggerThirdparty = require('./triggers/thirdparty'); +const triggerContact = require('./triggers/contact'); const triggerTicket = require('./triggers/ticket'); const triggerUser = require('./triggers/user'); +const triggerMember = require('./triggers/member'); const searchThirdparty = require('./searches/thirdparty'); +const searchContact = require('./searches/contact'); +const searchMember = require('./searches/member'); const createThirdparty = require('./creates/thirdparty'); +const createContact = require('./creates/contact'); +const createMember = require('./creates/member'); const { config: authentication, @@ -62,18 +68,24 @@ const App = { [triggerAction.key]: triggerAction, [triggerOrder.key]: triggerOrder, [triggerThirdparty.key]: triggerThirdparty, + [triggerContact.key]: triggerContact, [triggerTicket.key]: triggerTicket, [triggerUser.key]: triggerUser, + [triggerMember.key]: triggerMember, }, // If you want your searches to show up, you better include it here! searches: { [searchThirdparty.key]: searchThirdparty, + [searchContact.key]: searchContact, + [searchMember.key]: searchMember, }, // If you want your creates to show up, you better include it here! creates: { [createThirdparty.key]: createThirdparty, + [createContact.key]: createContact, + [createMember.key]: createMember, } }; diff --git a/dev/examples/zapier/package.json b/dev/examples/zapier/package.json index 4266a6f00b1..a9d519dec69 100644 --- a/dev/examples/zapier/package.json +++ b/dev/examples/zapier/package.json @@ -1,6 +1,6 @@ { "name": "dolibarr", - "version": "1.13.0", + "version": "1.14.0", "description": "An app for connecting Dolibarr to the Zapier platform.", "repository": "Dolibarr/dolibarr", "homepage": "https://www.dolibarr.org/", @@ -11,11 +11,11 @@ "test": "mocha --recursive" }, "engines": { - "node": "8.10.0", + "node": "14.0.0", "npm": ">=5.6.0" }, "dependencies": { - "zapier-platform-core": "10.1.2" + "zapier-platform-core": "11.0.1" }, "devDependencies": { "mocha": "^5.2.0", diff --git a/dev/examples/zapier/searches/contact.js b/dev/examples/zapier/searches/contact.js new file mode 100644 index 00000000000..b52b8d3e367 --- /dev/null +++ b/dev/examples/zapier/searches/contact.js @@ -0,0 +1,95 @@ +module.exports = { + key: 'contact', + + // You'll want to provide some helpful display labels and descriptions + // for users. Zapier will put them into the UX. + noun: 'Contact', + display: { + label: 'Find a Contact', + description: 'Search for contact.' + }, + + // `operation` is where we make the call to your API to do the search + operation: { + // This search only has one search field. Your searches might have just one, or many + // search fields. + inputFields: [ + { + key: 'lastname', + type: 'string', + label: 'Lastname', + helpText: 'Lastname to limit to the search to (i.e. The company or %company%).' + }, + { + key: 'email', + type: 'string', + label: 'Email', + helpText: 'Email to limit to the search to.' + } + ], + + perform: async (z, bundle) => { + const url = bundle.authData.url + '/api/index.php/contacts/'; + + // Put the search value in a query param. The details of how to build + // a search URL will depend on how your API works. + let filter = ''; + if (bundle.inputData.lastname) { + filter = "t.lastname like \'%"+bundle.inputData.name+"%\'"; + } + if (bundle.inputData.email) { + if (bundle.inputData.lastname) { + filter += " and "; + } + filter += "t.email like \'"+bundle.inputData.email+"\'"; + } + const response = await z.request({ + url: url, + // this parameter avoid throwing errors and let us manage them + skipThrowForStatus: true, + params: { + sqlfilters: filter + } + }); + //z.console.log(response); + if (response.status != 200) { + return []; + } + return response.json; + }, + + // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example + // from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of + // returned records, and have obviously dummy values that we can show to any user. + sample: { + id: 1, + createdAt: 1472069465, + name: 'DOE', + firstname: 'John', + authorId: 1, + directions: '1. Boil Noodles\n2.Serve with sauce', + style: 'italian' + }, + + // If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom + // field definitions. The result will be used to augment the sample. + // outputFields: () => { return []; } + // Alternatively, a static field definition should be provided, to specify labels for the fields + outputFields: [ + { + key: 'id', + type: "integer", + label: 'ID' + }, + {key: 'createdAt', type: "integer", label: 'Created At'}, + {key: 'name', label: 'Name'}, + {key: 'firstname', label: 'Firstname'}, + {key: 'directions', label: 'Directions'}, + {key: 'authorId', type: "integer", label: 'Author ID'}, + { + key: 'style', + label: 'Style' + } + ] + } +}; diff --git a/dev/examples/zapier/searches/member.js b/dev/examples/zapier/searches/member.js new file mode 100644 index 00000000000..f1a84061146 --- /dev/null +++ b/dev/examples/zapier/searches/member.js @@ -0,0 +1,88 @@ +module.exports = { + key: 'member', + + // You'll want to provide some helpful display labels and descriptions + // for users. Zapier will put them into the UX. + noun: 'Member', + display: { + label: 'Find a Member', + description: 'Search for member.' + }, + + // `operation` is where we make the call to your API to do the search + operation: { + // This search only has one search field. Your searches might have just one, or many + // search fields. + inputFields: [ + { + key: 'lastname', + type: 'string', + label: 'Lastname', + helpText: 'Lastname to limit to the search to (i.e. The company or %company%).' + }, + { + key: 'email', + type: 'string', + label: 'Email', + helpText: 'Email to limit to the search to.' + } + ], + + perform: async (z, bundle) => { + const url = bundle.authData.url + '/api/index.php/members/'; + + // Put the search value in a query param. The details of how to build + // a search URL will depend on how your API works. + let filter = ''; + if (bundle.inputData.lastname) { + filter = "t.lastname like \'%" + bundle.inputData.name + "%\'"; + } + if (bundle.inputData.email) { + if (bundle.inputData.lastname) { + filter += " and "; + } + filter += "t.email like \'" + bundle.inputData.email + "\'"; + } + const response = await z.request({ + url: url, + // this parameter avoid throwing errors and let us manage them + skipThrowForStatus: true, + params: { + sqlfilters: filter + } + }); + //z.console.log(response); + if (response.status != 200) { + return []; + } + return response.json; + }, + + // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example + // from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of + // returned records, and have obviously dummy values that we can show to any user. + sample: { + id: 1, + createdAt: 1472069465, + name: 'DOE', + firstname: 'John', + authorId: 1, + }, + + // If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom + // field definitions. The result will be used to augment the sample. + // outputFields: () => { return []; } + // Alternatively, a static field definition should be provided, to specify labels for the fields + outputFields: [ + { + key: 'id', + type: "integer", + label: 'ID' + }, + { key: 'createdAt', type: "integer", label: 'Created At' }, + { key: 'name', label: 'Name' }, + { key: 'firstname', label: 'Firstname' }, + { key: 'authorId', type: "integer", label: 'Author ID' }, + ] + } +}; diff --git a/dev/examples/zapier/searches/thirdparty.js b/dev/examples/zapier/searches/thirdparty.js index 8f72b9270e5..e1e6878f5b3 100644 --- a/dev/examples/zapier/searches/thirdparty.js +++ b/dev/examples/zapier/searches/thirdparty.js @@ -19,21 +19,43 @@ module.exports = { type: 'string', label: 'Name', helpText: 'Name to limit to the search to (i.e. The company or %company%).' + }, + { + key: 'email', + type: 'string', + label: 'Email', + helpText: 'Email to limit to the search to.' } ], - perform: (z, bundle) => { + perform: async (z, bundle) => { const url = bundle.authData.url + '/api/index.php/thirdparties/'; // Put the search value in a query param. The details of how to build // a search URL will depend on how your API works. - const options = { - params: { - sqlfilters: "t.nom like \'%"+bundle.inputData.name+"%\'" + let filter = ''; + if (bundle.inputData.name) { + filter = "t.nom like \'%"+bundle.inputData.name+"%\'"; + } + if (bundle.inputData.email) { + if (bundle.inputData.name) { + filter += " and "; } - }; - - return z.request(url, options).then(response => JSON.parse(response.content)); + filter += "t.email like \'"+bundle.inputData.email+"\'"; + } + const response = await z.request({ + url: url, + // this parameter avoid throwing errors and let us manage them + skipThrowForStatus: true, + params: { + sqlfilters: filter + } + }); + //z.console.log(response); + if (response.status != 200) { + return []; + } + return response.json; }, // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example diff --git a/dev/examples/zapier/triggers/contact.js b/dev/examples/zapier/triggers/contact.js new file mode 100644 index 00000000000..2ba3bd226f8 --- /dev/null +++ b/dev/examples/zapier/triggers/contact.js @@ -0,0 +1,171 @@ +const subscribeHook = (z, bundle) => { + // `z.console.log()` is similar to `console.log()`. + z.console.log('suscribing hook!'); + + // bundle.targetUrl has the Hook URL this app should call when an action is created. + const data = { + url: bundle.targetUrl, + event: bundle.event, + module: 'contact', + action: bundle.inputData.action + }; + + const url = bundle.authData.url + '/api/index.php/zapierapi/hook'; + + // You can build requests and our client will helpfully inject all the variables + // you need to complete. You can also register middleware to control this. + const options = { + url: url, + method: 'POST', + body: data, + }; + + // You may return a promise or a normal data structure from any perform method. + return z.request(options).then((response) => JSON.parse(response.content)); +}; + +const unsubscribeHook = (z, bundle) => { + // bundle.subscribeData contains the parsed response JSON from the subscribe + // request made initially. + z.console.log('unsuscribing hook!'); + + // You can build requests and our client will helpfully inject all the variables + // you need to complete. You can also register middleware to control this. + const options = { + url: bundle.authData.url + '/api/index.php/zapierapi/hook/' + bundle.subscribeData.id, + method: 'DELETE', + }; + + // You may return a promise or a normal data structure from any perform method. + return z.request(options).then((response) => JSON.parse(response.content)); +}; + +const getContact = (z, bundle) => { + // bundle.cleanedRequest will include the parsed JSON object (if it's not a + // test poll) and also a .querystring property with the URL's query string. + const contact = { + id: bundle.cleanedRequest.id, + name: bundle.cleanedRequest.name, + name_alias: bundle.cleanedRequest.name_alias, + firstname: bundle.cleanedRequest.firstname, + address: bundle.cleanedRequest.address, + zip: bundle.cleanedRequest.zip, + town: bundle.cleanedRequest.town, + email: bundle.cleanedRequest.email, + phone_pro: bundle.cleanedRequest.phone_pro, + phone_perso: bundle.cleanedRequest.phone_perso, + phone_mobile: bundle.cleanedRequest.phone_mobile, + authorId: bundle.cleanedRequest.authorId, + createdAt: bundle.cleanedRequest.createdAt, + action: bundle.cleanedRequest.action + }; + + return [contact]; +}; + +const getFallbackRealContact = (z, bundle) => { + // For the test poll, you should get some real data, to aid the setup process. + const module = bundle.inputData.module; + const options = { + url: bundle.authData.url + '/api/index.php/contacts/0', + }; + + return z.request(options).then((response) => [JSON.parse(response.content)]); +}; + +// const getModulesChoices = (z/*, bundle*/) => { +// // For the test poll, you should get some real data, to aid the setup process. +// const options = { +// url: bundle.authData.url + '/api/index.php/zapierapi/getmoduleschoices', +// }; + +// return z.request(options).then((response) => JSON.parse(response.content)); +// }; +// const getModulesChoices = () => { +// return { +// orders: "Order", +// invoices: "Invoice", +// contacts: "Contact", +// contacts: "Contacts" +// }; +// }; + +// const getActionsChoices = (z, bundle) => { +// // For the test poll, you should get some real data, to aid the setup process. +// const module = bundle.inputData.module; +// const options = { +// url: url: bundle.authData.url + '/api/index.php/zapierapi/getactionschoices/thirparty`, +// }; + +// return z.request(options).then((response) => JSON.parse(response.content)); +// }; + +// We recommend writing your triggers separate like this and rolling them +// into the App definition at the end. +module.exports = { + key: 'contact', + + // You'll want to provide some helpful display labels and descriptions + // for users. Zapier will put them into the UX. + noun: 'Contact', + display: { + label: 'New Contact', + description: 'Triggers when a new contact action is done in Dolibarr.' + }, + + // `operation` is where the business logic goes. + operation: { + + // `inputFields` can define the fields a user could provide, + // we'll pass them in as `bundle.inputData` later. + inputFields: [ + { + key: 'action', + required: true, + type: 'string', + helpText: 'Which action of contact this should trigger on.', + choices: { + create: "Create", + modify: "Modify", + validate: "Validate", + } + } + ], + + type: 'hook', + + performSubscribe: subscribeHook, + performUnsubscribe: unsubscribeHook, + + perform: getContact, + performList: getFallbackRealContact, + + // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example + // from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of + // returned records, and have obviously dummy values that we can show to any user. + sample: { + id: 1, + createdAt: 1472069465, + lastname: 'DOE', + firstname: 'John', + authorId: 1, + action: 'create' + }, + + // If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom + // field definitions. The result will be used to augment the sample. + // outputFields: () => { return []; } + // Alternatively, a static field definition should be provided, to specify labels for the fields + outputFields: [ + {key: 'id', type: "integer", label: 'ID'}, + {key: 'createdAt', label: 'Created At'}, + {key: 'lastname', label: 'Lastname'}, + {key: 'firstname', label: 'Firstname'}, + {key: 'phone', label: 'Phone pro'}, + {key: 'phone_perso', label: 'Phone perso'}, + {key: 'phone_mobile', label: 'Phone mobile'}, + {key: 'authorId', type: "integer", label: 'Author ID'}, + {key: 'action', label: 'Action'} + ] + } +}; diff --git a/dev/examples/zapier/triggers/member.js b/dev/examples/zapier/triggers/member.js new file mode 100644 index 00000000000..3385cdca625 --- /dev/null +++ b/dev/examples/zapier/triggers/member.js @@ -0,0 +1,171 @@ +const subscribeHook = (z, bundle) => { + // `z.console.log()` is similar to `console.log()`. + z.console.log('suscribing hook!'); + + // bundle.targetUrl has the Hook URL this app should call when an action is created. + const data = { + url: bundle.targetUrl, + event: bundle.event, + module: 'member', + action: bundle.inputData.action + }; + + const url = bundle.authData.url + '/api/index.php/zapierapi/hook'; + + // You can build requests and our client will helpfully inject all the variables + // you need to complete. You can also register middleware to control this. + const options = { + url: url, + method: 'POST', + body: data, + }; + + // You may return a promise or a normal data structure from any perform method. + return z.request(options).then((response) => JSON.parse(response.content)); +}; + +const unsubscribeHook = (z, bundle) => { + // bundle.subscribeData contains the parsed response JSON from the subscribe + // request made initially. + z.console.log('unsuscribing hook!'); + + // You can build requests and our client will helpfully inject all the variables + // you need to complete. You can also register middleware to control this. + const options = { + url: bundle.authData.url + '/api/index.php/zapierapi/hook/' + bundle.subscribeData.id, + method: 'DELETE', + }; + + // You may return a promise or a normal data structure from any perform method. + return z.request(options).then((response) => JSON.parse(response.content)); +}; + +const getMember = (z, bundle) => { + // bundle.cleanedRequest will include the parsed JSON object (if it's not a + // test poll) and also a .querystring property with the URL's query string. + const member = { + id: bundle.cleanedRequest.id, + name: bundle.cleanedRequest.name, + name_alias: bundle.cleanedRequest.name_alias, + firstname: bundle.cleanedRequest.firstname, + address: bundle.cleanedRequest.address, + zip: bundle.cleanedRequest.zip, + town: bundle.cleanedRequest.town, + email: bundle.cleanedRequest.email, + phone_pro: bundle.cleanedRequest.phone_pro, + phone_perso: bundle.cleanedRequest.phone_perso, + phone_mobile: bundle.cleanedRequest.phone_mobile, + authorId: bundle.cleanedRequest.authorId, + createdAt: bundle.cleanedRequest.createdAt, + action: bundle.cleanedRequest.action + }; + + return [member]; +}; + +const getFallbackRealMember = (z, bundle) => { + // For the test poll, you should get some real data, to aid the setup process. + const module = bundle.inputData.module; + const options = { + url: bundle.authData.url + '/api/index.php/members/0', + }; + + return z.request(options).then((response) => [JSON.parse(response.content)]); +}; + +// const getModulesChoices = (z/*, bundle*/) => { +// // For the test poll, you should get some real data, to aid the setup process. +// const options = { +// url: bundle.authData.url + '/api/index.php/zapierapi/getmoduleschoices', +// }; + +// return z.request(options).then((response) => JSON.parse(response.content)); +// }; +// const getModulesChoices = () => { +// return { +// orders: "Order", +// invoices: "Invoice", +// members: "Member", +// members: "Members" +// }; +// }; + +// const getActionsChoices = (z, bundle) => { +// // For the test poll, you should get some real data, to aid the setup process. +// const module = bundle.inputData.module; +// const options = { +// url: url: bundle.authData.url + '/api/index.php/zapierapi/getactionschoices/thirparty`, +// }; + +// return z.request(options).then((response) => JSON.parse(response.content)); +// }; + +// We recommend writing your triggers separate like this and rolling them +// into the App definition at the end. +module.exports = { + key: 'member', + + // You'll want to provide some helpful display labels and descriptions + // for users. Zapier will put them into the UX. + noun: 'Member', + display: { + label: 'New Member', + description: 'Triggers when a new member action is done in Dolibarr.' + }, + + // `operation` is where the business logic goes. + operation: { + + // `inputFields` can define the fields a user could provide, + // we'll pass them in as `bundle.inputData` later. + inputFields: [ + { + key: 'action', + required: true, + type: 'string', + helpText: 'Which action of member this should trigger on.', + choices: { + create: "Create", + modify: "Modify", + validate: "Validate", + } + } + ], + + type: 'hook', + + performSubscribe: subscribeHook, + performUnsubscribe: unsubscribeHook, + + perform: getMember, + performList: getFallbackRealMember, + + // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example + // from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of + // returned records, and have obviously dummy values that we can show to any user. + sample: { + id: 1, + createdAt: 1472069465, + lastname: 'DOE', + firstname: 'John', + authorId: 1, + action: 'create' + }, + + // If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom + // field definitions. The result will be used to augment the sample. + // outputFields: () => { return []; } + // Alternatively, a static field definition should be provided, to specify labels for the fields + outputFields: [ + {key: 'id', type: "integer", label: 'ID'}, + {key: 'createdAt', label: 'Created At'}, + {key: 'lastname', label: 'Lastname'}, + {key: 'firstname', label: 'Firstname'}, + {key: 'phone', label: 'Phone pro'}, + {key: 'phone_perso', label: 'Phone perso'}, + {key: 'phone_mobile', label: 'Phone mobile'}, + {key: 'authorId', type: "integer", label: 'Author ID'}, + {key: 'action', label: 'Action'} + ] + } +}; diff --git a/dev/examples/zapier/triggers/thirdparty.js b/dev/examples/zapier/triggers/thirdparty.js index 4656f836e74..76194acbc9a 100644 --- a/dev/examples/zapier/triggers/thirdparty.js +++ b/dev/examples/zapier/triggers/thirdparty.js @@ -56,6 +56,12 @@ const getThirdparty = (z, bundle) => { fournisseur: bundle.cleanedRequest.fournisseur, code_client: bundle.cleanedRequest.code_client, code_fournisseur: bundle.cleanedRequest.code_fournisseur, + idprof1: bundle.cleanedRequest.idprof1, + idprof2: bundle.cleanedRequest.idprof2, + idprof3: bundle.cleanedRequest.idprof3, + idprof4: bundle.cleanedRequest.idprof4, + idprof5: bundle.cleanedRequest.idprof5, + idprof6: bundle.cleanedRequest.idprof6, authorId: bundle.cleanedRequest.authorId, createdAt: bundle.cleanedRequest.createdAt, action: bundle.cleanedRequest.action @@ -112,7 +118,7 @@ module.exports = { noun: 'Thirdparty', display: { label: 'New Thirdparty', - description: 'Triggers when a new thirdpaty action is done in Dolibarr.' + description: 'Triggers when a new thirdparty action is done in Dolibarr.' }, // `operation` is where the business logic goes. @@ -170,7 +176,13 @@ module.exports = { {key: 'client', label: 'Customer/Prospect 0/1/2/3'}, {key: 'fournisseur', label: 'Supplier 0/1'}, {key: 'code_client', label: 'Customer code'}, - {key: 'code_fournisseur', label: 'Supplier code'} + {key: 'code_fournisseur', label: 'Supplier code'}, + {key: 'idprof1', label: 'Id Prof 1'}, + {key: 'idprof2', label: 'Id Prof 2'}, + {key: 'idprof3', label: 'Id Prof 3'}, + {key: 'idprof4', label: 'Id Prof 4'}, + {key: 'idprof5', label: 'Id Prof 5'}, + {key: 'idprof6', label: 'Id Prof 6'} ] } }; diff --git a/dev/initdemo/.gitignore b/dev/initdemo/.gitignore new file mode 100644 index 00000000000..1204e1426c6 --- /dev/null +++ b/dev/initdemo/.gitignore @@ -0,0 +1 @@ +/initdemopostsql.sql diff --git a/dev/initdemo/initdemo.sh b/dev/initdemo/initdemo.sh index ccd8c8d8b9a..258eeaf646a 100755 --- a/dev/initdemo/initdemo.sh +++ b/dev/initdemo/initdemo.sh @@ -232,6 +232,10 @@ else fi +if [ -s "$mydir/initdemopostsql.sql" ]; then + mysql -P$port $base < "$mydir/initdemopostsql.sql" +fi + if [ "x$res" = "x0" ] then diff --git a/dev/initdemo/initdemopassword.sh b/dev/initdemo/initdemopassword.sh index d3527151c64..933c3b1afa2 100755 --- a/dev/initdemo/initdemopassword.sh +++ b/dev/initdemo/initdemopassword.sh @@ -39,7 +39,7 @@ if [ "x$confirm" != "xconfirm" ] then echo "----- $0 -----" echo "Usage: initdemopassword.sh confirm [base port login pass password_hash_algo]" - echo "password_hash_algo can be md5 of password_hash" + echo "password_hash_algo can be md5 or password_hash" exit fi @@ -149,15 +149,19 @@ then fi #echo "mysql -P$port -u$admin $passwd $base < $mydir/$dumpfile" #mysql -P$port -u$admin $passwd $base < $mydir/$dumpfile -echo "echo \"UPDATE llx_user SET pass_crypted = MD5('$demopass') WHERE login = '$demologin';\" | mysql -P$port $base" -if [ "x$demopasshash" != "xpassword_hash" ] +if [ "x${demopasshash}" != "xpassword_hash" ] then - newpass=`echo '' | php` + echo '' > /tmp/tmp.php + newpass=`php -f /tmp/tmp.php` + rm /tmp/tmp.php else - newpass=`echo '' | php` + echo '' > /tmp/tmp.php + newpass=`php -f /tmp/tmp.php` + rm /tmp/tmp.php fi +echo "echo \"UPDATE llx_user SET pass_crypted = '$newpass' WHERE login = '$demologin';\" | mysql -P$port $base" echo "UPDATE llx_user SET pass_crypted = '$newpass' WHERE login = '$demologin';" | mysql -P$port $base export res=$? @@ -166,6 +170,10 @@ if [ $res -ne 0 ]; then exit fi +if [ -s "$mydir/initdemopostsql.sql" ]; then + mysql -P$port $base < "$mydir/initdemopostsql.sql" +fi + if [ "x$res" = "x0" ] then diff --git a/dev/initdemo/mysqldump_dolibarr_3.5.0.sql b/dev/initdemo/mysqldump_dolibarr_3.5.0.sql index 46053d1a187..252643afb59 100644 --- a/dev/initdemo/mysqldump_dolibarr_3.5.0.sql +++ b/dev/initdemo/mysqldump_dolibarr_3.5.0.sql @@ -5503,7 +5503,7 @@ CREATE TABLE `llx_product` ( LOCK TABLES `llx_product` WRITE; /*!40000 ALTER TABLE `llx_product` DISABLE KEYS */; -INSERT INTO `llx_product` VALUES (1,'2010-07-08 14:33:17','2013-03-12 09:30:24',0,0,'PIDRESS',1,NULL,'Pink dress','A beatifull pink dress','',NULL,NULL,100.00000000,112.50000000,90.00000000,101.25000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',20,NULL,0,'','',NULL,100,0,NULL,0,NULL,0,NULL,0,2,0.00000000,NULL,1,0,NULL,0),(2,'2010-07-09 00:30:01','2013-01-19 17:31:58',0,0,'Product_P1',1,NULL,'Product P1','','','',32,0.00000000,0.00000000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,998,0.00000000,NULL,0,0,NULL,0),(3,'2010-07-09 00:30:25','2012-12-08 13:11:14',0,0,'Service_S1',1,NULL,'Service S1','','',NULL,NULL,0.00000000,0.00000000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,1,'1m',NULL,NULL,0,'','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00000000,NULL,0,0,NULL,0),(4,'2010-07-10 14:44:06','2013-01-19 17:22:48',0,0,'DECAP',1,NULL,'Decapsuleur','','',NULL,NULL,5.00000000,5.62500000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,2,-3,NULL,0,NULL,0,NULL,0,1001,10.00000000,NULL,1,0,NULL,0),(5,'2011-07-20 23:11:38','2011-07-27 17:02:59',0,0,'aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(6,'2011-07-29 22:16:44','2011-07-29 20:16:44',0,0,'Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(7,'2011-07-29 22:31:21','2011-07-29 20:31:21',0,0,'Copy_of_Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,0,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(8,'2011-07-29 22:46:54','2011-07-29 20:46:54',0,0,'Copy_of_Copy_of_Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,0,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(10,'2008-12-31 00:00:00','2012-12-08 13:11:14',0,0,'PR123456',1,NULL,'My product','This is a description example for record','Some note',NULL,NULL,100.00000000,110.00000000,0.00000000,0.00000000,'HT',10.000,0,0.000,0.000,NULL,0,0,0,'1y',0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00000000,NULL,NULL,0,'20110729232310',0),(11,'2013-01-13 20:24:42','2013-01-19 17:22:48',0,0,'gh',1,NULL,'hfghf','','','',NULL,0.00000000,0.00000000,0.00000000,0.00000000,'HT',0.000,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,-1,0.00000000,'',1,0,NULL,0); +INSERT INTO `llx_product` VALUES (1,'2010-07-08 14:33:17','2013-03-12 09:30:24',0,0,'PINKDRESS',1,NULL,'Pink dress','A beatifull pink dress','',NULL,NULL,100.00000000,112.50000000,90.00000000,101.25000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',20,NULL,0,'','',NULL,100,0,NULL,0,NULL,0,NULL,0,2,0.00000000,NULL,1,0,NULL,0),(2,'2010-07-09 00:30:01','2013-01-19 17:31:58',0,0,'Product_P1',1,NULL,'Product P1','','','',32,0.00000000,0.00000000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,998,0.00000000,NULL,0,0,NULL,0),(3,'2010-07-09 00:30:25','2012-12-08 13:11:14',0,0,'Service_S1',1,NULL,'Service S1','','',NULL,NULL,0.00000000,0.00000000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,1,'1m',NULL,NULL,0,'','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00000000,NULL,0,0,NULL,0),(4,'2010-07-10 14:44:06','2013-01-19 17:22:48',0,0,'DECAP',1,NULL,'Decapsuleur','','',NULL,NULL,5.00000000,5.62500000,0.00000000,0.00000000,'HT',12.500,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,2,-3,NULL,0,NULL,0,NULL,0,1001,10.00000000,NULL,1,0,NULL,0),(5,'2011-07-20 23:11:38','2011-07-27 17:02:59',0,0,'aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(6,'2011-07-29 22:16:44','2011-07-29 20:16:44',0,0,'Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(7,'2011-07-29 22:31:21','2011-07-29 20:31:21',0,0,'Copy_of_Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,0,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(8,'2011-07-29 22:46:54','2011-07-29 20:46:54',0,0,'Copy_of_Copy_of_Copy_of_aaaa',1,NULL,'aaaa','cccc','bbbb','',NULL,10.00000000,11.96000000,0.00000000,0.00000000,'HT',19.600,0,0.000,0.000,1,0,0,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0.00000000,'',1,0,NULL,0),(10,'2008-12-31 00:00:00','2012-12-08 13:11:14',0,0,'PR123456',1,NULL,'My product','This is a description example for record','Some note',NULL,NULL,100.00000000,110.00000000,0.00000000,0.00000000,'HT',10.000,0,0.000,0.000,NULL,0,0,0,'1y',0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00000000,NULL,NULL,0,'20110729232310',0),(11,'2013-01-13 20:24:42','2013-01-19 17:22:48',0,0,'gh',1,NULL,'hfghf','','','',NULL,0.00000000,0.00000000,0.00000000,0.00000000,'HT',0.000,0,0.000,0.000,1,1,1,0,'',NULL,NULL,0,'','',NULL,NULL,0,NULL,0,NULL,0,NULL,0,-1,0.00000000,'',1,0,NULL,0); /*!40000 ALTER TABLE `llx_product` ENABLE KEYS */; UNLOCK TABLES; diff --git a/dev/resources/iso-normes/EORI.txt b/dev/resources/iso-normes/EORI.txt new file mode 100644 index 00000000000..13ff095c693 --- /dev/null +++ b/dev/resources/iso-normes/EORI.txt @@ -0,0 +1,6 @@ +EORI + +https://en.wikipedia.org/wiki/EORI_number + +in Dolibarr avaiable since v13 +- it is set to field 'profid5' diff --git a/dev/resources/iso-normes/address_format.txt b/dev/resources/iso-normes/address_format.txt index cc3b23285c8..d87e90e79b5 100644 --- a/dev/resources/iso-normes/address_format.txt +++ b/dev/resources/iso-normes/address_format.txt @@ -1 +1,4 @@ -http://bitboost.com/ref/international-address-formats.html#Formats \ No newline at end of file +https://bitboost.com/ref/international-address-formats.html#Formats + +https://www.upu.int/en/Postal-Solutions/Programmes-Services/Addressing-Solutions + diff --git a/dev/resources/iso-normes/code_nace.txt b/dev/resources/iso-normes/code_nace.txt index 0c490bd4bf1..a07e3a76b31 100644 --- a/dev/resources/iso-normes/code_nace.txt +++ b/dev/resources/iso-normes/code_nace.txt @@ -1 +1,5 @@ -http://ec.europa.eu/eurostat/ramon/nomenclatures/index.cfm?TargetUrl=LST_CLS_DLD&StrNom=NACE_REV2&StrLanguageCode=FR&StrLayoutCode=# \ No newline at end of file +NACE + +https://ec.europa.eu/eurostat/ramon/nomenclatures/index.cfm?TargetUrl=LST_CLS_DLD&StrNom=NACE_REV2&StrLanguageCode=EN&StrLayoutCode= + +https://en.wikipedia.org/wiki/Statistical_Classification_of_Economic_Activities_in_the_European_Community diff --git a/dev/resources/iso-normes/countries_iso-3166_en.txt b/dev/resources/iso-normes/countries_iso-3166_en.txt index b953435d1c9..d6624026963 100644 --- a/dev/resources/iso-normes/countries_iso-3166_en.txt +++ b/dev/resources/iso-normes/countries_iso-3166_en.txt @@ -3,11 +3,12 @@ # The list is updated whenever a change to the official code list in ISO 3166-1 is effected by the ISO 3166/MA. # It lists 240 official short names and code elements. One line of text contains one entry. # A country name and its code element are separated by a semicolon (;). -# http://www.iso.org/iso/fr/iso3166_en_code_lists.txt +# https://www.iso.org/iso-3166-country-codes.html -# ISO-3166: http://en.wikipedia.org/wiki/ISO_3166-1 -# ISO-3166 alpha 2: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 -# ISO-3166 alpha 3: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 +# https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes +# ISO-3166: https://en.wikipedia.org/wiki/ISO_3166-1 +# ISO-3166 alpha 2: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 +# ISO-3166 alpha 3: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 AFGHANISTAN;AF ÅLAND ISLANDS;AX @@ -254,4 +255,4 @@ WALLIS AND FUTUNA;WF WESTERN SAHARA;EH YEMEN;YE ZAMBIA;ZM -ZIMBABWE;ZW \ No newline at end of file +ZIMBABWE;ZW diff --git a/dev/resources/iso-normes/countries_iso-3166_fr.txt b/dev/resources/iso-normes/countries_iso-3166_fr.txt index 578c0f0effe..532b73ef47e 100644 --- a/dev/resources/iso-normes/countries_iso-3166_fr.txt +++ b/dev/resources/iso-normes/countries_iso-3166_fr.txt @@ -3,11 +3,12 @@ # The list is updated whenever a change to the official code list in ISO 3166-1 is effected by the ISO 3166/MA. # It lists 240 official short names and code elements. One line of text contains one entry. # A country name and its code element are separated by a semicolon (;). -# http://www.iso.org/iso/fr/iso3166_fr_code_lists.txt +# https://www.iso.org/fr/iso-3166-country-codes.html -# ISO-3166: http://en.wikipedia.org/wiki/ISO_3166-1 -# ISO-3166 alpha 2: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 -# ISO-3166 alpha 3: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 +# https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes +# ISO-3166: https://fr.wikipedia.org/wiki/ISO_3166-1 +# ISO-3166 alpha 2: https://fr.wikipedia.org/wiki/ISO_3166-1_alpha-2 +# ISO-3166 alpha 3: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 AFGHANISTAN;AF AFRIQUE DU SUD;ZA @@ -254,4 +255,4 @@ VIET NAM;VN WALLIS ET FUTUNA;WF YÉMEN;YE ZAMBIE;ZM -ZIMBABWE;ZW \ No newline at end of file +ZIMBABWE;ZW diff --git a/dev/resources/iso-normes/locales.txt b/dev/resources/iso-normes/locales.txt index cb39e45ec0d..67ea5280342 100644 --- a/dev/resources/iso-normes/locales.txt +++ b/dev/resources/iso-normes/locales.txt @@ -1,9 +1,9 @@ For languages: -http://demo.icu-project.org/icu-bin/locexp?d_=fr +https://icu4c-demos.unicode.org/icu-bin/icudemos - Locale Explorer -> Error 404 For format number: -http://en.wikipedia.org/wiki/Decimal_mark +https://en.wikipedia.org/wiki/Decimal_mark For date format: -http://en.wikipedia.org/wiki/Date_format_by_country \ No newline at end of file +https://en.wikipedia.org/wiki/Date_format_by_country diff --git a/dev/resources/iso-normes/vat_number_names.txt b/dev/resources/iso-normes/vat_number_names.txt index 23fce59ed3b..b1e8d469ec8 100644 --- a/dev/resources/iso-normes/vat_number_names.txt +++ b/dev/resources/iso-normes/vat_number_names.txt @@ -1 +1,7 @@ -http://en.wikipedia.org/wiki/VAT_identification_number \ No newline at end of file +https://en.wikipedia.org/wiki/VAT_identification_number + +terms +(en) VAT = Value Added Tax +(fr) TVA = Taxe sur la Valeur Ajouté +(es) NIF / CIF +(de) USt / MwSt diff --git a/dev/resources/iso-normes/world_tax_rates.txt b/dev/resources/iso-normes/world_tax_rates.txt index 740062288dc..c007474e5fd 100644 --- a/dev/resources/iso-normes/world_tax_rates.txt +++ b/dev/resources/iso-normes/world_tax_rates.txt @@ -1,4 +1,5 @@ http://www.taxrates.cc/index.html +https://en.wikipedia.org/wiki/List_of_countries_by_tax_rates For India: VAT=IGST/CGST=Localtax1/SGST=Localtax2: https://cleartax.in/s/what-is-sgst-cgst-igst diff --git a/dev/resources/sepa/text.txt b/dev/resources/sepa/text.txt index dbcfeded5a4..dfa55834e58 100644 --- a/dev/resources/sepa/text.txt +++ b/dev/resources/sepa/text.txt @@ -1,3 +1,7 @@ +https://en.wikipedia.org/wiki/Single_Euro_Payments_Area +https://www.ecb.europa.eu/paym/integration/retail/sepa/html/index.en.html +https://www.europeanpaymentscouncil.eu/about-sepa + Spec for credit transfer: https://docs.oracle.com/cd/E39124_01/doc.91/e60210/fields_sepa_pay_file_appx.htm#EOAEL00515 diff --git a/dev/setup/codesniffer/README b/dev/setup/codesniffer/README index 087fb318f6f..2fdc66b9d1f 100644 --- a/dev/setup/codesniffer/README +++ b/dev/setup/codesniffer/README @@ -10,6 +10,11 @@ To run phpcs: > cd dolibarrgitrepo > phpcs --standard=dev/setup/codesniffer/ruleset.xml --extensions=php --parallel=8 . +To fix with phpcbf: +> cd dolibarrgitrepo +> phpcbf --standard=dev/setup/codesniffer/ruleset.xml --extensions=php --parallel=8 . + + Note with Eclipse: You must setup the PTI plugin of Eclipse into PHPCodeSniffer menu with: * tab value to 4 * path of code sniffer standard to dev/codesniffer diff --git a/dev/setup/codesniffer/ruleset.xml b/dev/setup/codesniffer/ruleset.xml index e99b8673981..e78438d8791 100644 --- a/dev/setup/codesniffer/ruleset.xml +++ b/dev/setup/codesniffer/ruleset.xml @@ -16,7 +16,7 @@ htdocs/conf.php */nltechno* */htdocs/includes - */htdocs/includes + source .git diff --git a/dev/translation/README b/dev/translation/README index 8d6954878b5..3ceedcd4b82 100644 --- a/dev/translation/README +++ b/dev/translation/README @@ -17,3 +17,7 @@ for Linux OS to install or to update transifex client: sudo pip install --upgrade transifex-client + +Comparison of Terms between ERPs +--------------------------------- +https://wiki.dolibarr.org/index.php?title=Comparison_of_Terms_between_ERPs diff --git a/doc/images/README.md b/doc/images/README.md index 7422d246d40..e93c9f9c3d4 100644 --- a/doc/images/README.md +++ b/doc/images/README.md @@ -10,17 +10,16 @@ https://github.com/Dolibarr/foundation -* Few icons are / were from website led24.de -* Attention: This website is no longer available! +# LICENCE OF IMAGE RESOURCES +-------------------------------- -This is original README file for this source: -------------------------------------------------------- +* All image resources (except dolihelp.ico and doliadmin.ico) in this directory are distributed under licence CC BY-SA + +List of icons from http://led24.de/iconset/ are: +- doliadmin.ico +- dolihelp.ico + +This is original README file for the package with this 2 images: You can do whatever you want with these icons (use on web or in desktop applications) as long as you don’t pass them off as your own and remove this readme file. A credit statement and a link back to http://led24.de/iconset/ or http://led24.de/ would be appreciated. - -Follow us on twitter http://twitter.com/gasyoun or email leds24@gmail.com -512 icons 20/05/2009 -------------------------------------------------------- -List of icons from http://led24.de/iconset/ are: -- dolihelp.ico diff --git a/doc/images/appicon_128.png b/doc/images/appicon_128.png index 60b82198bbd..b1f4e0bc9b2 100644 Binary files a/doc/images/appicon_128.png and b/doc/images/appicon_128.png differ diff --git a/doc/images/appicon_14.png b/doc/images/appicon_14.png deleted file mode 100644 index 6d41a440d25..00000000000 Binary files a/doc/images/appicon_14.png and /dev/null differ diff --git a/doc/images/appicon_16.ico b/doc/images/appicon_16.ico index 5d4a155baa0..22b04f213aa 100644 Binary files a/doc/images/appicon_16.ico and b/doc/images/appicon_16.ico differ diff --git a/doc/images/appicon_16.png b/doc/images/appicon_16.png index 0657833a8e7..a199f94a07f 100644 Binary files a/doc/images/appicon_16.png and b/doc/images/appicon_16.png differ diff --git a/doc/images/appicon_32.ico b/doc/images/appicon_32.ico new file mode 100644 index 00000000000..b0cba0f6af9 Binary files /dev/null and b/doc/images/appicon_32.ico differ diff --git a/doc/images/appicon_32.png b/doc/images/appicon_32.png index 8e456bb15e1..2eb74873d8f 100644 Binary files a/doc/images/appicon_32.png and b/doc/images/appicon_32.png differ diff --git a/doc/images/appicon_48.ico b/doc/images/appicon_48.ico index 0be300a91a6..5acfa77ea75 100644 Binary files a/doc/images/appicon_48.ico and b/doc/images/appicon_48.ico differ diff --git a/doc/images/appicon_64.png b/doc/images/appicon_64.png index 220e09e97f5..a08d91a0cb7 100644 Binary files a/doc/images/appicon_64.png and b/doc/images/appicon_64.png differ diff --git a/doc/images/dolibarr_favicon.ico b/doc/images/dolibarr_favicon.ico index b93a86747d6..b0cba0f6af9 100644 Binary files a/doc/images/dolibarr_favicon.ico and b/doc/images/dolibarr_favicon.ico differ diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index 0ebba6c18a4..0f4d538cfac 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -54,8 +54,8 @@ $code = GETPOST('code', 'alpha'); $acts[0] = "activate"; $acts[1] = "disable"; -$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); -$actl[1] = img_picto($langs->trans("Activated"), 'switch_on'); +$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off', 'class="size15x"'); +$actl[1] = img_picto($langs->trans("Activated"), 'switch_on', 'class="size15x"'); $listoffset = GETPOST('listoffset', 'alpha'); $listlimit = GETPOST('listlimit', 'int') > 0 ?GETPOST('listlimit', 'int') : 1000; @@ -442,7 +442,7 @@ if ($id) { } else { $sql .= " WHERE "; } - $sql .= " c.rowid = ".$search_country_id; + $sql .= " c.rowid = ".((int) $search_country_id); } // If sort order is "country", we use country_code instead @@ -609,10 +609,12 @@ if ($id) { print ''; if ($num) { + $i = 0; // Lines with values while ($i < $num) { $obj = $db->fetch_object($resql); //print_r($obj); + print ''; if ($action == 'edit' && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) { print '
'; @@ -708,6 +710,7 @@ if ($id) { print "\n"; } + $i++; } } diff --git a/htdocs/accountancy/admin/categories_list.php b/htdocs/accountancy/admin/categories_list.php index 549bd942524..9a8a84893fe 100644 --- a/htdocs/accountancy/admin/categories_list.php +++ b/htdocs/accountancy/admin/categories_list.php @@ -48,8 +48,8 @@ if (empty($user->rights->accounting->chartofaccount)) { $acts[0] = "activate"; $acts[1] = "disable"; -$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); -$actl[1] = img_picto($langs->trans("Activated"), 'switch_on'); +$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off', 'class="size15x"'); +$actl[1] = img_picto($langs->trans("Activated"), 'switch_on', 'class="size15x"'); $listoffset = GETPOST('listoffset', 'alpha'); $listlimit = GETPOST('listlimit', 'int') > 0 ?GETPOST('listlimit', 'int') : 1000; @@ -444,7 +444,7 @@ if ($search_country_id > 0) { } else { $sql .= " WHERE "; } - $sql .= " (a.fk_country = ".$search_country_id." OR a.fk_country = 0)"; + $sql .= " (a.fk_country = ".((int) $search_country_id)." OR a.fk_country = 0)"; } // If sort order is "country", we use country_code instead diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 59aeaae06f0..79a5c0975b7 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -169,7 +169,7 @@ foreach ($list_account_main as $key) { print ''; // Value print ''; // Do not force class=right, or it align also the content of the select box - print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1); + print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain'); print ''; print ''; } @@ -186,7 +186,7 @@ foreach ($list_account as $key) { print ''.$label.''; // Value print ''; // Do not force class=right, or it align also the content of the select box - print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1); + print $formaccounting->select_account($conf->global->$key, $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accounts'); print ''; print ''; } diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index a0764a97af2..24d31acddd6 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -302,7 +302,9 @@ if (!empty($conf->global->BANK_DISABLE_DIRECT_INPUT)) { print ''; print ''; -print ''.$langs->trans("ACCOUNTANCY_COMBO_FOR_AUX").''; +print ''.$langs->trans("ACCOUNTANCY_COMBO_FOR_AUX"); +print ' - '.$langs->trans("NotRecommended").''; +print ''; if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { print ''; diff --git a/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index 7aecfaada49..9ba9d8a6e20 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -51,8 +51,8 @@ if (empty($user->rights->accounting->chartofaccount)) { $acts[0] = "activate"; $acts[1] = "disable"; -$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); -$actl[1] = img_picto($langs->trans("Activated"), 'switch_on'); +$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off', 'class="size15x"'); +$actl[1] = img_picto($langs->trans("Activated"), 'switch_on', 'class="size15x"'); $listoffset = GETPOST('listoffset', 'alpha'); $listlimit = GETPOST('listlimit', 'int') > 0 ?GETPOST('listlimit', 'int') : 1000; diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 2013b0c7295..e29653a3e40 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -183,7 +183,7 @@ if ($action == 'update') { } if ($result <= 0) { // setEventMessages(null, $accounting->errors, 'errors'); - $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Product").' '.$productid.' '.$langs->trans("NotVentilatedinAccount").' : id='.$accounting_account_id.'
'.$sql.'
'; + $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Product").' '.$productid.' '.$langs->trans("NotVentilatedinAccount").' : id='.$accounting_account_id.'
'.$sql.'
'; $ko++; } else { $db->begin(); @@ -270,8 +270,8 @@ if (empty($pcgvercode)) { $sql = "SELECT p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.tva_tx,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell, pa.accountancy_code_sell_intra, pa.accountancy_code_sell_export,"; - $sql .= " pa.accountancy_code_buy, pa.accountancy_code_buy_intra, pa.accountancy_code_buy_export,"; + $sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export,"; + $sql .= " ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export,"; } else { $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export,"; $sql .= " p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,"; @@ -280,14 +280,14 @@ $sql .= " p.tms, p.fk_product_type as product_type,"; $sql .= " aa.rowid as aaid"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = pa." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ppe." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; } else { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; } $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; if (strlen(trim($search_current_account))) { - $sql .= natural_search((empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "pa.") . $accountancy_field_name, $search_current_account); + $sql .= natural_search((empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "ppe.") . $accountancy_field_name, $search_current_account); } if ($search_current_account_valid == 'withoutvalidaccount') { $sql .= " AND aa.account_number IS NULL"; @@ -466,7 +466,7 @@ if ($result) { } else { print_liste_field_titre("OnBuy", $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'center '); } - print_liste_field_titre("CurrentDedicatedAccountingAccount", $_SERVER["PHP_SELF"], (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "pa.") . $accountancy_field_name, "", $param, '', $sortfield, $sortorder); + print_liste_field_titre("CurrentDedicatedAccountingAccount", $_SERVER["PHP_SELF"], (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "ppe.") . $accountancy_field_name, "", $param, '', $sortfield, $sortorder); print_liste_field_titre("AssignDedicatedAccountingAccount"); $clickpitco = $form->showCheckAddButtons('checkforselect', 1); print_liste_field_titre($clickpitco, '', '', '', '', '', '', '', 'center '); diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index e03790a8995..a35333020cd 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -1,7 +1,7 @@ * Copyright (C) 2016 Florian Henry - * Copyright (C) 2016-2020 Alexandre Spangaro + * Copyright (C) 2016-2021 Alexandre Spangaro * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; 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.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; @@ -38,9 +39,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; // Load translation files required by the page $langs->loadLangs(array("accountancy", "compta")); -$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -$sortorder = GETPOST("sortorder", 'alpha'); -$sortfield = GETPOST("sortfield", 'alpha'); $action = GETPOST('action', 'aZ09'); // Load variable for pagination @@ -60,7 +58,7 @@ $pagenext = $page + 1; $show_subgroup = GETPOST('show_subgroup', 'alpha'); $search_date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); $search_date_end = dol_mktime(23, 59, 59, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); - +$search_ledger_code = GETPOST('search_ledger_code', 'array'); $search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); if ($search_accountancy_code_start == - 1) { $search_accountancy_code_start = ''; @@ -70,7 +68,9 @@ if ($search_accountancy_code_end == - 1) { $search_accountancy_code_end = ''; } +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new BookKeeping($db); +$hookmanager->initHooks(array('balancelist')); // Note that conf->hooks_modules contains array $formaccounting = new FormAccounting($db); $formother = new FormOther($db); @@ -134,6 +134,12 @@ if (!empty($search_accountancy_code_end)) { $filter['t.numero_compte<='] = $search_accountancy_code_end; $param .= '&search_accountancy_code_end='.$search_accountancy_code_end; } +if (!empty($search_ledger_code)) { + $filter['t.code_journal'] = $search_ledger_code; + foreach ($search_ledger_code as $code) { + $param .= '&search_ledger_code[]='.urlencode($code); + } +} if (empty($conf->accounting->enabled)) { accessforbidden(); @@ -151,15 +157,23 @@ if (empty($user->rights->accounting->mouvements->lire)) { * Action */ -if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers - $show_subgroup = ''; - $search_date_start = ''; - $search_date_end = ''; - $search_accountancy_code_start = ''; - $search_accountancy_code_end = ''; - $filter = array(); +$parameters = array('socid'=>$socid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } +if (empty($reshook)) { + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $show_subgroup = ''; + $search_date_start = ''; + $search_date_end = ''; + $search_accountancy_code_start = ''; + $search_accountancy_code_end = ''; + $search_ledger_code = array(); + $filter = array(); + } +} /* * View @@ -178,11 +192,11 @@ if ($action == 'export_csv') { } foreach ($object->lines as $line) { - print length_accountg($line->numero_compte).$sep; - print $object->get_compte_desc($line->numero_compte).$sep; - print price($line->debit).$sep; - print price($line->credit).$sep; - print price($line->debit - $line->credit).$sep; + print '"'.length_accountg($line->numero_compte).'"'.$sep; + print '"'.$object->get_compte_desc($line->numero_compte).'"'.$sep; + print '"'.price($line->debit).'"'.$sep; + print '"'.price($line->credit).'"'.$sep; + print '"'.price($line->debit - $line->credit).'"'.$sep; print "\n"; } @@ -221,22 +235,28 @@ if ($action != 'export_csv') { print ''; print ''; - $button = 'global->ACCOUNTING_EXPORT_FORMAT.')" />'; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $button = 'global->ACCOUNTING_EXPORT_FORMAT.')" />'; - print ''; + '; + } print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $button, $result, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit); + $selectedfields = ''; + $moreforfilter = ''; $moreforfilter .= '
'; @@ -249,6 +269,12 @@ if ($action != 'export_csv') { $moreforfilter .= ': '; $moreforfilter .= ''; + $moreforfilter .= '
'; + + $moreforfilter .= '
'; + + $moreforfilter .= $langs->trans("Journal"); + $moreforfilter .= $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1); $moreforfilter .= '
'; @@ -261,24 +287,29 @@ if ($action != 'export_csv') { print ''; } + $colspan = (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE) ? 5 : 4); print ''; print ''; print ''; - print ''; - - print ''; + print ''."\n"; print ''; print_liste_field_titre("AccountAccounting", $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder); @@ -288,8 +319,14 @@ if ($action != 'export_csv') { print_liste_field_titre("Debit", $_SERVER['PHP_SELF'], "t.debit", "", $param, 'class="right"', $sortfield, $sortorder); print_liste_field_titre("Credit", $_SERVER['PHP_SELF'], "t.credit", "", $param, 'class="right"', $sortfield, $sortorder); print_liste_field_titre("Balance", $_SERVER["PHP_SELF"], "", $param, "", 'class="right"', $sortfield, $sortorder); - print_liste_field_titre('', $_SERVER["PHP_SELF"], "", $param, "", 'width="60" class="center"', $sortfield, $sortorder); - print "\n"; + + // Hook fields + $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); + $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + print ''."\n"; $total_debit = 0; $total_credit = 0; @@ -415,7 +452,8 @@ if ($action != 'export_csv') { } else { print ''; } - print ''; print "\n"; diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 03600781319..81b6f98570e 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -579,7 +579,7 @@ if ($action == 'create') { { $sqlmid = 'SELECT rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."facture as fac"; - $sqlmid .= " WHERE fac.rowid=" . $object->fk_doc; + $sqlmid .= " WHERE fac.rowid=" . ((int) $object->fk_doc); dol_syslog("accountancy/bookkeeping/card.php::sqlmid=" . $sqlmid, LOG_DEBUG); $resultmid = $db->query($sqlmid); if ($resultmid) { diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index a9ef259e243..cd44e3598e3 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -74,7 +74,7 @@ if ($search_accountancy_code_end == - 1) { $search_accountancy_code_end = ''; } -$search_accountancy_aux_code = GETPOST("search_accountancy_aux_code"); +$search_accountancy_aux_code = GETPOST("search_accountancy_aux_code", 'alpha'); $search_accountancy_aux_code_start = GETPOST('search_accountancy_aux_code_start', 'alpha'); if ($search_accountancy_aux_code_start == - 1) { $search_accountancy_aux_code_start = ''; @@ -473,12 +473,14 @@ if (count($filter) > 0) { $sqlwhere[] = $key.'=\''.$db->idate($value).'\''; } elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') { $sqlwhere[] = $key.'\''.$db->idate($value).'\''; - } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.subledger_account>=' || $key == 't.subledger_account<=') { + } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=') { $sqlwhere[] = $key.'\''.$db->escape($value).'\''; } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { $sqlwhere[] = $key.'='.$value; - } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { + } elseif ($key == 't.numero_compte') { $sqlwhere[] = $key.' LIKE \''.$db->escape($value).'%\''; + } elseif ($key == 't.subledger_account') { + $sqlwhere[] = natural_search($key, $value, 0, 1); } elseif ($key == 't.date_creation>=' || $key == 't.date_creation<=') { $sqlwhere[] = $key.'\''.$db->idate($value).'\''; } elseif ($key == 't.tms>=' || $key == 't.tms<=') { @@ -780,36 +782,29 @@ if (!empty($arrayfields['t.doc_ref']['checked'])) { if (!empty($arrayfields['t.numero_compte']['checked'])) { print ''; } // Subledger account if (!empty($arrayfields['t.subledger_account']['checked'])) { print ''; } // Label operation diff --git a/htdocs/accountancy/bookkeeping/listbysubaccount.php b/htdocs/accountancy/bookkeeping/listbysubaccount.php index 129e695de3c..43d4acf343f 100644 --- a/htdocs/accountancy/bookkeeping/listbysubaccount.php +++ b/htdocs/accountancy/bookkeeping/listbysubaccount.php @@ -682,7 +682,7 @@ while ($i < min($num, $limit)) { print ""; print ''; - if (empty($obj->lettering_code)) { + if (empty($obj->lettering_code) && empty($obj->date_validated)) { print ''; print ''; print ''; print ''; - print ''; print ''; //print ''; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index f52dfc6d589..4df8d6b9b15 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2020 Alexandre Spangaro + * Copyright (C) 2013-2021 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent @@ -59,9 +59,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); @@ -135,9 +140,14 @@ if (empty($reshook)) { $search_amount = ''; $search_account = ''; $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; $search_country = ''; $search_tvaintra = ''; } @@ -219,8 +229,8 @@ $sql = "SELECT f.rowid as facid, f.ref, f.datef, f.type as ftype,"; $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell as code_sell, pa.accountancy_code_sell_intra as code_sell_intra, pa.accountancy_code_sell_export as code_sell_export,"; - $sql .= " pa.accountancy_code_buy as code_buy, pa.accountancy_code_buy_intra as code_buy_intra, pa.accountancy_code_buy_export as code_buy_export,"; + $sql .= " ppe.accountancy_code_sell as code_sell, ppe.accountancy_code_sell_intra as code_sell_intra, ppe.accountancy_code_sell_export as code_sell_export,"; + $sql .= " ppe.accountancy_code_buy as code_buy, ppe.accountancy_code_buy_intra as code_buy_intra, ppe.accountancy_code_buy_export as code_buy_export,"; } else { $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; @@ -229,8 +239,8 @@ $sql .= " p.tosell as status, p.tobuy as status_buy,"; $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; $sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,"; -if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " sa.accountancy_code_sell as company_code_sell"; +if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { + $sql .= " spe.accountancy_code_sell as company_code_sell"; } else { $sql .= " s.accountancy_code_sell as company_code_sell"; } @@ -240,16 +250,16 @@ $sql .= $hookmanager->resPrint; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as sa ON sa.fk_soc = s.rowid AND sa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity); } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facturedet as l ON f.rowid = l.fk_facture"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } -$alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "sa"; -$alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; +$alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "spe"; +$alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; @@ -289,7 +299,12 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("l.tva_tx", price2num($search_vat), 1); } -$sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +} if (strlen(trim($search_country))) { $arrayofcode = getCountriesInEEC(); $country_code_in_EEC = $country_code_in_EEC_without_me = ''; @@ -368,14 +383,23 @@ if ($result) { if ($search_lineid) { $param .= '&search_lineid='.urlencode($search_lineid); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } if ($search_invoice) { $param .= '&search_invoice='.urlencode($search_invoice); @@ -436,12 +460,13 @@ if ($result) { print ''; print ''; print ''; - print ''; print ''; //print ''; @@ -450,7 +475,7 @@ if ($result) { print ''; print ''; print ''; print ''; @@ -687,8 +712,8 @@ if ($result) { print ''; // Found accounts - print ''; print ''; print ''; - print ''; print ''; print ''; diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 414cd624bee..63dd996a546 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2020 Alexandre Spangaro + * Copyright (C) 2013-2021 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2014 Juanjo Menent s @@ -60,9 +60,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); @@ -140,9 +145,14 @@ if (empty($reshook)) { $search_amount = ''; $search_account = ''; $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; $search_country = ''; $search_tvaintra = ''; } @@ -188,7 +198,7 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { $msg .= '
'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'; $ok++; } else { - $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'.$sql.'
'; + $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'.$sql.'
'; $ko++; } } @@ -224,8 +234,8 @@ $sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_lab $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell as code_sell, pa.accountancy_code_sell_intra as code_sell_intra, pa.accountancy_code_sell_export as code_sell_export,"; - $sql .= " pa.accountancy_code_buy as code_buy, pa.accountancy_code_buy_intra as code_buy_intra, pa.accountancy_code_buy_export as code_buy_export,"; + $sql .= " ppe.accountancy_code_sell as code_sell, ppe.accountancy_code_sell_intra as code_sell_intra, ppe.accountancy_code_sell_export as code_sell_export,"; + $sql .= " ppe.accountancy_code_buy as code_buy, ppe.accountancy_code_buy_intra as code_buy_intra, ppe.accountancy_code_buy_export as code_buy_export,"; } else { $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; @@ -235,7 +245,7 @@ $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_ $sql .= " co.code as country_code, co.label as country_label,"; $sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { - $sql .= " sa.accountancy_code_buy as company_code_buy"; + $sql .= " spe.accountancy_code_buy as company_code_buy"; } else { $sql .= " s.accountancy_code_buy as company_code_buy"; } @@ -245,16 +255,16 @@ $sql .= $hookmanager->resPrint; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as sa ON sa.fk_soc = s.rowid AND sa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity); } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn_det as l ON f.rowid = l.fk_facture_fourn"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } -$alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "sa"; -$alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; +$alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "spe"; +$alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; @@ -293,7 +303,12 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("l.tva_tx", price2num($search_vat), 1); } -$sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +} if (strlen(trim($search_country))) { $arrayofcode = getCountriesInEEC(); $country_code_in_EEC = $country_code_in_EEC_without_me = ''; @@ -372,14 +387,23 @@ if ($result) { if ($search_lineid) { $param .= '&search_lineid='.urlencode($search_lineid); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } if ($search_invoice) { $param .= '&search_invoice='.urlencode($search_invoice); @@ -444,12 +468,13 @@ if ($result) { print '
'; print ''; //print ''; - print ''; print ''; print ''; @@ -671,8 +696,8 @@ if ($result) { print ''; // Found accounts - print ''; print ''; + // Website + print ''; + print ''; + // Address print ''; + $val = (GETPOSTISSET('member_'.$key) ? GETPOST('member_'.$key, 'alpha') : (empty($object->socialnetworks[$key]) ? '' : $object->socialnetworks[$key])); + print ''; } } @@ -1167,17 +1176,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { document.formsoc.action.value="edit"; document.formsoc.submit(); }); - function initfieldrequired() - { + function initfieldrequired() { jQuery("#tdcompany").removeClass("fieldrequired"); jQuery("#tdlastname").removeClass("fieldrequired"); jQuery("#tdfirstname").removeClass("fieldrequired"); - if (jQuery("#morphy").val() == \'mor\') - { + if (jQuery("#morphy").val() == \'mor\') { jQuery("#tdcompany").addClass("fieldrequired"); } - if (jQuery("#morphy").val() == \'phy\') - { + if (jQuery("#morphy").val() == \'phy\') { jQuery("#tdlastname").addClass("fieldrequired"); jQuery("#tdfirstname").addClass("fieldrequired"); } @@ -1278,6 +1284,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; print ''; + // Website + print ''; + print ''; + // Address print ''; print ''; print ''; print ''."\n"; diff --git a/htdocs/admin/commande_fournisseur_dispatch_extrafields.php b/htdocs/admin/commande_fournisseur_dispatch_extrafields.php index d0c7c85463e..ac8f4fced4d 100644 --- a/htdocs/admin/commande_fournisseur_dispatch_extrafields.php +++ b/htdocs/admin/commande_fournisseur_dispatch_extrafields.php @@ -84,7 +84,7 @@ print "
\n"; $head = reception_admin_prepare_head(); -print dol_get_fiche_head($head, 'attributeslines_reception', $langs->trans("Receptions"), -1, 'sending'); +print dol_get_fiche_head($head, 'attributeslines_reception', $langs->trans("Receptions"), -1, 'reception'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/delais.php b/htdocs/admin/delais.php index 00f05152a86..4b1e34335e8 100644 --- a/htdocs/admin/delais.php +++ b/htdocs/admin/delais.php @@ -359,16 +359,16 @@ if (empty($conf->global->MAIN_DISABLE_METEO) || $conf->global->MAIN_DISABLE_METE print '
'; print '
'; print img_weather($text, 0, $options); - print ' <=  %'; + print ' <=  %'; print '
'; print img_weather($text, 1, $options); - print ' <=  %'; + print ' <=  %'; print '
'; print img_weather($text, 2, $options); - print ' <=  %'; + print ' <=  %'; print '
'; print img_weather($text, 3, $options); - print ' <=  %'; + print ' <=  %'; print '
'; print '
'; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 2e4b88c2287..230c6e28229 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -70,8 +70,8 @@ if (!$allowed) { $acts = array(); $actl = array(); $acts[0] = "activate"; $acts[1] = "disable"; -$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); -$actl[1] = img_picto($langs->trans("Activated"), 'switch_on'); +$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off', 'class="size15x"'); +$actl[1] = img_picto($langs->trans("Activated"), 'switch_on', 'class="size15x"'); $listoffset = GETPOST('listoffset'); $listlimit = GETPOST('listlimit') > 0 ?GETPOST('listlimit') : 1000; // To avoid too long dictionaries @@ -100,7 +100,7 @@ $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, 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, 41, 0, 15, 30, 0, 37, 42, 0, 25, 0); +$taborder = array(9, 0, 4, 3, 2, 0, 1, 8, 19, 16, 39, 27, 40, 38, 0, 5, 11, 0, 6, 0, 29, 0, 33, 34, 32, 24, 28, 17, 35, 36, 0, 10, 23, 12, 13, 7, 0, 14, 0, 22, 20, 18, 21, 41, 0, 15, 30, 0, 37, 42, 0, 43, 0, 25, 0); // Name of SQL tables of dictionaries $tabname = array(); @@ -146,6 +146,7 @@ $tabname[39] = MAIN_DB_PREFIX."c_prospectcontactlevel"; $tabname[40] = MAIN_DB_PREFIX."c_stcommcontact"; $tabname[41] = MAIN_DB_PREFIX."c_transport_mode"; $tabname[42] = MAIN_DB_PREFIX."c_product_nature"; +$tabname[43] = MAIN_DB_PREFIX."c_productbatch_qcstatus"; // Dictionary labels $tablib = array(); @@ -191,6 +192,7 @@ $tablib[39] = "DictionaryProspectContactLevel"; $tablib[40] = "DictionaryProspectContactStatus"; $tablib[41] = "DictionaryTransportMode"; $tablib[42] = "DictionaryProductNature"; +$tablib[43] = "DictionaryBatchStatus"; // Requests to extract data $tabsql = array(); @@ -236,6 +238,7 @@ $tabsql[39] = "SELECT code, label as libelle, sortorder, active FROM ".MAIN_DB_P $tabsql[40] = "SELECT id as rowid, code, libelle, picto, active FROM ".MAIN_DB_PREFIX."c_stcommcontact"; $tabsql[41] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_transport_mode"; $tabsql[42] = "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_product_nature"; +$tabsql[43] = "SELECT rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_productbatch_qcstatus"; // Criteria to sort dictionaries $tabsqlsort = array(); @@ -281,6 +284,7 @@ $tabsqlsort[39] = "sortorder ASC"; $tabsqlsort[40] = "code ASC"; $tabsqlsort[41] = "code ASC"; $tabsqlsort[42] = "code ASC"; +$tabsqlsort[43] = "code ASC"; // Field names in select result for dictionary display $tabfield = array(); @@ -326,6 +330,7 @@ $tabfield[39] = "code,libelle,sortorder"; $tabfield[40] = "code,libelle,picto"; $tabfield[41] = "code,label"; $tabfield[42] = "code,label"; +$tabfield[43] = "code,label"; // Edit field names for editing a record $tabfieldvalue = array(); @@ -371,6 +376,7 @@ $tabfieldvalue[39] = "code,libelle,sortorder"; $tabfieldvalue[40] = "code,libelle,picto"; $tabfieldvalue[41] = "code,label"; $tabfieldvalue[42] = "code,label"; +$tabfieldvalue[43] = "code,label"; // Field names in the table for inserting a record $tabfieldinsert = array(); @@ -417,6 +423,7 @@ $tabfieldinsert[39] = "code,label,sortorder"; $tabfieldinsert[40] = "code,libelle,picto"; $tabfieldinsert[41] = "code,label"; $tabfieldinsert[42] = "code,label"; +$tabfieldinsert[43] = "code,label"; // Rowid name of field depending if field is autoincrement on or off.. // Use "" if id field is "rowid" and has autoincrement on @@ -464,6 +471,7 @@ $tabrowid[39] = "code"; $tabrowid[40] = "id"; $tabrowid[41] = ""; $tabrowid[42] = "rowid"; +$tabrowid[43] = "rowid"; // Condition to show dictionary in setup page $tabcond = array(); @@ -509,6 +517,7 @@ $tabcond[39] = (!empty($conf->societe->enabled) && empty($conf->global->SOCIETE_ $tabcond[40] = (!empty($conf->societe->enabled) && !empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)); $tabcond[41] = !empty($conf->intracommreport->enabled); $tabcond[42] = !empty($conf->product->enabled); +$tabcond[43] = !empty($conf->product->enabled) && !empty($conf->productbatch->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2; // List of help for fields $tabhelp = array(); @@ -554,55 +563,58 @@ $tabhelp[39] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[40] = array('code'=>$langs->trans("EnterAnyCode"), 'picto'=>$langs->trans("PictoHelp")); $tabhelp[41] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[42] = array('code'=>$langs->trans("EnterAnyCode")); +$tabhelp[43] = array('code'=>$langs->trans("EnterAnyCode")); + +// Table to store complete informations (will replace all other table). Key is table name. +$tabcomplete = array( + 'c_forme_juridique'=>array('picto'=>'company'), + 'c_departements'=>array('picto'=>'country'), + 'c_regions'=>array('picto'=>'country'), + 'c_country'=>array('picto'=>'country'), + 'c_civility'=>array('picto'=>'contact'), + 'c_actioncomm'=>array('picto'=>'action'), + 'c_chargesociales'=>array('picto'=>'bill'), + 'c_typent'=>array('picto'=>'company'), + 'c_currencies'=>array('picto'=>'multicurrency'), + 'c_tva'=>array('picto'=>'bill'), + 'c_type_contact'=>array('picto'=>'contact'), + 'c_payment_term'=>array('picto'=>'bill'), + 'c_paiement'=>array('picto'=>'bill'), + 'c_ecotaxe'=>array('picto'=>'bill'), + 'c_paper_format'=>array('picto'=>'generic'), + 'c_prospectlevel'=>array('picto'=>'company'), + 'c_type_fees'=>array('picto'=>'trip'), + 'c_effectif'=>array('picto'=>'company'), + 'c_input_method'=>array('picto'=>'order'), + 'c_input_reason'=>array('picto'=>'order'), + 'c_availability'=>array('picto'=>'shipment'), + 'c_shipment_mode'=>array('picto'=>'shipment'), + 'c_revenuestamp'=>array('picto'=>'bill'), + 'c_type_resource'=>array('picto'=>'resource'), + 'c_type_container'=>array('picto'=>'website'), + 'c_stcomm'=>array('picto'=>'company'), + 'c_holiday_types'=>array('picto'=>'holiday'), + 'c_lead_status'=>array('picto'=>'project'), + 'c_format_cards'=>array('picto'=>'generic'), + 'c_hrm_public_holiday'=>array('picto'=>'holiday'), + 'c_hrm_department'=>array('picto'=>'hrm'), + 'c_hrm_function'=>array('picto'=>'hrm'), + 'c_exp_tax_cat'=>array('picto'=>'expensereport'), + 'c_exp_tax_range'=>array('picto'=>'expensereport'), + 'c_units'=>array('picto'=>'product'), + 'c_socialnetworks'=>array('picto'=>'share-alt'), + 'c_product_nature'=>array('picto'=>'product'), + 'c_transport_mode'=>array('picto'=>'incoterm'), + 'c_prospectcontactlevel'=>array('picto'=>'company'), + 'c_stcommcontact'=>array('picto'=>'company'), + 'c_product_nature'=>array('picto'=>'product'), + 'c_productbatch_qcstatus'=>array('picto'=>'lot'), + +); -// List of check for fields (NOT USED YET) -$tabfieldcheck = array(); -$tabfieldcheck[1] = array(); -$tabfieldcheck[2] = array(); -$tabfieldcheck[3] = array(); -$tabfieldcheck[4] = array(); -$tabfieldcheck[5] = array(); -$tabfieldcheck[6] = array(); -$tabfieldcheck[7] = array(); -$tabfieldcheck[8] = array(); -$tabfieldcheck[9] = array(); -$tabfieldcheck[10] = array(); -$tabfieldcheck[11] = array(); -$tabfieldcheck[12] = array(); -$tabfieldcheck[13] = array(); -$tabfieldcheck[14] = array(); -$tabfieldcheck[15] = array(); -$tabfieldcheck[16] = array(); -$tabfieldcheck[17] = array(); -$tabfieldcheck[18] = array(); -$tabfieldcheck[19] = array(); -$tabfieldcheck[20] = array(); -$tabfieldcheck[21] = array(); -$tabfieldcheck[22] = array(); -$tabfieldcheck[23] = array(); -$tabfieldcheck[24] = array(); -$tabfieldcheck[25] = array(); -//$tabfieldcheck[26] = array(); -$tabfieldcheck[27] = array(); -$tabfieldcheck[28] = array(); -$tabfieldcheck[29] = array(); -$tabfieldcheck[30] = array(); -//$tabfieldcheck[31] = array(); -$tabfieldcheck[32] = array(); -$tabfieldcheck[33] = array(); -$tabfieldcheck[34] = array(); -$tabfieldcheck[35] = array(); -$tabfieldcheck[36] = array(); -$tabfieldcheck[37] = array(); -$tabfieldcheck[38] = array(); -$tabfieldcheck[39] = array(); -$tabfieldcheck[40] = array(); -$tabfieldcheck[41] = array(); -$tabfieldcheck[42] = 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); - +complete_dictionary_with_modules($taborder, $tabname, $tablib, $tabsql, $tabsqlsort, $tabfield, $tabfieldvalue, $tabfieldinsert, $tabrowid, $tabcond, $tabhelp, $tabcomplete); // Defaut sortorder if (empty($sortfield)) { @@ -859,8 +871,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($value == 'price' || preg_match('/^amount/i', $value)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($value == 'taux' || $value == 'localtax1' || $value == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + } elseif ($value == 'taux' || $value == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($value == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); } @@ -928,8 +940,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($field == 'price' || preg_match('/^amount/i', $field)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($field == 'taux' || $field == 'localtax1' || $field == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + } elseif ($field == 'taux' || $field == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($field == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); } @@ -1151,7 +1163,7 @@ if ($id) { $sql .= " WHERE 1 = 1"; } if ($search_country_id > 0) { - $sql .= " AND c.rowid = ".$search_country_id; + $sql .= " AND c.rowid = ".((int) $search_country_id); } if ($search_code != '' && $id == 9) { $sql .= natural_search("code_iso", $search_code); @@ -1242,13 +1254,13 @@ if ($id) { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $class = "center"; $sortable = 0; } if ($value == 'localtax1') { - $valuetoshow = $langs->trans("Rate")." 2"; $class = "center"; + $valuetoshow = $langs->trans("RateOfTaxN", '2'); $class = "center"; } if ($value == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $class = "center"; $sortable = 0; } if ($value == 'localtax2') { - $valuetoshow = $langs->trans("Rate")." 3"; $class = "center"; + $valuetoshow = $langs->trans("RateOfTaxN", '3'); $class = "center"; } if ($value == 'organization') { $valuetoshow = $langs->trans("Organization"); @@ -1586,17 +1598,18 @@ if ($id) { } $cssprefix = 'center '; } + if ($value == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax1') { - $valuetoshow = $langs->trans("Rate")." 2"; $cssprefix = "center "; $sortable = 0; + $valuetoshow = $langs->trans("RateOfTaxN", '2'); $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax2') { - $valuetoshow = $langs->trans("Rate")." 3"; $cssprefix = "center "; $sortable = 0; + $valuetoshow = $langs->trans("RateOfTaxN", '3'); $cssprefix = "center "; $sortable = 0; } if ($value == 'organization') { $valuetoshow = $langs->trans("Organization"); @@ -1968,6 +1981,9 @@ if ($id) { } elseif ($value == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_product_nature') { $langs->load("products"); $valuetoshow = $langs->trans($obj->{$value}); + } elseif ($fieldlist[$field] == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'c_productbatch_qcstatus') { + $langs->load("productbatch"); + $valuetoshow = $langs->trans($obj->{$value}); } $class .= ($class ? ' ' : '').'tddict'; if ($value == 'note' && $id == 10) { @@ -2123,7 +2139,7 @@ if ($id) { print '
'; - print $langs->trans('From'); - print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', 1, array(), 1, 1, ''); + print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, '', 'accounts'); print ' '; - print $langs->trans('to'); - print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', 1, array(), 1, 1, ''); + print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, '', 'accounts'); print ''; + + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields); + $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Action column + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print '
'.price(price2num($line->debit - $line->credit, 'MT')).''.$link; + print ''; + print $link; print '
'; print '
'; - print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 1); + print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 'account'); print '
'; print '
'; - print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 1); + print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 'account'); print '
'; print '
'; - print '
'; // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because it does not // use setup of keypress to select thirdparty and this hang browser on large database. if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $langs->trans('From').' '; - print $formaccounting->select_auxaccount($search_accountancy_aux_code_start, 'search_accountancy_aux_code_start', 1); + print '
'; + //print $langs->trans('From').' '; + print $formaccounting->select_auxaccount($search_accountancy_aux_code_start, 'search_accountancy_aux_code_start', $langs->trans('From'), 'maxwidth250', 'subledgeraccount'); + print '
'; + print '
'; + print $formaccounting->select_auxaccount($search_accountancy_aux_code_end, 'search_accountancy_aux_code_end', $langs->trans('to'), 'maxwidth250', 'subledgeraccount'); + print '
'; } else { - print ''; + print ''; } - print '
'; - print '
'; - // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because it does not - // use setup of keypress to select thirdparty and this hang browser on large database. - if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $langs->trans('to').' '; - print $formaccounting->select_auxaccount($search_accountancy_aux_code_end, 'search_accountancy_aux_code_end', 1); - } else { - print ''; - } - print '
'; print '
'; if ($line->subledger_account != "" && $line->subledger_account != '-1') { - print $object->get_compte_desc($line->numero_compte).' : '.length_accounta($line->subledger_account); + print $line->subledger_label.' : '.length_accounta($line->subledger_account); } else { // Should not happen: subledger account must be null or a non empty value print ''.$langs->trans("Unknown"); diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php index 0064e8c4715..8669cae7c2f 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php @@ -281,7 +281,7 @@ if ($resql) { $journaltoshow = (($result > 0) ? $accountingjournal->getNomUrl(0, 0, 0, '', 0) : $obj->code_journal); print ''.$journaltoshow.''; print img_edit(); diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 75f1275c142..783fc7156c2 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -473,7 +473,7 @@ class AccountancyCategory // extends CommonObject $sql .= " SELECT DISTINCT aa.account_number"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = ".$conf->global->CHARTOFACCOUNTS; + $sql .= " AND asy.rowid = ".((int) $conf->global->CHARTOFACCOUNTS); $sql .= " AND aa.active = 1"; $sql .= " AND aa.entity = ".$conf->entity.")"; $sql .= " GROUP BY t.numero_compte, t.label_operation, t.doc_ref"; @@ -562,7 +562,7 @@ class AccountancyCategory // extends CommonObject $sql = "SELECT aa.rowid, aa.account_number"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = ".$conf->global->CHARTOFACCOUNTS; + $sql .= " AND asy.rowid = ".((int) $conf->global->CHARTOFACCOUNTS); $sql .= " AND aa.active = 1"; $sql .= " AND aa.entity = ".$conf->entity; $sql .= " ORDER BY LENGTH(aa.account_number) DESC;"; // LENGTH is ok with mysql and postgresql @@ -589,8 +589,8 @@ class AccountancyCategory // extends CommonObject $accountincptsadded[$account_number_formated] = 1; // We found an account number that is in list $cpts of account to add $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account"; - $sql .= " SET fk_accounting_category=".$id_cat; - $sql .= " WHERE rowid=".$obj->rowid; + $sql .= " SET fk_accounting_category=".((int) $id_cat); + $sql .= " WHERE rowid=".((int) $obj->rowid); dol_syslog(__METHOD__, LOG_DEBUG); $resqlupdate = $this->db->query($sql); if (!$resqlupdate) { @@ -629,7 +629,7 @@ class AccountancyCategory // extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account as aa"; $sql .= " SET fk_accounting_category= 0"; - $sql .= " WHERE aa.rowid= ".$cpt_id; + $sql .= " WHERE aa.rowid = ".((int) $cpt_id); $this->db->begin(); dol_syslog(__METHOD__." sql=".$sql, LOG_DEBUG); @@ -675,7 +675,7 @@ class AccountancyCategory // extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."c_accounting_category as c"; $sql .= " WHERE c.active = 1"; $sql .= " AND c.entity = ".$conf->entity; - $sql .= " AND (c.fk_country = ".$mysoc->country_id." OR c.fk_country = 0)"; + $sql .= " AND (c.fk_country = ".((int) $mysoc->country_id)." OR c.fk_country = 0)"; $sql .= " AND cat.rowid = t.fk_accounting_category"; $sql .= " AND t.entity = ".$conf->entity; $sql .= " ORDER BY cat.position ASC"; @@ -806,7 +806,7 @@ class AccountancyCategory // extends CommonObject if ($categorytype >= 0) { $sql .= " AND c.category_type = 1"; } - $sql .= " AND (c.fk_country = ".$mysoc->country_id." OR c.fk_country = 0)"; + $sql .= " AND (c.fk_country = ".((int) $mysoc->country_id)." OR c.fk_country = 0)"; $sql .= " ORDER BY c.position ASC"; $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index ad3e863cc8c..f007208cf57 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -557,13 +557,13 @@ class AccountancyExport $Tab['signe_montant'] = '+'; // The amount must be in centimes without decimal points. - $Tab['montant'] = str_pad(abs(($data->debit - $abs->credit) * 100), 12, '0', STR_PAD_LEFT); + $Tab['montant'] = str_pad(abs(($data->debit - $data->credit) * 100), 12, '0', STR_PAD_LEFT); $Tab['contrepartie'] = str_repeat(' ', 8); // Force date format : %d%m%y - if (!empty($data->date_echeance)) { - //$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE); - $Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%y'); // Format must be ddmmyy + if (!empty($data->date_lim_reglement)) { + //$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE); + $Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%y'); // Format must be ddmmyy } else { $Tab['date_echeance'] = '000000'; } @@ -660,9 +660,9 @@ class AccountancyExport $Tab['code_stat'] = str_repeat(' ', 4); - if (!empty($data->date_echeance)) { - //$Tab['date_echeance'] = dol_print_date($data->date_echeance, $conf->global->ACCOUNTING_EXPORT_DATE); - $Tab['date_echeance'] = dol_print_date($data->date_echeance, '%d%m%Y'); + if (!empty($data->date_lim_reglement)) { + //$Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, $conf->global->ACCOUNTING_EXPORT_DATE); + $Tab['date_echeance'] = dol_print_date($data->date_lim_reglement, '%d%m%Y'); } else { $Tab['date_echeance'] = dol_print_date($data->doc_date, '%d%m%Y'); } diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index a7d89c45294..99a0dc0dc48 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -347,10 +347,10 @@ class AccountingAccount extends CommonObject $sql .= " , label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "''"); $sql .= " , labelshort = ".($this->labelshort ? "'".$this->db->escape($this->labelshort)."'" : "''"); $sql .= " , fk_accounting_category = ".(empty($this->account_category) ? 0 : (int) $this->account_category); - $sql .= " , fk_user_modif = ".$user->id; + $sql .= " , fk_user_modif = ".((int) $user->id); $sql .= " , active = ".(int) $this->active; $sql .= " , reconcilable = ".(int) $this->reconcilable; - $sql .= " WHERE rowid = ".$this->id; + $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG); $result = $this->db->query($sql); @@ -602,7 +602,7 @@ class AccountingAccount extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account "; $sql .= "SET ".$fieldtouse." = '0'"; - $sql .= " WHERE rowid = ".$this->db->escape($id); + $sql .= " WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::accountDeactivate ".$fieldtouse." sql=".$sql, LOG_DEBUG); $result = $this->db->query($sql); @@ -640,7 +640,7 @@ class AccountingAccount extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account"; $sql .= " SET ".$fieldtouse." = '1'"; - $sql .= " WHERE rowid = ".$this->db->escape($id); + $sql .= " WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::account_activate ".$fieldtouse." sql=".$sql, LOG_DEBUG); $result = $this->db->query($sql); diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 611dfcdc30c..59d74783d04 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -129,12 +129,13 @@ class BookKeeping extends CommonObject /** * @var float FEC:Amount (Not necessary) - * @deprecated Use $amount + * @deprecated No more used (we have info into debit/credit and sens) */ public $montant; /** * @var float FEC:Amount (Not necessary) + * @deprecated No more used (we have info into debit/credit and sens) */ public $amount; @@ -286,34 +287,38 @@ class BookKeeping extends CommonObject $this->piece_num = 0; // First check if line not yet already in bookkeeping. - // Note that we must include doc_type - fk_doc - numero_compte - label to be sure to have unicity of line (we may have several lines + // Note that we must include 'doc_type - fk_doc - numero_compte - label' to be sure to have unicity of line (because we may have several lines // with same doc_type, fk_doc, numero_compte for 1 invoice line when using localtaxes with same account) // WARNING: This is not reliable, label may have been modified. This is just a small protection. - // The page to make journalization make the test on couple doc_type - fk_doc only. + // The page that make transfer make the test on couple (doc_type - fk_doc) only. $sql = "SELECT count(*) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'"; - $sql .= " AND fk_doc = ".$this->fk_doc; + $sql .= " AND fk_doc = ".((int) $this->fk_doc); if (!empty($conf->global->ACCOUNTANCY_ENABLE_FKDOCDET)) { - // DO NOT USE THIS IN PRPDUCTION. This will generate a lot of trouble into reports and will corrupt database (by generating duplicate entries. - $sql .= " AND fk_docdet = " . $this->fk_docdet; // This field can be 0 if record is for several lines + // DO NOT USE THIS IN PRODUCTION. This will generate a lot of trouble into reports and will corrupt database (by generating duplicate entries. + $sql .= " AND fk_docdet = " . $this->fk_docdet; // This field can be 0 if record is for several lines } $sql .= " AND numero_compte = '".$this->db->escape($this->numero_compte)."'"; $sql .= " AND label_operation = '".$this->db->escape($this->label_operation)."'"; - $sql .= " AND entity IN (".getEntity('accountancy').")"; + $sql .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features $resql = $this->db->query($sql); if ($resql) { $row = $this->db->fetch_object($resql); - if ($row->nb == 0) { - // Determine piece_num + if ($row->nb == 0) { // Not already into bookkeeping + // Check to know if piece_num already exists for data we try to insert to reuse the same value $sqlnum = "SELECT piece_num"; $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element; $sqlnum .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'"; // For example doc_type = 'bank' - $sqlnum .= " AND fk_docdet = ".$this->db->escape($this->fk_docdet); // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ... + $sqlnum .= " AND fk_doc = ".((int) $this->fk_doc); + if (!empty($conf->global->ACCOUNTANCY_ENABLE_FKDOCDET)) { + // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ... + $sqlnum .= " AND fk_docdet = ".((int) $this->fk_docdet); + } $sqlnum .= " AND doc_ref = '".$this->db->escape($this->doc_ref)."'"; // ref of source object - $sqlnum .= " AND entity IN (".getEntity('accountancy').")"; + $sqlnum .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features dol_syslog(get_class($this).":: create sqlnum=".$sqlnum, LOG_DEBUG); $resqlnum = $this->db->query($sqlnum); @@ -326,15 +331,14 @@ class BookKeeping extends CommonObject if (empty($this->piece_num)) { $sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum"; $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element; - $sqlnum .= " WHERE entity IN (".getEntity('accountancy').")"; + $sqlnum .= " WHERE entity = ".$conf->entity; // Do not use getEntity for accounting features - dol_syslog(get_class($this).":: create sqlnum=".$sqlnum, LOG_DEBUG); $resqlnum = $this->db->query($sqlnum); if ($resqlnum) { $objnum = $this->db->fetch_object($resqlnum); $this->piece_num = $objnum->maxpiecenum; } - dol_syslog(get_class($this).":: create this->piece_num=".$this->piece_num, LOG_DEBUG); + dol_syslog(get_class($this).":: create now this->piece_num=".$this->piece_num, LOG_DEBUG); } if (empty($this->piece_num)) { $this->piece_num = 1; @@ -370,8 +374,8 @@ class BookKeeping extends CommonObject $sql .= ", ".(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'"); $sql .= ", '".$this->db->escape($this->doc_type)."'"; $sql .= ", '".$this->db->escape($this->doc_ref)."'"; - $sql .= ", ".$this->fk_doc; - $sql .= ", ".$this->fk_docdet; + $sql .= ", ".((int) $this->fk_doc); + $sql .= ", ".((int) $this->fk_docdet); $sql .= ", ".(!empty($this->thirdparty_code) ? ("'".$this->db->escape($this->thirdparty_code)."'") : "NULL"); $sql .= ", ".(!empty($this->subledger_account) ? ("'".$this->db->escape($this->subledger_account)."'") : "NULL"); $sql .= ", ".(!empty($this->subledger_label) ? ("'".$this->db->escape($this->subledger_label)."'") : "NULL"); @@ -631,8 +635,8 @@ class BookKeeping extends CommonObject $sql .= ' '.(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'").','; $sql .= ' '.(!isset($this->doc_type) ? 'NULL' : "'".$this->db->escape($this->doc_type)."'").','; $sql .= ' '.(!isset($this->doc_ref) ? 'NULL' : "'".$this->db->escape($this->doc_ref)."'").','; - $sql .= ' '.(empty($this->fk_doc) ? '0' : $this->fk_doc).','; - $sql .= ' '.(empty($this->fk_docdet) ? '0' : $this->fk_docdet).','; + $sql .= ' '.(empty($this->fk_doc) ? '0' : (int) $this->fk_doc).','; + $sql .= ' '.(empty($this->fk_docdet) ? '0' : (int) $this->fk_docdet).','; $sql .= ' '.(!isset($this->thirdparty_code) ? 'NULL' : "'".$this->db->escape($this->thirdparty_code)."'").','; $sql .= ' '.(!isset($this->subledger_account) ? 'NULL' : "'".$this->db->escape($this->subledger_account)."'").','; $sql .= ' '.(!isset($this->subledger_label) ? 'NULL' : "'".$this->db->escape($this->subledger_label)."'").','; @@ -1135,6 +1139,12 @@ class BookKeeping extends CommonObject $sqlwhere[] = $key.' LIKE \''.$this->db->escape($value).'%\''; } elseif ($key == 't.subledger_label') { $sqlwhere[] = $key.' LIKE \''.$this->db->escape($value).'%\''; + } elseif ($key == 't.code_journal' && !empty($value)) { + if (is_array($value)) { + $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1); + } else { + $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); + } } else { $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; } @@ -1889,7 +1899,7 @@ class BookKeeping extends CommonObject $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte"; $sql .= " AND aa.active = 1"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = " . $pcgver; + $sql .= " AND asy.rowid = " . ((int) $pcgver); $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")"; $sql .= " ORDER BY account_number ASC"; */ @@ -1922,7 +1932,7 @@ class BookKeeping extends CommonObject $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.account_number = ab.numero_compte"; $sql .= " AND aa.active = 1"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = ".$pcgver; + $sql .= " AND asy.rowid = ".((int) $pcgver); $sql .= " AND ab.entity IN (".getEntity('accountancy').")"; $sql .= " ORDER BY account_number ASC"; diff --git a/htdocs/accountancy/closure/index.php b/htdocs/accountancy/closure/index.php index 390c288b606..bcb3d7901f5 100644 --- a/htdocs/accountancy/closure/index.php +++ b/htdocs/accountancy/closure/index.php @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "other", "main", "accountancy")); +$langs->loadLangs(array("compta", "bills", "other", "accountancy")); $socid = GETPOST('socid', 'int'); diff --git a/htdocs/accountancy/customer/card.php b/htdocs/accountancy/customer/card.php index f0bcd9f7a49..b3ce892b235 100644 --- a/htdocs/accountancy/customer/card.php +++ b/htdocs/accountancy/customer/card.php @@ -102,7 +102,7 @@ if (!empty($id)) { $sql = "SELECT f.ref, f.rowid as facid, l.fk_product, l.description, l.price,"; $sql .= " l.qty, l.rowid, l.tva_tx, l.remise_percent, l.subprice,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell as code_sell,"; + $sql .= " ppe.accountancy_code_sell as code_sell,"; } else { $sql .= " p.accountancy_code_sell as code_sell,"; } @@ -110,7 +110,7 @@ if (!empty($id)) { $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as l"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON l.fk_code_ventilation = aa.rowid"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = l.fk_facture"; diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 0b32e2802c4..9580e8bca37 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "other", "main", "accountancy")); +$langs->loadLangs(array("compta", "bills", "other", "accountancy")); // Security check if (empty($conf->accounting->enabled)) { @@ -110,13 +110,13 @@ if ($action == 'validatehistory') { $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; $sql1 .= " FROM " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facturedet.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . $conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facturedet.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_sell=accnt.account_number"; $sql1 .= " AND " . MAIN_DB_PREFIX . "facturedet.fk_code_ventilation = 0"; } else { $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet as fd, " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . $conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_sell=accnt.account_number"; $sql1 .= " AND fd.fk_code_ventilation = 0"; }*/ @@ -126,15 +126,15 @@ if ($action == 'validatehistory') { $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell as code_sell, pa.accountancy_code_sell_intra as code_sell_intra, pa.accountancy_code_sell_export as code_sell_export,"; + $sql .= " ppe.accountancy_code_sell as code_sell, ppe.accountancy_code_sell_intra as code_sell_intra, ppe.accountancy_code_sell_export as code_sell_export,"; } else { $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; } $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; $sql .= " s.tva_intra,"; - if (!empty($conf->global->ACCOUNTANCY_COMPANY_SHARED)) { - $sql .= " sa.accountancy_code_sell as company_code_sell"; + if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { + $sql .= " spe.accountancy_code_sell as company_code_sell"; } else { $sql .= " s.accountancy_code_sell as company_code_sell"; } @@ -145,10 +145,10 @@ if ($action == 'validatehistory') { $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facturedet as l ON f.rowid = l.fk_facture"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } - $alias_societe_perentity = empty($conf->global->ACCOUNTANCY_COMPANY_SHARED) ? "s" : "sa"; - $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; + $alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "spe"; + $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; @@ -170,7 +170,7 @@ if ($action == 'validatehistory') { while ($i < min($num_lines, 10000)) { // No more than 10000 at once $objp = $db->fetch_object($result); - $isBuyerInEEC = isInEEC($objp); + $isBuyerInEEC = isInEEC($objp); // This make a database request but there is a cache into $conf->cache['country_code_in_EEC'] // Level 2: Search suggested account for product/service (similar code exists in page list.php to make manual binding) $suggestedaccountingaccountfor = ''; diff --git a/htdocs/accountancy/customer/lines.php b/htdocs/accountancy/customer/lines.php index 6f522750398..1e6fb660c62 100644 --- a/htdocs/accountancy/customer/lines.php +++ b/htdocs/accountancy/customer/lines.php @@ -53,9 +53,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); @@ -109,9 +114,14 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_amount = ''; $search_account = ''; $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; $search_country = ''; $search_tvaintra = ''; } @@ -184,9 +194,9 @@ $sql .= " fd.rowid, fd.description, fd.product_type as line_type, fd.total_ht, f $sql .= " s.rowid as socid, s.nom as name, s.code_compta, s.code_client,"; $sql .= " p.rowid as product_id, p.fk_product_type as product_type, p.ref as product_ref, p.label as product_label,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell,"; + $sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export,"; } else { - $sql .= " p.accountancy_code_sell,"; + $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export,"; } $sql .= " aa.rowid as fk_compte, aa.account_number, aa.label as label_account, aa.labelshort as labelshort_account,"; $sql .= " fd.situation_percent,"; @@ -198,7 +208,7 @@ $sql .= $hookmanager->resPrint; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; @@ -210,7 +220,7 @@ $sql .= " AND f.fk_statut > 0"; if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_SITUATION.")"; } else { - $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_STANDARD.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")"; + $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")"; } // Add search filter like if ($search_societe) { @@ -240,7 +250,12 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("fd.tva_tx", price2num($search_vat), 1); } -$sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +} if (strlen(trim($search_country))) { $arrayofcode = getCountriesInEEC(); $country_code_in_EEC = $country_code_in_EEC_without_me = ''; @@ -315,14 +330,23 @@ if ($result) { if ($search_vat) { $param .= "&search_vat=".urlencode($search_vat); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } if ($search_country) { $param .= "&search_country=".urlencode($search_country); @@ -357,12 +381,13 @@ if ($result) { print '
'; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print '
'; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print '
'; - print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1); + print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1, null, 1); //print ''; print ''.$objp->tva_intra.''; - $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + print ''; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') { $shelp .= $langs->trans("SaleEEC"); @@ -699,7 +724,7 @@ if ($result) { print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); if ($objp->product_id > 0) { print '
'; - $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; $ttype = 'help'; if ($suggestedaccountingaccountfor == 'eec') { $shelp = $langs->trans("SaleEEC"); @@ -716,7 +741,7 @@ if ($result) { } else { if (!empty($conf->global->ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY)) { print '
'; - $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; $s .= $langs->trans("NotDefined"); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); @@ -724,7 +749,7 @@ if ($result) { } if (!empty($conf->global->ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY)) { print '
'; - $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; $shelp = ''; $s .= ($objp->code_sell_t > 0 ? length_accountg($objp->code_sell_t) : ''.$langs->trans("NotDefined").''); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 38f7f596932..baeefa1bbfb 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "other", "main", "accountancy")); +$langs->loadLangs(array("compta", "bills", "other", "accountancy")); $month_start = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1); if (GETPOST("year", 'int')) { @@ -103,13 +103,13 @@ if ($action == 'validatehistory') { $sql1 = "UPDATE ".MAIN_DB_PREFIX."expensereport_det"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; $sql1 .= " FROM ".MAIN_DB_PREFIX."c_type_fees as t, ".MAIN_DB_PREFIX."accounting_account as accnt , ".MAIN_DB_PREFIX."accounting_system as syst"; - $sql1 .= " WHERE ".MAIN_DB_PREFIX."expensereport_det.fk_c_type_fees = t.id AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=".$conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE ".MAIN_DB_PREFIX."expensereport_det.fk_c_type_fees = t.id AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid = ".((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND t.accountancy_code = accnt.account_number"; $sql1 .= " AND ".MAIN_DB_PREFIX."expensereport_det.fk_code_ventilation = 0"; } else { $sql1 = "UPDATE ".MAIN_DB_PREFIX."expensereport_det as erd, ".MAIN_DB_PREFIX."c_type_fees as t, ".MAIN_DB_PREFIX."accounting_account as accnt , ".MAIN_DB_PREFIX."accounting_system as syst"; $sql1 .= " SET erd.fk_code_ventilation = accnt.rowid"; - $sql1 .= " WHERE erd.fk_c_type_fees = t.id AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=".$conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE erd.fk_c_type_fees = t.id AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid = ".((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND t.accountancy_code=accnt.account_number"; $sql1 .= " AND erd.fk_code_ventilation = 0"; } diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 4d2d5f7b88a..810f65c68df 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -164,7 +164,7 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { $msg .= '
'.$langs->trans("LineOfExpenseReport").' '.$monId.' - '.$langs->trans("VentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'; $ok++; } else { - $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'.$sql.'
'; + $msg .= '
'.$langs->trans("ErrorDB").' : '.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NotVentilatedinAccount").' : '.length_accountg($accountventilated->account_number).'
'.$sql.'
'; $ko++; } } diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 94dc6aa05c9..6e13a662948 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -35,16 +35,23 @@ $langs->loadLangs(array("compta", "bills", "other", "accountancy", "loans", "ban $hookmanager->initHooks(array('accountancyindex')); // Security check -if (empty($conf->accounting->enabled)) { +if ($user->socid > 0) { accessforbidden(); } -if ($user->socid > 0) { +/* +if (empty($conf->accounting->enabled)) { accessforbidden(); } if (empty($user->rights->accounting->mouvements->lire)) { accessforbidden(); } - +*/ +if (empty($conf->comptabilite->enabled) && empty($conf->accounting->enabled) && empty($conf->asset->enabled) && empty($conf->intracommreport->enabled)) { + accessforbidden(); +} +if (empty($user->rights->compta->resultat->lire) && empty($user->rights->accounting->mouvements->lire) && empty($user->rights->asset->read) && empty($user->rights->intracommreport->read)) { + accessforbidden(); +} /* @@ -54,7 +61,7 @@ if (empty($user->rights->accounting->mouvements->lire)) { if (GETPOST('addbox')) { // Add box (when submit is done from a form when ajax disabled) require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; - $zone = GETPOST('areacode', 'aZ09'); + $zone = GETPOST('areacode', 'int'); $userid = GETPOST('userid', 'int'); $boxorder = GETPOST('boxorder', 'aZ09'); $boxorder .= GETPOST('boxcombo', 'aZ09'); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 27b37c74932..32670b15575 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -120,7 +120,8 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,"; $sql .= " ba.courant, ba.ref as baref, ba.account_number, ba.fk_accountancy_journal,"; $sql .= " soc.code_compta, soc.code_compta_fournisseur, soc.rowid as socid, soc.nom as name, soc.email as email, bu1.type as typeop_company,"; -$sql .= " u.accountancy_code, u.rowid as userid, u.lastname as lastname, u.firstname as firstname, u.email as useremail, bu2.type as typeop_user,"; +$sql .= " u.accountancy_code, u.rowid as userid, u.lastname as lastname, u.firstname as firstname, u.email as useremail, u.statut as userstatus,"; +$sql .= " bu2.type as typeop_user,"; $sql .= " bu3.type as typeop_payment, bu4.type as typeop_payment_supplier"; $sql .= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql .= " JOIN ".MAIN_DB_PREFIX."bank_account as ba on b.fk_account=ba.rowid"; @@ -130,7 +131,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_url as bu3 ON bu3.fk_bank = b.rowid A $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_url as bu4 ON bu4.fk_bank = b.rowid AND bu4.type='payment_supplier'"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as soc on bu1.url_id=soc.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on bu2.url_id=u.rowid"; -$sql .= " WHERE ba.fk_accountancy_journal=".$id_journal; +$sql .= " WHERE ba.fk_accountancy_journal=".((int) $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)."'"; @@ -259,7 +260,8 @@ if ($result) { 'lastname' => $obj->lastname, 'firstname' => $obj->firstname, 'email' => $obj->useremail, - 'accountancy_code' => $compta_user + 'accountancy_code' => $compta_user, + 'status' => $obj->userstatus ); // Variable bookkeeping ($obj->rowid is Bank Id) @@ -328,8 +330,10 @@ if ($result) { $userstatic->email = $tabuser[$obj->rowid]['email']; $userstatic->firstname = $tabuser[$obj->rowid]['firstname']; $userstatic->lastname = $tabuser[$obj->rowid]['lastname']; + $userstatic->statut = $tabuser[$obj->rowid]['status']; + $userstatic->accountancy_code = $tabuser[$obj->rowid]['accountancy_code']; if ($userstatic->id > 0) { - $tabpay[$obj->rowid]["soclib"] = $userstatic->getNomUrl(1, '', 30); + $tabpay[$obj->rowid]["soclib"] = $userstatic->getNomUrl(1, 'accountancy', 0); } else { $tabpay[$obj->rowid]["soclib"] = '???'; // Should not happen, but happens with old data when id of user was not saved on expense report payment. } @@ -507,6 +511,18 @@ var_dump($tabtype);*/ if (!$error && $action == 'writebookkeeping') { $now = dol_now(); + $accountingaccountcustomer = new AccountingAccount($db); + $accountingaccountcustomer->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER, true); + + $accountingaccountsupplier = new AccountingAccount($db); + $accountingaccountsupplier->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER, true); + + $accountingaccountpayment = new AccountingAccount($db); + $accountingaccountpayment->fetch(null, $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT, true); + + $accountingaccountsuspense = new AccountingAccount($db); + $accountingaccountsuspense->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUSPENSE, true); + $error = 0; foreach ($tabpay as $key => $val) { // $key is rowid into llx_bank $date = dol_print_date($db->jdate($val["date"]), 'day'); @@ -530,6 +546,9 @@ if (!$error && $action == 'writebookkeeping') { // Line into bank account foreach ($tabbq[$key] as $k => $mt) { if ($mt) { + $accountingaccount->fetch(null, $k, true); // $k is accounting bank account. TODO We should use a cache here to avoid this fetch + $account_label = $accountingaccount->label; + $reflabel = ''; if (!empty($val['lib'])) { $reflabel .= dol_string_nohtmltag($val['lib'])." - "; @@ -545,10 +564,9 @@ if (!$error && $action == 'writebookkeeping') { $bookkeeping->doc_type = 'bank'; $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_bank"]; - $bookkeeping->numero_compte = $k; - $accountingaccount->fetch(null, $k, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $account_label; $bookkeeping->label_operation = $reflabel; $bookkeeping->montant = $mt; @@ -606,6 +624,7 @@ if (!$error && $action == 'writebookkeeping') { $bookkeeping->doc_type = 'bank'; $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_bank"]; + $bookkeeping->label_operation = $reflabel; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; @@ -620,78 +639,63 @@ if (!$error && $action == 'writebookkeeping') { $bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp $bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER; - - $accountingaccount->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_compte = $accountingaccountcustomer->label; } elseif ($tabtype[$key] == 'payment_supplier') { // If payment is payment of supplier invoice, we get ref of invoice $bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp $bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER; - - $accountingaccount->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_compte = $accountingaccountsupplier->label; } elseif ($tabtype[$key] == 'payment_expensereport') { $bookkeeping->subledger_account = $tabuser[$key]['accountancy_code']; $bookkeeping->subledger_label = $tabuser[$key]['name']; $bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT; - - $accountingaccount->fetch(null, $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_compte = $accountingaccountpayment->label; } elseif ($tabtype[$key] == 'payment_salary') { $bookkeeping->subledger_account = $tabuser[$key]['accountancy_code']; $bookkeeping->subledger_label = $tabuser[$key]['name']; $bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT; - - $accountingaccount->fetch(null, $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_compte = $accountingaccountpayment->label; } elseif (in_array($tabtype[$key], array('sc', 'payment_sc'))) { // If payment is payment of social contribution $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'payment_vat') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'payment_donation') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'member') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'payment_loan') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'payment_various') { $bookkeeping->subledger_account = $k; $bookkeeping->subledger_label = $tabcompany[$key]['name']; + $accountingaccount->fetch(null, $tabpay[$key]["account_various"], true); // TODO Use a cache $bookkeeping->numero_compte = $tabpay[$key]["account_various"]; - - $accountingaccount->fetch(null, $bookkeeping->numero_compte, true); $bookkeeping->label_compte = $accountingaccount->label; } elseif ($tabtype[$key] == 'banktransfert') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $accountingaccount->fetch(null, $k, true); // TODO Use a cache $bookkeeping->numero_compte = $k; - - $accountingaccount->fetch(null, $k, true); $bookkeeping->label_compte = $accountingaccount->label; } else { if ($tabtype[$key] == 'unknown') { // Unknown transaction, we will use a waiting account for thirdparty. @@ -699,9 +703,7 @@ if (!$error && $action == 'writebookkeeping') { $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUSPENSE; - - $accountingaccount->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUSPENSE, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_compte = $accountingaccountsuspense->label; } } $bookkeeping->label_operation = $reflabel; @@ -1318,47 +1320,47 @@ function getSourceDocRef($val, $typerecord) if ($typerecord == 'payment') { $sqlmid = 'SELECT payfac.fk_facture as id, f.ref as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."paiement_facture as payfac, ".MAIN_DB_PREFIX."facture as f"; - $sqlmid .= " WHERE payfac.fk_facture = f.rowid AND payfac.fk_paiement=".$val["paymentid"]; + $sqlmid .= " WHERE payfac.fk_facture = f.rowid AND payfac.fk_paiement=".((int) $val["paymentid"]); $ref = $langs->transnoentitiesnoconv("Invoice"); } elseif ($typerecord == 'payment_supplier') { $sqlmid = 'SELECT payfac.fk_facturefourn as id, f.ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."paiementfourn_facturefourn as payfac, ".MAIN_DB_PREFIX."facture_fourn as f"; - $sqlmid .= " WHERE payfac.fk_facturefourn = f.rowid AND payfac.fk_paiementfourn=".$val["paymentsupplierid"]; + $sqlmid .= " WHERE payfac.fk_facturefourn = f.rowid AND payfac.fk_paiementfourn=".((int) $val["paymentsupplierid"]); $ref = $langs->transnoentitiesnoconv("SupplierInvoice"); } elseif ($typerecord == 'payment_expensereport') { $sqlmid = 'SELECT e.rowid as id, e.ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."payment_expensereport as pe, ".MAIN_DB_PREFIX."expensereport as e"; - $sqlmid .= " WHERE pe.rowid=".$val["paymentexpensereport"]." AND pe.fk_expensereport = e.rowid"; + $sqlmid .= " WHERE pe.rowid=".((int) $val["paymentexpensereport"])." AND pe.fk_expensereport = e.rowid"; $ref = $langs->transnoentitiesnoconv("ExpenseReport"); } elseif ($typerecord == 'payment_salary') { $sqlmid = 'SELECT s.rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."payment_salary as s"; - $sqlmid .= " WHERE s.rowid=".$val["paymentsalid"]; + $sqlmid .= " WHERE s.rowid=".((int) $val["paymentsalid"]); $ref = $langs->transnoentitiesnoconv("SalaryPayment"); } elseif ($typerecord == 'sc') { $sqlmid = 'SELECT sc.rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."paiementcharge as sc"; - $sqlmid .= " WHERE sc.rowid=".$val["paymentscid"]; + $sqlmid .= " WHERE sc.rowid=".((int) $val["paymentscid"]); $ref = $langs->transnoentitiesnoconv("SocialContribution"); } elseif ($typerecord == 'payment_vat') { $sqlmid = 'SELECT v.rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."tva as v"; - $sqlmid .= " WHERE v.rowid=".$val["paymentvatid"]; + $sqlmid .= " WHERE v.rowid=".((int) $val["paymentvatid"]); $ref = $langs->transnoentitiesnoconv("PaymentVat"); } elseif ($typerecord == 'payment_donation') { $sqlmid = 'SELECT payd.fk_donation as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."payment_donation as payd"; - $sqlmid .= " WHERE payd.fk_donation=".$val["paymentdonationid"]; + $sqlmid .= " WHERE payd.fk_donation=".((int) $val["paymentdonationid"]); $ref = $langs->transnoentitiesnoconv("Donation"); } elseif ($typerecord == 'payment_loan') { $sqlmid = 'SELECT l.rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."payment_loan as l"; - $sqlmid .= " WHERE l.rowid=".$val["paymentloanid"]; + $sqlmid .= " WHERE l.rowid=".((int) $val["paymentloanid"]); $ref = $langs->transnoentitiesnoconv("LoanPayment"); } elseif ($typerecord == 'payment_various') { $sqlmid = 'SELECT v.rowid as ref'; $sqlmid .= " FROM ".MAIN_DB_PREFIX."payment_various as v"; - $sqlmid .= " WHERE v.rowid=".$val["paymentvariousid"]; + $sqlmid .= " WHERE v.rowid=".((int) $val["paymentvariousid"]); $ref = $langs->transnoentitiesnoconv("VariousPayment"); } // Add warning diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 2916d4d1fca..0273690ae81 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -206,6 +206,9 @@ if ($action == 'writebookkeeping') { $now = dol_now(); $error = 0; + $accountingaccountexpense = new AccountingAccount($db); + $accountingaccountexpense->fetch(null, $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT, true); + foreach ($taber as $key => $val) { // Loop on each expense report $errorforline = 0; @@ -225,12 +228,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->doc_type = 'expense_report'; $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_expensereportdet"]; + $bookkeeping->subledger_account = $tabuser[$key]['user_accountancy_code']; $bookkeeping->subledger_label = $tabuser[$key]['name']; - $bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT; - $accountingaccount->fetch(null, $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $conf->global->SALARIES_ACCOUNTING_ACCOUNT_PAYMENT; + $bookkeeping->label_compte = $accountingaccountexpense->label; $bookkeeping->label_operation = $tabuser[$key]['name']; $bookkeeping->montant = $mt; @@ -274,10 +277,13 @@ if ($action == 'writebookkeeping') { $bookkeeping->doc_type = 'expense_report'; $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_expensereportdet"]; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $bookkeeping->numero_compte = $k; $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->label_operation = $accountingaccount->label; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'C' : 'D'; @@ -322,6 +328,9 @@ if ($action == 'writebookkeeping') { foreach ($arrayofvat[$key] as $k => $mt) { if ($mt) { + $accountingaccount->fetch($k, null, true); // TODO Use a cache for label + $account_label = $accountingaccount->label; + // get compte id and label $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; @@ -330,12 +339,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->doc_type = 'expense_report'; $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_expensereportdet"]; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; - $bookkeeping->numero_compte = $k; - $accountingaccount->fetch($k, null, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $account_label; $bookkeeping->label_operation = $langs->trans("VAT").' '.join(', ', $def_tva[$key][$k]).' %'; $bookkeeping->montant = $mt; diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index bf950182798..2677f8569f2 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -106,9 +106,17 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $sql = "SELECT f.rowid, f.ref as ref, f.type, f.datef as df, f.libelle,f.ref_supplier, f.date_lim_reglement as dlf, f.close_code,"; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.tva as total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; -$sql .= " p.accountancy_code_buy , aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; +if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " ppe.accountancy_code_buy,"; +} else { + $sql .= " p.accountancy_code_buy,"; +} +$sql .= " aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as fd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; +if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); +} $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " JOIN ".MAIN_DB_PREFIX."facture_fourn as f ON f.rowid = fd.fk_facture_fourn"; $sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; @@ -240,7 +248,7 @@ foreach ($tabfac as $key => $val) { // Loop on each invoice $sql = "SELECT COUNT(fd.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as fd"; $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0"; - $sql .= " AND fd.total_ttc <> 0 AND fk_facture_fourn = ".$key; + $sql .= " AND fd.total_ttc <> 0 AND fk_facture_fourn = ".((int) $key); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); @@ -262,6 +270,9 @@ if ($action == 'writebookkeeping') { $companystatic = new Societe($db); $invoicestatic = new FactureFournisseur($db); + $accountingaccountsupplier = new AccountingAccount($db); + + $accountingaccountsupplier->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER, true); foreach ($tabfac as $key => $val) { // Loop on each invoice $errorforline = 0; @@ -323,12 +334,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_fournisseur; + $bookkeeping->subledger_account = $tabcompany[$key]['code_compta_fournisseur']; $bookkeeping->subledger_label = $tabcompany[$key]['name']; - $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER; - $accountingaccount->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER; + $bookkeeping->label_compte = $accountingaccountsupplier->label; $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("SubledgerAccount"); $bookkeeping->montant = $mt; @@ -363,8 +374,11 @@ if ($action == 'writebookkeeping') { // Product / Service if (!$errorforline) { foreach ($tabht[$key] as $k => $mt) { + $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache + $label_account = $accountingaccount->label; + // get compte id and label - if ($accountingaccount->fetch(null, $k, true)) { + if ($resultfetch > 0) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; $bookkeeping->date_lim_reglement = $val["datereg"]; @@ -374,11 +388,14 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_fournisseur; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $bookkeeping->numero_compte = $k; - $bookkeeping->label_compte = $accountingaccount->label; - $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$accountingaccount->label; + $bookkeeping->label_compte = $label_account; + + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$label_account; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'C' : 'D'; $bookkeeping->debit = ($mt > 0) ? $mt : 0; @@ -424,6 +441,9 @@ if ($action == 'writebookkeeping') { foreach ($arrayofvat[$key] as $k => $mt) { if ($mt) { + $accountingaccount->fetch($k, null, true); // TODO Use a cache for label + $label_account = $accountingaccount->label; + $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; $bookkeeping->date_lim_reglement = $val["datereg"]; @@ -433,12 +453,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_fournisseur; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; - $bookkeeping->numero_compte = $k; - $accountingaccount->fetch($k, null, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $label_account; $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT").' '.join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : ''); $bookkeeping->montant = $mt; @@ -486,9 +506,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_fournisseur; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT").' NPR'; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'C' : 'D'; diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 1904631775d..d147186a8d8 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -110,14 +110,14 @@ $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.tot $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte,"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " pa.accountancy_code_sell"; + $sql .= " ppe.accountancy_code_sell"; } else { $sql .= " p.accountancy_code_sell"; } $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture"; @@ -148,7 +148,7 @@ if ($in_bookkeeping == 'notyet') { // $sql .= " AND fd.rowid NOT IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account } $sql .= " ORDER BY f.datef"; -//print $sql; +//print $sql; exit; dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG); $result = $db->query($sql); @@ -264,7 +264,7 @@ foreach ($tabfac as $key => $val) { // Loop on each invoice $sql = "SELECT COUNT(fd.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0"; - $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".$key; + $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); @@ -285,6 +285,9 @@ if ($action == 'writebookkeeping') { $companystatic = new Societe($db); $invoicestatic = new Facture($db); + $accountingaccountcustomer = new AccountingAccount($db); + + $accountingaccountcustomer->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER, true); foreach ($tabfac as $key => $val) { // Loop on each invoice $errorforline = 0; @@ -344,12 +347,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_client; + $bookkeeping->subledger_account = $tabcompany[$key]['code_compta']; $bookkeeping->subledger_label = $tabcompany[$key]['name']; - $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER; - $accountingaccount->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER; + $bookkeeping->label_compte = $accountingaccountcustomer->label; $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount"); $bookkeeping->montant = $mt; @@ -384,8 +387,11 @@ if ($action == 'writebookkeeping') { // Product / Service if (!$errorforline) { foreach ($tabht[$key] as $k => $mt) { + $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache + $label_account = $accountingaccount->label; + // get compte id and label - if ($accountingaccount->fetch(null, $k, true)) { + if ($resultfetch > 0) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; $bookkeeping->date_lim_reglement = $val["datereg"]; @@ -395,11 +401,14 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_client; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; + $bookkeeping->numero_compte = $k; - $bookkeeping->label_compte = $accountingaccount->label; - $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$accountingaccount->label; + $bookkeeping->label_compte = $label_account; + + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$label_account; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; $bookkeeping->debit = ($mt < 0) ? -$mt : 0; @@ -444,6 +453,9 @@ if ($action == 'writebookkeeping') { foreach ($arrayofvat[$key] as $k => $mt) { if ($mt) { + $accountingaccount->fetch($k, null, true); // TODO Use a cache for label + $label_account = $accountingaccount->label; + $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; $bookkeeping->date_lim_reglement = $val["datereg"]; @@ -453,12 +465,12 @@ if ($action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add $bookkeeping->thirdparty_code = $companystatic->code_client; + $bookkeeping->subledger_account = ''; $bookkeeping->subledger_label = ''; - $bookkeeping->numero_compte = $k; - $accountingaccount->fetch($k, null, true); - $bookkeeping->label_compte = $accountingaccount->label; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $label_account; $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").' '.join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : ''); $bookkeeping->montant = $mt; diff --git a/htdocs/accountancy/supplier/card.php b/htdocs/accountancy/supplier/card.php index cd17df33776..1e7887c1bdc 100644 --- a/htdocs/accountancy/supplier/card.php +++ b/htdocs/accountancy/supplier/card.php @@ -101,10 +101,18 @@ $formaccounting = new FormAccounting($db); if (!empty($id)) { $sql = "SELECT f.ref as ref, f.rowid as facid, l.fk_product, l.description, l.rowid, l.fk_code_ventilation, "; - $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label"; - $sql .= ", aa.account_number, aa.label"; + $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label,"; + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " ppe.accountancy_code_buy as code_buy,"; + } else { + $sql .= " p.accountancy_code_buy as code_buy,"; + } + $sql .= " aa.account_number, aa.label"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as l"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); + } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON l.fk_code_ventilation = aa.rowid"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn as f ON f.rowid = l.fk_facture_fourn "; $sql .= " WHERE f.fk_statut > 0 AND l.rowid = ".((int) $id); diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 392551708de..c1a3ffe23a6 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "other", "main", "accountancy")); +$langs->loadLangs(array("compta", "bills", "other", "accountancy")); // Security check if (empty($conf->accounting->enabled)) { @@ -118,13 +118,13 @@ if ($action == 'validatehistory') { $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; $sql1 .= " FROM " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facture_fourn_det.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . $conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facture_fourn_det.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_buy=accnt.account_number"; $sql1 .= " AND " . MAIN_DB_PREFIX . "facture_fourn_det.fk_code_ventilation = 0"; } else { $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det as fd, " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . $conf->global->CHARTOFACCOUNTS.' AND accnt.entity = '.$conf->entity; + $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_buy=accnt.account_number"; $sql1 .= " AND fd.fk_code_ventilation = 0"; }*/ @@ -132,20 +132,35 @@ if ($action == 'validatehistory') { // Supplier Invoice Lines (must be same request than into page list.php for manual binding) $sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_label, f.datef, f.type as ftype,"; $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; - $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type,"; - $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export, p.tva_tx as tva_tx_prod,"; + $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " ppe.accountancy_code_buy as code_buy, ppe.accountancy_code_buy_intra as code_buy_intra, ppe.accountancy_code_buy_export as code_buy_export,"; + } else { + $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; + } $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; - $sql .= " s.tva_intra, s.accountancy_code_buy as company_code_buy"; + $sql .= " s.tva_intra,"; + if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { + $sql .= " spe.accountancy_code_buy as company_code_buy"; + } else { + $sql .= " s.accountancy_code_buy as company_code_buy"; + } + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn_det as l ON f.rowid = l.fk_facture_fourn"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; - $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 = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; + if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); + } + $alias_societe_perentity = empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED) ? "s" : "spe"; + $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON " . $alias_product_perentity . ".accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; diff --git a/htdocs/accountancy/supplier/lines.php b/htdocs/accountancy/supplier/lines.php index 1f81a5d7e2c..90e7213c8f9 100644 --- a/htdocs/accountancy/supplier/lines.php +++ b/htdocs/accountancy/supplier/lines.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013-2020 Alexandre Spangaro + * Copyright (C) 2013-2021 Alexandre Spangaro * Copyright (C) 2014-2015 Ari Elbaz (elarifr) * Copyright (C) 2013-2016 Florian Henry * Copyright (C) 2014 Juanjo Menent @@ -54,9 +54,14 @@ $search_desc = GETPOST('search_desc', 'alpha'); $search_amount = GETPOST('search_amount', 'alpha'); $search_account = GETPOST('search_account', 'alpha'); $search_vat = GETPOST('search_vat', 'alpha'); -$search_day = GETPOST("search_day", "int"); -$search_month = GETPOST("search_month", "int"); -$search_year = GETPOST("search_year", "int"); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); @@ -94,6 +99,9 @@ if (empty($user->rights->accounting->mouvements->lire)) { } +$formaccounting = new FormAccounting($db); + + /* * Actions */ @@ -109,14 +117,19 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_amount = ''; $search_account = ''; $search_vat = ''; - $search_day = ''; - $search_month = ''; - $search_year = ''; + $search_date_startday = ''; + $search_date_startmonth = ''; + $search_date_startyear = ''; + $search_date_endday = ''; + $search_date_endmonth = ''; + $search_date_endyear = ''; + $search_date_start = ''; + $search_date_end = ''; $search_country = ''; $search_tvaintra = ''; } -if (is_array($changeaccount) && count($changeaccount) > 0) { +if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->accounting->bind->write) { $error = 0; if (!(GETPOST('account_parent', 'int') >= 0)) { @@ -124,7 +137,6 @@ if (is_array($changeaccount) && count($changeaccount) > 0) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Account")), null, 'errors'); } - if (!$error) { $db->begin(); @@ -184,7 +196,11 @@ $sql = "SELECT f.rowid as facid, f.ref as ref, f.ref_supplier, f.libelle as invo $sql .= " l.rowid, l.fk_product, l.product_type as line_type, l.description, l.total_ht , l.qty, l.tva_tx, l.vat_src_code,"; $sql .= " aa.label, aa.labelshort, aa.account_number,"; $sql .= " p.rowid as product_id, p.fk_product_type as product_type, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tobuy, p.tosell,"; -$sql .= " p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,"; +if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export,"; +} else { + $sql .= " p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,"; +} $sql .= " co.code as country_code, co.label as country,"; $sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur"; $parameters = array(); @@ -192,6 +208,9 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // N $sql .= $hookmanager->resPrint; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as l"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; +if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); +} $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = l.fk_code_ventilation"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn as f ON f.rowid = l.fk_facture_fourn"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; @@ -225,7 +244,12 @@ if (strlen(trim($search_account))) { if (strlen(trim($search_vat))) { $sql .= natural_search("l.tva_tx", price2num($search_vat), 1); } -$sql .= dolSqlDateFilter('f.datef', $search_day, $search_month, $search_year); +if ($search_date_start) { + $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'"; +} +if ($search_date_end) { + $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'"; +} if (strlen(trim($search_country))) { $arrayofcode = getCountriesInEEC(); $country_code_in_EEC = $country_code_in_EEC_without_me = ''; @@ -306,14 +330,23 @@ if ($result) { if ($search_vat) { $param .= "&search_vat=".urlencode($search_vat); } - if ($search_day) { - $param .= '&search_day='.urlencode($search_day); + if ($search_date_startday) { + $param .= '&search_date_startday='.urlencode($search_date_startday); } - if ($search_month) { - $param .= '&search_month='.urlencode($search_month); + if ($search_date_startmonth) { + $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); } - if ($search_year) { - $param .= '&search_year='.urlencode($search_year); + if ($search_date_startyear) { + $param .= '&search_date_startyear='.urlencode($search_date_startyear); + } + if ($search_date_endday) { + $param .= '&search_date_endday='.urlencode($search_date_endday); + } + if ($search_date_endmonth) { + $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); + } + if ($search_date_endyear) { + $param .= '&search_date_endyear='.urlencode($search_date_endyear); } if ($search_country) { $param .= "&search_country=".urlencode($search_country); @@ -350,12 +383,13 @@ if ($result) { print '
'; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print '
'; - if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) { - print ''; - } - print ''; - $formother->select_year($search_year, 'search_year', 1, 20, 5); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print '
'.$objp->tva_intra.''; - $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + print ''; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') { $shelp .= $langs->trans("SaleEEC"); @@ -683,7 +708,7 @@ if ($result) { print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); if ($objp->product_id > 0) { print '
'; - $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountfor == 'eec') { $shelp = $langs->trans("SaleEEC"); @@ -694,13 +719,13 @@ if ($result) { print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } else { print '
'; - $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; $s .= $langs->trans("NotDefined"); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } print '
'; - $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; $shelp = ''; $s .= ($objp->code_buy_t > 0 ? length_accountg($objp->code_buy_t) : ''.$langs->trans("NotDefined").''); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); diff --git a/htdocs/adherents/admin/member.php b/htdocs/adherents/admin/member.php index 62291791fc5..621873afc94 100644 --- a/htdocs/adherents/admin/member.php +++ b/htdocs/adherents/admin/member.php @@ -9,7 +9,6 @@ * Copyright (C) 2012 J. Fernando Lagrange * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2020-2021 Frédéric France - * Copyright (C) 2021 Waël Almoman * * 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 @@ -34,7 +33,6 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; // Load translation files required by the page $langs->loadLangs(array("admin", "members")); @@ -74,12 +72,12 @@ if ($action == 'set_default') { } elseif ($action == 'setdoc') { // Set default model if (dolibarr_set_const($db, "MEMBER_ADDON_PDF_ODT", $value, 'chaine', 0, '', $conf->entity)) { - // La constante qui a ete lue en avant du nouveau set - // on passe donc par une variable pour avoir un affichage coherent + // The constant that was read ahead of the new set + // we therefore go through a variable to have a consistent display $conf->global->MEMBER_ADDON_PDF_ODT = $value; } - // On active le modele + // We activate the model $ret = delDocumentModel($value, $type); if ($ret > 0) { $ret = addDocumentModel($value, $type, $label, $scandir); @@ -107,6 +105,7 @@ if ($action == 'set_default') { $res1 = dolibarr_set_const($db, 'ADHERENT_LOGIN_NOT_REQUIRED', GETPOST('ADHERENT_LOGIN_NOT_REQUIRED', 'alpha') ? 0 : 1, 'chaine', 0, '', $conf->entity); $res2 = dolibarr_set_const($db, 'ADHERENT_MAIL_REQUIRED', GETPOST('ADHERENT_MAIL_REQUIRED', 'alpha'), 'chaine', 0, '', $conf->entity); $res3 = dolibarr_set_const($db, 'ADHERENT_DEFAULT_SENDINFOBYMAIL', GETPOST('ADHERENT_DEFAULT_SENDINFOBYMAIL', 'alpha'), 'chaine', 0, '', $conf->entity); + $res3 = dolibarr_set_const($db, 'ADHERENT_CREATE_EXTERNAL_USER_LOGIN', GETPOST('ADHERENT_CREATE_EXTERNAL_USER_LOGIN', 'alpha'), 'chaine', 0, '', $conf->entity); $res4 = dolibarr_set_const($db, 'ADHERENT_BANK_USE', GETPOST('ADHERENT_BANK_USE', 'alpha'), 'chaine', 0, '', $conf->entity); // Use vat for invoice creation if ($conf->facture->enabled) { @@ -198,6 +197,8 @@ print ''; print ''; print load_fiche_titre($langs->trans("MemberMainOptions"), '', ''); + +print '
'; print ''; print ''; print ''; @@ -219,6 +220,11 @@ print '\n"; +// Create an external user login for each new member subscription validated +print '\n"; + // Insert subscription into bank account print ''; $arraychoices = array('0'=>$langs->trans("None")); @@ -264,6 +270,7 @@ if ($conf->facture->enabled) { } print '
'.$langs->trans("Description").'
'.$langs->trans("MemberSendInformationByMailByDef print $form->selectyesno('ADHERENT_DEFAULT_SENDINFOBYMAIL', (!empty($conf->global->ADHERENT_DEFAULT_SENDINFOBYMAIL) ? $conf->global->ADHERENT_DEFAULT_SENDINFOBYMAIL : 0), 1); print "
'.$langs->trans("MemberCreateAnExternalUserForSubscriptionValidated").''; +print $form->selectyesno('ADHERENT_CREATE_EXTERNAL_USER_LOGIN', (!empty($conf->global->ADHERENT_CREATE_EXTERNAL_USER_LOGIN) ? $conf->global->ADHERENT_CREATE_EXTERNAL_USER_LOGIN : 0), 1); +print "
'.$langs->trans("MoreActionsOnSubscription").'
'; +print '
'; print '
'; print ''; @@ -313,7 +320,7 @@ $helptext .= '__YEAR__, __MONTH__, __DAY__'; form_constantes($constantes, 0, $helptext); $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); -// Defini tableau def des modeles +// Defined model definition table $def = array(); $sql = "SELECT nom"; $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; @@ -334,6 +341,7 @@ if ($resql) { print load_fiche_titre($langs->trans("MembersDocModules"), '', ''); +print '
'; print ''; print ''; print ''; @@ -442,6 +450,8 @@ foreach ($dirmodels as $reldir) { } print '
'.$langs->trans("Name").'
'; +print '
'; + print "
"; print dol_get_fiche_end(); diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php index 4df95e06e52..bb320e9f48a 100644 --- a/htdocs/adherents/admin/website.php +++ b/htdocs/adherents/admin/website.php @@ -39,6 +39,8 @@ if (!$user->admin) { accessforbidden(); } +$error = 0; + /* * Actions @@ -57,7 +59,8 @@ if ($action == 'update') { $amount = GETPOST('MEMBER_NEWFORM_AMOUNT'); $editamount = GETPOST('MEMBER_NEWFORM_EDITAMOUNT'); $payonline = GETPOST('MEMBER_NEWFORM_PAYONLINE'); - $forcetype = GETPOST('MEMBER_NEWFORM_FORCETYPE'); + $forcetype = GETPOST('MEMBER_NEWFORM_FORCETYPE', 'int'); + $forcemorphy = GETPOST('MEMBER_NEWFORM_FORCEMORPHY', 'aZ09'); $res = dolibarr_set_const($db, "MEMBER_ENABLE_PUBLIC", $public, 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "MEMBER_NEWFORM_AMOUNT", $amount, 'chaine', 0, '', $conf->entity); @@ -68,6 +71,11 @@ if ($action == 'update') { } else { $res = dolibarr_set_const($db, "MEMBER_NEWFORM_FORCETYPE", $forcetype, 'chaine', 0, '', $conf->entity); } + if ($forcemorphy == '-1') { + $res = dolibarr_del_const($db, "MEMBER_NEWFORM_FORCEMORPHY", $conf->entity); + } else { + $res = dolibarr_set_const($db, "MEMBER_NEWFORM_FORCEMORPHY", $forcemorphy, 'chaine', 0, '', $conf->entity); + } if (!($res > 0)) { $error++; @@ -164,6 +172,7 @@ print '
'; if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { print '
'; + print '
'; print ''; print ''; @@ -182,6 +191,16 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { print $form->selectarray("MEMBER_NEWFORM_FORCETYPE", $listofval, $forcetype, count($listofval) > 1 ? 1 : 0); print "\n"; + // Force nature of member (mor/phy) + $morphys["phy"] = $langs->trans("Physical"); + $morphys["mor"] = $langs->trans("Moral"); + print '\n"; + // Amount print '\n"; print '
'; + print $langs->trans("ForceMemberNature"); + print ''; + $forcenature = empty($conf->global->MEMBER_NEWFORM_FORCEMORPHY) ? 0 : $conf->global->MEMBER_NEWFORM_FORCEMORPHY; + print $form->selectarray("MEMBER_NEWFORM_FORCEMORPHY", $morphys, $forcenature, 1); + print "
'; print $langs->trans("DefaultAmount"); @@ -216,6 +235,7 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { print "
'; + print '
'; print '
'; print ''; @@ -244,7 +264,7 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current print ''; print ajax_autoselect('publicurlmember'); diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 9b28cc6473e..d20318090e0 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -6,7 +6,7 @@ * Copyright (C) 2012 Marcos García * Copyright (C) 2012-2020 Philippe Grand * Copyright (C) 2015-2018 Alexandre Spangaro - * Copyright (C) 2018-2020 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * Copyright (C) 2021 Waël Almoman * * This program is free software; you can redistribute it and/or modify @@ -284,6 +284,7 @@ if (empty($reshook)) { $object->phone_perso = trim(GETPOST("phone_perso", 'alpha')); $object->phone_mobile = trim(GETPOST("phone_mobile", 'alpha')); $object->email = preg_replace('/\s+/', '', GETPOST("member_email", 'alpha')); + $object->url = trim(GETPOST('member_url', 'custom', 0, FILTER_SANITIZE_URL)); $object->socialnetworks = array(); foreach ($socialnetworks as $key => $value) { if (GETPOSTISSET($key) && GETPOST($key, 'alphanohtml') != '') { @@ -431,6 +432,7 @@ if (empty($reshook)) { // $facebook=GETPOST("member_facebook", 'alpha'); // $linkedin=GETPOST("member_linkedin", 'alpha'); $email = preg_replace('/\s+/', '', GETPOST("member_email", 'alpha')); + $url = trim(GETPOST('url', 'custom', 0, FILTER_SANITIZE_URL)); $login = GETPOST("member_login", 'alphanohtml'); $pass = GETPOST("password", 'alpha'); $photo = GETPOST("photo", 'alpha'); @@ -469,6 +471,7 @@ if (empty($reshook)) { // $object->linkedin = $linkedin; $object->email = $email; + $object->url = $url; $object->login = $login; $object->pass = $pass; $object->birth = $birthdate; @@ -537,6 +540,10 @@ if (empty($reshook)) { $langs->load("errors"); setEventMessages($langs->trans("ErrorBadEMail", $email), null, 'errors'); } + if (!empty($object->url) && !isValidUrl($object->url)) { + $langs->load("errors"); + setEventMessages('', $langs->trans("ErrorBadUrl", $object->url), 'errors'); + } $public = 0; if (isset($public)) { $public = 1; @@ -937,17 +944,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { document.formsoc.action.value="create"; document.formsoc.submit(); }); - function initfieldrequired() - { + function initfieldrequired() { jQuery("#tdcompany").removeClass("fieldrequired"); jQuery("#tdlastname").removeClass("fieldrequired"); jQuery("#tdfirstname").removeClass("fieldrequired"); - if (jQuery("#morphy").val() == \'mor\') - { + if (jQuery("#morphy").val() == \'mor\') { jQuery("#tdcompany").addClass("fieldrequired"); } - if (jQuery("#morphy").val() == \'phy\') - { + if (jQuery("#morphy").val() == \'phy\') { jQuery("#tdlastname").addClass("fieldrequired"); jQuery("#tdfirstname").addClass("fieldrequired"); } @@ -1031,6 +1035,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
'.($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').''.img_picto('', 'object_email').'
'.$form->editfieldkey('Web', 'member_url', '', $object, 0).''.img_picto('', 'globe').'
'.$langs->trans("Address").''; print ''; @@ -1080,7 +1088,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if (!$value['active']) { break; } - print '
'.$langs->trans($value['label']).'
'.$langs->trans($value['label']).'
'.($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').''.img_picto('', 'object_email').' email).'">
'.$form->editfieldkey('Web', 'member_url', GETPOST('member_url', 'alpha'), $object, 0).''.img_picto('', 'globe').'
'.$langs->trans("Address").''; print ''; @@ -1747,12 +1757,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print $langs->trans("SubscriptionNotNeeded"); } elseif (!$adht->subscription) { print $langs->trans("SubscriptionNotRecorded"); - if ($object->statut > 0) { + if (Adherent::STATUS_VALIDATED == $object->statut) { print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft, not excluded and not resiliated } } else { print $langs->trans("SubscriptionNotReceived"); - if ($object->statut > 0) { + if (Adherent::STATUS_VALIDATED == $object->statut) { print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft, not excluded and not resiliated } } @@ -1797,7 +1807,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; print ''; print ''; - print ''; + print '
'; print ''; @@ -1862,97 +1872,91 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if ($action != 'editlogin' && $action != 'editthirdparty') { // Send if (empty($user->socid)) { - if ($object->statut == 1) { - print ''."\n"; + if (Adherent::STATUS_VALIDATED == $object->statut) { + print ''.$langs->trans('SendMail').''."\n"; } } // Send card by email // TODO Remove this to replace with a template /* - if ($user->rights->adherent->creer) - { - if ($object->statut >= 1) - { - if ($object->email) print '\n"; - else print '\n"; + if ($user->rights->adherent->creer) { + if (Adherent::STATUS_VALIDATED == $object->statut) { + if ($object->email) print ''.$langs->trans("SendCardByMail")."\n"; + else print ''.$langs->trans("SendCardByMail")."\n"; + } else { + print ''.$langs->trans("SendCardByMail").""; } - else - { - print '
'.$langs->trans("SendCardByMail")."
"; - } - } - else - { - print '
'.$langs->trans("SendCardByMail")."
"; + } else { + print ''.$langs->trans("SendCardByMail").""; }*/ // Modify - if ($user->rights->adherent->creer) { - print ''."\n"; + if (!empty($user->rights->adherent->creer)) { + print ''.$langs->trans("Modify").''."\n"; } else { - print '
'.$langs->trans("Modify").'
'."\n"; + print ''.$langs->trans("Modify").''."\n"; } // Validate - if ($object->statut == -1) { + if (Adherent::STATUS_DRAFT == $object->statut) { if ($user->rights->adherent->creer) { - print ''."\n"; + print ''.$langs->trans("Validate").''."\n"; } else { - print '
'.$langs->trans("Validate").'
'."\n"; + print ''.$langs->trans("Validate").''."\n"; } } // Reactivate - if ($object->statut == 0 || $object->statut == -2) { + if (Adherent::STATUS_RESILIATED == $object->statut || Adherent::STATUS_EXCLUDED == $object->statut) { if ($user->rights->adherent->creer) { - print '\n"; + print ''.$langs->trans("Reenable")."\n"; } else { - print '
'.$langs->trans("Reenable").'
'."\n"; + print ''.$langs->trans("Reenable").''."\n"; } } // Resiliate - if ($object->statut >= 1) { + if (Adherent::STATUS_VALIDATED == $object->statut) { if ($user->rights->adherent->supprimer) { - print '\n"; + print ''.$langs->trans("Resiliate")."\n"; } else { - print '
'.$langs->trans("Resiliate").'
'."\n"; + print ''.$langs->trans("Resiliate").''."\n"; } } // Exclude - if ($object->statut >= 1) { + if (Adherent::STATUS_VALIDATED == $object->statut) { if ($user->rights->adherent->supprimer) { - print '\n"; + print ''.$langs->trans("Exclude")."\n"; } else { - print '
'.$langs->trans("Exclude").'
'."\n"; + print ''.$langs->trans("Exclude").''."\n"; } } // Create third party if (!empty($conf->societe->enabled) && !$object->socid) { if ($user->rights->societe->creer) { - if ($object->statut != -1) { - print ''."\n";; + if (Adherent::STATUS_DRAFT != $object->statut) { + print ''.$langs->trans("CreateDolibarrThirdParty").''."\n";; } else { - print ''."\n"; + print ''.$langs->trans("CreateDolibarrThirdParty").''."\n"; } } else { - print '
'.$langs->trans("CreateDolibarrThirdParty").'
'."\n"; + print ''.$langs->trans("CreateDolibarrThirdParty").''."\n"; } } // Create user if (!$user->socid && !$object->user_id) { if ($user->rights->user->user->creer) { - if ($object->statut != -1) { - print ''."\n"; + if (Adherent::STATUS_DRAFT != $object->statut) { + print ''.$langs->trans("CreateDolibarrLogin").''."\n"; } else { - print ''."\n"; + print ''.$langs->trans("CreateDolibarrLogin").''."\n"; } } else { - print '
'.$langs->trans("CreateDolibarrLogin").'
'."\n"; + print ''.$langs->trans("CreateDolibarrLogin").''."\n"; } } @@ -1961,18 +1965,18 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $isinspip = $mailmanspip->is_in_spip($object); if ($isinspip == 1) { - print ''."\n"; + print ''.$langs->trans("DeleteIntoSpip").''."\n"; } if ($isinspip == 0) { - print ''."\n"; + print ''.$langs->trans("AddIntoSpip").''."\n"; } } // Delete if ($user->rights->adherent->supprimer) { - print ''."\n"; + print ''.$langs->trans("Delete").''."\n"; } else { - print '
'.$langs->trans("Delete").'
'."\n"; + print ''.$langs->trans("Delete").''."\n"; } } } @@ -2010,7 +2014,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Show links to link elements /*$linktoelem = $form->showLinkToObjectBlock($object,array('order')); - if ($linktoelem) print ($somethingshown?'':'
').$linktoelem; + if ($linktoelem) { + print ($somethingshown?'':'
').$linktoelem; + } */ // Show online payment link diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 0299b32663c..2d5eae90938 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -44,7 +44,6 @@ require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; */ class Adherent extends CommonObject { - /** * @var string ID to identify managed object */ @@ -141,6 +140,11 @@ class Adherent extends CommonObject */ public $email; + /** + * @var string url + */ + public $url; + /** * @var array array of socialnetworks */ @@ -205,12 +209,11 @@ class Adherent extends CommonObject */ public $morphy; + /** + * @var int Info can be public + */ public $public; - // -2:exclu, -1:brouillon, 0:resilie, >=1:valide,paye - // def in common object - //public $status; - /** * @var string photo of member */ @@ -257,9 +260,9 @@ class Adherent extends CommonObject public $datefin; - // From member table - // Fields loaded by fetch_subscriptions() + // Fields loaded by fetch_subscriptions() from member table + public $first_subscription_date; public $first_subscription_amount; @@ -274,6 +277,12 @@ class Adherent extends CommonObject public $subscriptions = array(); + + // Fields loaded by fetchPartnerships() from partnership table + + public $partnerships = array(); + + /** * @var Adherent To contains a clone of this when we need to save old properties of object */ @@ -293,15 +302,15 @@ class Adherent extends CommonObject 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1), 'ref_ext' => array('type' => 'varchar(128)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 0, 'position' => 20), 'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => -1, 'position' => 25), - 'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => -1, 'position' => 30), - 'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => -1, 'position' => 35), + 'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => -1, 'position' => 30, 'showoncombobox'=>1), + 'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => -1, 'position' => 35, 'showoncombobox'=>1), 'login' => array('type' => 'varchar(50)', 'label' => 'Login', 'enabled' => 1, 'visible' => -1, 'position' => 40), 'gender' => array('type' => 'varchar(10)', 'label' => 'Gender', 'enabled' => 1, 'visible' => -1, 'position' => 250), 'pass' => array('type' => 'varchar(50)', 'label' => 'Pass', 'enabled' => 1, 'visible' => -1, 'position' => 45), 'pass_crypted' => array('type' => 'varchar(128)', 'label' => 'Pass crypted', 'enabled' => 1, 'visible' => -1, 'position' => 50), 'fk_adherent_type' => array('type' => 'integer', 'label' => 'Fk adherent type', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 55), 'morphy' => array('type' => 'varchar(3)', 'label' => 'MorPhy', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 60), - 'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => -1, 'position' => 65), + 'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'showoncombobox'=>2), 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => -1, 'position' => 70), 'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75), 'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80), @@ -309,6 +318,7 @@ class Adherent extends CommonObject 'state_id' => array('type' => 'integer', 'label' => 'State id', 'enabled' => 1, 'visible' => -1, 'position' => 90), 'country' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'position' => 95), 'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => -1, 'position' => 100), + 'url' =>array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>1, 'visible'=>-1, 'position'=>110), 'socialnetworks' => array('type' => 'text', 'label' => 'Socialnetworks', 'enabled' => 1, 'visible' => -1, 'position' => 105), 'phone' => array('type' => 'varchar(30)', 'label' => 'Phone', 'enabled' => 1, 'visible' => -1, 'position' => 115), 'phone_perso' => array('type' => 'varchar(30)', 'label' => 'Phone perso', 'enabled' => 1, 'visible' => -1, 'position' => 120), @@ -327,11 +337,28 @@ class Adherent extends CommonObject 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 190), 'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => -1, 'position' => 195), 'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500, - 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', -1 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort')), + 'arrayofkeyval' => array(-1 => 'Draft', 1 => 'Validated', 0 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort')), 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800), 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805) ); + /** + * Draft status + */ + const STATUS_DRAFT = -1; + /** + * Validated status + */ + const STATUS_VALIDATED = 1; + /** + * Resiliated + */ + const STATUS_RESILIATED = 0; + /** + * Excluded + */ + const STATUS_EXCLUDED = -2; + /** * Constructor @@ -341,7 +368,8 @@ class Adherent extends CommonObject public function __construct($db) { $this->db = $db; - $this->statut = -1; + $this->statut = self::STATUS_DRAFT; + $this->status = $this->statut; // l'adherent n'est pas public par defaut $this->public = 0; // les champs optionnels sont vides @@ -570,8 +598,8 @@ class Adherent extends CommonObject if ($this->user_id) { // Add link to user $sql = "UPDATE ".MAIN_DB_PREFIX."user SET"; - $sql .= " fk_member = ".$this->id; - $sql .= " WHERE rowid = ".$this->user_id; + $sql .= " fk_member = ".((int) $this->id); + $sql .= " WHERE rowid = ".((int) $this->user_id); dol_syslog(get_class($this)."::create", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { @@ -645,6 +673,7 @@ class Adherent extends CommonObject $this->setUpperOrLowerCase(); $this->note_public = ($this->note_public ? $this->note_public : $this->note_public); $this->note_private = ($this->note_private ? $this->note_private : $this->note_private); + $this->url = $this->url ?clean_url($this->url, 0) : ''; // Check parameters if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) { @@ -670,6 +699,7 @@ class Adherent extends CommonObject $sql .= ", country = ".($this->country_id > 0 ? $this->db->escape($this->country_id) : "null"); $sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null"); $sql .= ", email = '".$this->db->escape($this->email)."'"; + $sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null"); $sql .= ", socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'"; $sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null"); $sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null"); @@ -698,7 +728,7 @@ class Adherent extends CommonObject if (!empty($this->oldcopy) && $this->typeid != $this->oldcopy->typeid) { $sql2 = "SELECT libelle as label"; $sql2 .= " FROM ".MAIN_DB_PREFIX."adherent_type"; - $sql2 .= " WHERE rowid = ".$this->typeid; + $sql2 .= " WHERE rowid = ".((int) $this->typeid); $resql2 = $this->db->query($sql2); if ($resql2) { while ($obj = $this->db->fetch_object($resql2)) { @@ -1282,7 +1312,7 @@ class Adherent extends CommonObject $sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,"; $sql .= " d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,"; $sql .= " d.note_public,"; - $sql .= " d.email, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,"; + $sql .= " d.email, d.url, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,"; $sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,"; $sql .= " d.datec as datec,"; $sql .= " d.tms as datem,"; @@ -1361,6 +1391,7 @@ class Adherent extends CommonObject $this->phone_perso = $obj->phone_perso; $this->phone_mobile = $obj->phone_mobile; $this->email = $obj->email; + $this->url = $obj->url; $this->socialnetworks = (array) json_decode($obj->socialnetworks, true); @@ -1414,11 +1445,12 @@ class Adherent extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Function to get member subscriptions data - * first_subscription_date, first_subscription_date_start, first_subscription_date_end, first_subscription_amount - * last_subscription_date, last_subscription_date_start, last_subscription_date_end, last_subscription_amount + * Function to get member subscriptions data: + * subscriptions, + * first_subscription_date, first_subscription_date_start, first_subscription_date_end, first_subscription_amount + * last_subscription_date, last_subscription_date_start, last_subscription_date_end, last_subscription_amount * - * @return int <0 si KO, >0 si OK + * @return int <0 if KO, >0 if OK */ public function fetch_subscriptions() { @@ -1450,7 +1482,7 @@ class Adherent extends CommonObject $this->first_subscription_amount = $obj->subscription; } $this->last_subscription_date = $this->db->jdate($obj->datec); - $this->last_subscription_date_start = $this->db->jdate($obj->datef); + $this->last_subscription_date_start = $this->db->jdate($obj->dateh); $this->last_subscription_date_end = $this->db->jdate($obj->datef); $this->last_subscription_amount = $obj->subscription; @@ -1478,6 +1510,25 @@ class Adherent extends CommonObject } + /** + * Function to get partnerships array + * + * @param string $mode 'member' or 'thirdparty' + * @return int <0 if KO, >0 if OK + */ + public function fetchPartnerships($mode) + { + global $langs; + + require_once DOL_DOCUMENT_ROOT.'/parntership/class/partnership.class.php'; + + + $this->partnerships[] = array(); + + return 1; + } + + /** * Insert subscription into database and eventually add links to banks, mailman, etc... * @@ -1570,9 +1621,11 @@ class Adherent extends CommonObject * @param string $emetteur_nom Name of cheque writer * @param string $emetteur_banque Name of bank of cheque * @param string $autocreatethirdparty Auto create new thirdparty if member not yet linked to a thirdparty and we request an option that generate invoice. + * @param string $ext_payment_id External id of payment (for example Stripe charge id) + * @param string $ext_payment_site Name of external paymentmode (for example 'stripe') * @return int <0 if KO, >0 if OK */ - public function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom = '', $emetteur_banque = '', $autocreatethirdparty = 0) + public function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom = '', $emetteur_banque = '', $autocreatethirdparty = 0, $ext_payment_id = '', $ext_payment_site = '') { global $conf, $langs, $user, $mysoc; @@ -1597,8 +1650,8 @@ class Adherent extends CommonObject $inserturlid = $acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullname($langs), 'member'); if ($inserturlid > 0) { // Update table subscription - $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".$insertid; - $sql .= " WHERE rowid=".$subscriptionid; + $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".((int) $insertid); + $sql .= " WHERE rowid=".((int) $subscriptionid); dol_syslog("subscription::subscription", LOG_DEBUG); $resql = $this->db->query($sql); @@ -1685,7 +1738,8 @@ class Adherent extends CommonObject } } $invoice->socid = $this->fk_soc; - $invoice->date = $datesubscription; + //$invoice->date = $datesubscription; + $invoice->date = dol_now(); // Possibility to add external linked objects with hooks $invoice->linked_objects['subscription'] = $subscriptionid; @@ -1752,6 +1806,8 @@ class Adherent extends CommonObject $paiement->paiementid = dol_getIdFromCode($this->db, $operation, 'c_paiement', 'code', 'id', 1); $paiement->num_payment = $num_chq; $paiement->note_public = $label; + $paiement->ext_payment_id = $ext_payment_id; + $paiement->ext_payment_site = $ext_payment_site; if (!$error) { // Create payment line for invoice @@ -1834,7 +1890,7 @@ class Adherent extends CommonObject $now = dol_now(); // Check parameters - if ($this->statut == 1) { + if ($this->statut == self::STATUS_VALIDATED) { dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING); return 0; } @@ -1842,7 +1898,7 @@ class Adherent extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET"; - $sql .= " statut = 1"; + $sql .= " statut = ".self::STATUS_VALIDATED; $sql .= ", datevalid = '".$this->db->idate($now)."'"; $sql .= ", fk_user_valid=".$user->id; $sql .= " WHERE rowid = ".$this->id; @@ -1850,7 +1906,7 @@ class Adherent extends CommonObject dol_syslog(get_class($this)."::validate", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { - $this->statut = 1; + $this->statut = self::STATUS_VALIDATED; // Call trigger $result = $this->call_trigger('MEMBER_VALIDATE', $user); @@ -1886,7 +1942,7 @@ class Adherent extends CommonObject $error = 0; // Check parameters - if ($this->statut == 0) { + if ($this->statut == self::STATUS_RESILIATED) { dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING); return 0; } @@ -1894,13 +1950,13 @@ class Adherent extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET"; - $sql .= " statut = 0"; + $sql .= " statut = ".self::STATUS_RESILIATED; $sql .= ", fk_user_valid=".$user->id; $sql .= " WHERE rowid = ".$this->id; $result = $this->db->query($sql); if ($result) { - $this->statut = 0; + $this->statut = self::STATUS_RESILIATED; // Call trigger $result = $this->call_trigger('MEMBER_RESILIATE', $user); @@ -1936,7 +1992,7 @@ class Adherent extends CommonObject $error = 0; // Check parameters - if ($this->statut == 0) { + if ($this->statut == self::STATUS_EXCLUDED) { dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING); return 0; } @@ -1944,13 +2000,13 @@ class Adherent extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET"; - $sql .= " statut = -2"; + $sql .= " statut = ".self::STATUS_EXCLUDED; $sql .= ", fk_user_valid=".$user->id; $sql .= " WHERE rowid = ".$this->id; $result = $this->db->query($sql); if ($result) { - $this->statut = 0; + $this->statut = self::STATUS_EXCLUDED; // Call trigger $result = $this->call_trigger('MEMBER_EXCLUDE', $user); @@ -2255,11 +2311,11 @@ class Adherent extends CommonObject $labelStatus = ''; $labelStatusShort = ''; - if ($status == -1) { + if ($status == self::STATUS_DRAFT) { $statusType = 'status0'; $labelStatus = $langs->trans("MemberStatusDraft"); $labelStatusShort = $langs->trans("MemberStatusDraftShort"); - } elseif ($status >= 1) { + } elseif ($status >= self::STATUS_VALIDATED) { if ($need_subscription == 0) { $statusType = 'status4'; $labelStatus = $langs->trans("MemberStatusNoSubscription"); @@ -2277,11 +2333,11 @@ class Adherent extends CommonObject $labelStatus = $langs->trans("MemberStatusPaid"); $labelStatusShort = $langs->trans("MemberStatusPaidShort"); } - } elseif ($status == 0) { + } elseif ($status == self::STATUS_RESILIATED) { $statusType = 'status6'; $labelStatus = $langs->trans("MemberStatusResiliated"); $labelStatusShort = $langs->trans("MemberStatusResiliatedShort"); - } elseif ($status == -2) { + } elseif ($status == self::STATUS_EXCLUDED) { $statusType = 'status10'; $labelStatus = $langs->trans("MemberStatusExcluded"); $labelStatusShort = $langs->trans("MemberStatusExcludedShort"); @@ -2347,11 +2403,11 @@ class Adherent extends CommonObject $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t"; $sql .= " WHERE a.fk_adherent_type = t.rowid"; if ($mode == 'expired') { - $sql .= " AND a.statut = 1"; + $sql .= " AND a.statut = ".self::STATUS_VALIDATED; $sql .= " AND a.entity IN (".getEntity('adherent').")"; $sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')"; } elseif ($mode == 'shift') { - $sql .= " AND a.statut = -1"; + $sql .= " AND a.statut = ".self::STATUS_DRAFT; $sql .= " AND a.entity IN (".getEntity('adherent').")"; } @@ -2368,10 +2424,10 @@ class Adherent extends CommonObject $warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24; $label = $langs->trans("MembersWithSubscriptionToReceive"); $labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort"); - $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=1&filter=outofdate'; + $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut='.self::STATUS_VALIDATED.'&filter=outofdate'; } elseif ($mode == 'shift') { $warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24; - $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=-1'; + $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut='.self::STATUS_DRAFT; $label = $langs->trans("MembersListToValid"); $labelShort = $langs->trans("ToValidate"); } @@ -2484,7 +2540,7 @@ class Adherent extends CommonObject $this->birth = $now; $this->photo = ''; $this->public = 1; - $this->statut = 0; + $this->statut = self::STATUS_DRAFT; $this->datefin = $now; $this->datevalid = $now; @@ -2803,7 +2859,7 @@ class Adherent extends CommonObject global $conf; //Only valid members - if ($this->statut <= 0) { + if ($this->statut != self::STATUS_VALIDATED) { return false; } if (!$this->datefin) { diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index b2f181e59be..1cb9fcdb12c 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -4,7 +4,7 @@ * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2016 Charlie Benke * Copyright (C) 2018-2019 Thibault Foucart - * Copyright (C) 2021 Waël Almoman + * Copyright (C) 2021 Waël Almoman * * 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 +89,11 @@ class AdherentType extends CommonObject */ public $subscription; + /** + * @var float amount for subscription + */ + public $amount; + /** @var string Public note */ public $note; @@ -357,15 +362,16 @@ class AdherentType extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."adherent_type "; $sql .= "SET "; - $sql .= "statut = ".$this->status.","; + $sql .= "statut = ".((int) $this->status).","; $sql .= "libelle = '".$this->db->escape($this->label)."',"; $sql .= "morphy = '".$this->db->escape($this->morphy)."',"; $sql .= "subscription = '".$this->db->escape($this->subscription)."',"; + $sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? 'null' : ((float) $this->amount)).","; $sql .= "duration = '".$this->db->escape($this->duration_value.$this->duration_unit)."',"; $sql .= "note = '".$this->db->escape($this->note)."',"; $sql .= "vote = ".(integer) $this->db->escape($this->vote).","; $sql .= "mail_valid = '".$this->db->escape($this->mail_valid)."'"; - $sql .= " WHERE rowid =".$this->id; + $sql .= " WHERE rowid =".((int) $this->id); $result = $this->db->query($sql); if ($result) { @@ -455,7 +461,7 @@ class AdherentType extends CommonObject { global $langs, $conf; - $sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.mail_valid, d.note, d.vote"; + $sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.mail_valid, d.note, d.vote"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql .= " WHERE d.rowid = ".(int) $rowid; @@ -475,6 +481,7 @@ class AdherentType extends CommonObject $this->duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); $this->duration_unit = substr($obj->duration, -1); $this->subscription = $obj->subscription; + $this->amount = $obj->amount; $this->mail_valid = $obj->mail_valid; $this->note = $obj->note; $this->vote = $obj->vote; @@ -535,6 +542,45 @@ class AdherentType extends CommonObject return $adherenttypes; } + /** + * Return list of amount by type id + * + * @param int $status Filter on status of type + * @return array List of types of members + */ + public function amountByType($status = null) + { + + global $conf, $langs; + + $amountbytype = array(); + + $sql = "SELECT rowid, amount"; + $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type"; + $sql .= " WHERE entity IN (".getEntity('member_type').")"; + if ($status !== null) { + $sql .= " AND statut = ".((int) $status); + } + + $resql = $this->db->query($sql); + if ($resql) { + $nump = $this->db->num_rows($resql); + + if ($nump) { + $i = 0; + while ($i < $nump) { + $obj = $this->db->fetch_object($resql); + + $amountbytype[$obj->rowid] = $obj->amount; + $i++; + } + } + } else { + print $this->db->error(); + } + return $amountbytype; + } + /** * Return array of Member objects for member type this->id (or all if this->id not defined) * diff --git a/htdocs/adherents/class/api_members.class.php b/htdocs/adherents/class/api_members.class.php index 68d161d0cf1..d57a01510d4 100644 --- a/htdocs/adherents/class/api_members.class.php +++ b/htdocs/adherents/class/api_members.class.php @@ -228,19 +228,19 @@ class Members extends DolibarrApi } $sql .= ' WHERE t.entity IN ('.getEntity('adherent').')'; if (!empty($typeid)) { - $sql .= ' AND t.fk_adherent_type='.$typeid; + $sql .= ' AND t.fk_adherent_type='.((int) $typeid); } // Select members of given category if ($category > 0) { - $sql .= " AND c.fk_categorie = ".$this->db->escape($category); - $sql .= " AND c.fk_member = t.rowid "; + $sql .= " AND c.fk_categorie = ".((int) $category); + $sql .= " AND c.fk_member = t.rowid"; } // Add sql filters if ($sqlfilters) { if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index 5ab9ad8eead..b02a81dc5c9 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -105,7 +105,7 @@ class MembersTypes extends DolibarrApi if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } diff --git a/htdocs/adherents/class/api_subscriptions.class.php b/htdocs/adherents/class/api_subscriptions.class.php index 3758885c4a3..831be2882f1 100644 --- a/htdocs/adherents/class/api_subscriptions.class.php +++ b/htdocs/adherents/class/api_subscriptions.class.php @@ -103,7 +103,7 @@ class Subscriptions extends DolibarrApi if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index 65b01991100..bb5cdd20bd5 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -165,7 +165,7 @@ class Subscription extends CommonObject } else { $type = $this->fk_type; } - $sql .= " VALUES (".$this->fk_adherent.", '".$this->db->escape($type)."', '".$this->db->idate($now)."',"; + $sql .= " VALUES (".((int) $this->fk_adherent).", '".$this->db->escape($type)."', '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->dateh)."',"; $sql .= " '".$this->db->idate($this->datef)."',"; $sql .= " ".$this->amount.","; @@ -217,7 +217,7 @@ class Subscription extends CommonObject $sql .= " datef,"; $sql .= " subscription, note, fk_bank"; $sql .= " FROM ".MAIN_DB_PREFIX."subscription"; - $sql .= " WHERE rowid=".$rowid; + $sql .= " WHERE rowid=".((int) $rowid); dol_syslog(get_class($this)."::fetch", LOG_DEBUG); $resql = $this->db->query($sql); @@ -267,14 +267,14 @@ class Subscription extends CommonObject } $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET "; - $sql .= " fk_type = ".$this->fk_type.","; - $sql .= " fk_adherent = ".$this->fk_adherent.","; + $sql .= " fk_type = ".((int) $this->fk_type).","; + $sql .= " fk_adherent = ".((int) $this->fk_adherent).","; $sql .= " note=".($this->note ? "'".$this->db->escape($this->note)."'" : 'null').","; $sql .= " subscription = ".price2num($this->amount).","; $sql .= " dateadh='".$this->db->idate($this->dateh)."',"; $sql .= " datef='".$this->db->idate($this->datef)."',"; $sql .= " datec='".$this->db->idate($this->datec)."',"; - $sql .= " fk_bank = ".($this->fk_bank ? $this->fk_bank : 'null'); + $sql .= " fk_bank = ".($this->fk_bank ? ((int) $this->fk_bank) : 'null'); $sql .= " WHERE rowid = ".$this->id; dol_syslog(get_class($this)."::update", LOG_DEBUG); @@ -341,7 +341,7 @@ class Subscription extends CommonObject } if (!$error) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE rowid = ".$this->id; + $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { diff --git a/htdocs/adherents/document.php b/htdocs/adherents/document.php index 5150bea861e..98c0e026139 100644 --- a/htdocs/adherents/document.php +++ b/htdocs/adherents/document.php @@ -93,6 +93,8 @@ if ($id) { $caneditfieldmember = $user->rights->adherent->creer; } +$permissiontoadd = $canaddmember; + // Security check $result = restrictedArea($user, 'adherent', $object->id, '', '', 'socid', 'rowid', 0); @@ -180,7 +182,7 @@ if ($id > 0) { print dol_get_fiche_end(); $modulepart = 'member'; - $permission = $user->rights->adherent->creer; + $permissiontoadd = $user->rights->adherent->creer; $permtoedit = $user->rights->adherent->creer; $param = '&id='.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; diff --git a/htdocs/adherents/index.php b/htdocs/adherents/index.php index 998736e137f..8b59c0d3ca4 100644 --- a/htdocs/adherents/index.php +++ b/htdocs/adherents/index.php @@ -52,7 +52,7 @@ $result = restrictedArea($user, 'adherent'); if (GETPOST('addbox')) { // Add box (when submit is done from a form when ajax disabled) require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; - $zone = GETPOST('areacode', 'aZ09'); + $zone = GETPOST('areacode', 'int'); $userid = GETPOST('userid', 'int'); $boxorder = GETPOST('boxorder', 'aZ09'); $boxorder .= GETPOST('boxcombo', 'aZ09'); diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 9560a284e2a..749eacbbe10 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -5,6 +5,7 @@ * Copyright (C) 2013-2015 Raphaël Doursenaud * Copyright (C) 2014-2016 Juanjo Menent * Copyright (C) 2018 Alexandre Spangaro + * Copyright (C) 2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -247,6 +248,42 @@ if (empty($reshook)) { } } + // Create external user + if ($massaction == 'createexternaluser' && $user->rights->adherent->creer && $user->rights->user->user->creer) { + $tmpmember = new Adherent($db); + $error = 0; + $nbcreated = 0; + + $db->begin(); + + foreach ($toselect as $idtoclose) { + $tmpmember->fetch($idtoclose); + + if (!empty($tmpmember->fk_soc)) { + $nuser = new User($db); + $tmpuser = dol_clone($tmpmember); + + $result = $nuser->create_from_member($tmpuser, $tmpmember->login); + + if ($result < 0 && !count($tmpmember->errors)) { + setEventMessages($tmpmember->error, $tmpmember->errors, 'errors'); + } else { + if ($result > 0) { + $nbcreated++; + } + } + } + } + + if (!$error) { + setEventMessages($langs->trans("XExternalUserCreated", $nbcreated), null, 'mesgs'); + + $db->commit(); + } else { + $db->rollback(); + } + } + // Mass actions $objectclass = 'Adherent'; $objectlabel = 'Members'; @@ -269,7 +306,12 @@ $memberstatic = new Adherent($db); $now = dol_now(); -$sql = "SELECT d.rowid, d.ref, d.login, d.lastname, d.firstname, d.gender, d.societe as company, d.fk_soc,"; +if (!empty($search_categ) || !empty($catid)) { + $sql = "SELECT DISTINCT"; +} else { + $sql = "SELECT"; +} +$sql .= " d.rowid, d.ref, d.login, d.lastname, d.firstname, d.gender, d.societe as company, d.fk_soc,"; $sql .= " d.civility, d.datefin, d.address, d.zip, d.town, d.state_id, d.country,"; $sql .= " d.email, d.phone, d.phone_perso, d.phone_mobile, d.skype, d.birth, d.public, d.photo,"; $sql .= " d.fk_adherent_type as type_id, d.morphy, d.statut, d.datec as date_creation, d.tms as date_update,"; @@ -289,7 +331,7 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // N $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); $sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; -if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { +if (!empty($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 (d.rowid = ef.fk_object)"; } if (!empty($search_categ) || !empty($catid)) { @@ -300,7 +342,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = d $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = d.state_id)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on (s.rowid = d.fk_soc)"; $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t"; -$sql .= " WHERE d.fk_adherent_type = t.rowid "; +$sql .= " WHERE d.fk_adherent_type = t.rowid"; if ($catid > 0) { $sql .= " AND cm.fk_categorie = ".((int) $catid); } @@ -318,7 +360,7 @@ if ($sall) { $sql .= natural_search(array_keys($fieldstosearchall), $sall); } if ($search_type > 0) { - $sql .= " AND t.rowid=".$db->escape($search_type); + $sql .= " AND t.rowid=".((int) $search_type); } if ($search_filter == 'withoutsubscription') { $sql .= " AND (datefin IS NULL OR t.subscription = 0)"; @@ -555,6 +597,9 @@ if ($user->rights->adherent->supprimer) { if ($user->rights->societe->creer) { $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } +if ($user->rights->adherent->creer && $user->rights->user->user->creer) { + $arrayofmassactions['createexternaluser'] = img_picto('', 'user', 'class="pictofixedwidth"').$langs->trans("CreateExternalUser"); +} if (in_array($massaction, array('presend', 'predelete','preaffecttag'))) { $arrayofmassactions = array(); } @@ -669,7 +714,7 @@ if (!empty($arrayfields['d.morphy']['checked'])) { if (!empty($arrayfields['t.libelle']['checked'])) { print ''; } @@ -753,8 +798,8 @@ if (!empty($arrayfields['d.statut']['checked'])) { $liststatus = array( '-1'=>$langs->trans("Draft"), '1'=>$langs->trans("Validated"), - '0'=>$langs->trans("Resiliated"), - '-2'=>$langs->trans("Excluded") + '0'=>$langs->trans("MemberStatusResiliatedShort"), + '-2'=>$langs->trans("MemberStatusExcludedShort") ); print $form->selectarray('search_status', $liststatus, $search_status, -3); print ''; @@ -852,6 +897,7 @@ print "\n"; $i = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); @@ -908,7 +954,7 @@ while ($i < min($num, $limit)) { } // Firstname if (!empty($arrayfields['d.firstname']['checked'])) { - print "\n"; if (!$i) { @@ -917,7 +963,7 @@ while ($i < min($num, $limit)) { } // Lastname if (!empty($arrayfields['d.lastname']['checked'])) { - print "\n"; if (!$i) { @@ -937,13 +983,13 @@ while ($i < min($num, $limit)) { } // Company if (!empty($arrayfields['d.company']['checked'])) { - print "\n"; } // Login if (!empty($arrayfields['d.login']['checked'])) { - print "\n"; + print '\n"; if (!$i) { $totalarray['nbfield']++; } @@ -968,7 +1014,7 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['t.libelle']['checked'])) { $membertypestatic->id = $obj->type_id; $membertypestatic->label = $obj->type; - print ''; if (!$i) { @@ -977,7 +1023,7 @@ while ($i < min($num, $limit)) { } // Address if (!empty($arrayfields['d.address']['checked'])) { - print ''; if (!$i) { @@ -1057,13 +1103,13 @@ while ($i < min($num, $limit)) { print ''; } else { print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; $oldyear = $year; } diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 54729e5ba8a..7f8da3a33b3 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -590,7 +590,7 @@ if ($rowid > 0) { print ''; print ''; print ''; - print '
'; print $form->select_company($object->socid, 'socid', '', 1); print ''; $listetype = $membertypestatic->liste_array(); - print $form->selectarray("search_type", $listetype, $type, 1, 0, 0, '', 0, 32); + print $form->selectarray("search_type", $listetype, $search_type, 1, 0, 0, '', 0, 32); print '
"; + print ''; print $obj->firstname; print ""; + print ''; print $obj->lastname; print ""; + print ''; print $companyname; print "".$obj->login."'.$obj->login."'; + print ''; print $membertypestatic->getNomUrl(1, 32); print ''; + print ''; print $obj->address; print ''; print dol_print_date($datefin, 'day'); if ($memberstatic->hasDelay()) { - $textlate .= ' ('.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24) >= 0 ? '+' : '').ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24).' '.$langs->trans("days").')'; + $textlate = ' ('.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24) >= 0 ? '+' : '').ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24).' '.$langs->trans("days").')'; print " ".img_warning($langs->trans("SubscriptionLate").$textlate); } print ''; - if ($obj->subscription == 'yes') { + if (!empty($obj->subscription)) { print $langs->trans("SubscriptionNotReceived"); if ($obj->statut > 0) { print " ".img_warning(); diff --git a/htdocs/adherents/partnership.php b/htdocs/adherents/partnership.php new file mode 100644 index 00000000000..cf0e11d70e0 --- /dev/null +++ b/htdocs/adherents/partnership.php @@ -0,0 +1,294 @@ + + * Copyright (C) 2021 NextGestion + * + * 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 partnership_card.php + * \ingroup partnership + * \brief Page to create/edit/view partnership + */ + +//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 +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +require '../main.inc.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.'/core/lib/member.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; +require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; +require_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php'; +require_once DOL_DOCUMENT_ROOT.'/partnership/lib/partnership.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("companies","members","partnership", "other")); + +// Get parameters +$id = GETPOST('rowid', 'int') ? GETPOST('rowid', 'int') : 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') : 'partnershipcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +//$lineid = GETPOST('lineid', 'int'); + +$object = new Adherent($db); +if ($id > 0) { + $object->fetch($id); +} + +// Initialize technical objects +$object = new Partnership($db); +$extrafields = new ExtraFields($db); +$adht = new AdherentType($db); +$diroutputmassaction = $conf->partnership->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('partnershipthirdparty', '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 = GETPOST("search_all", 'alpha'); +$search = array(); + +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha')) { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } +} + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +$permissiontoread = $user->rights->partnership->read; +$permissiontoadd = $user->rights->partnership->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->partnership->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); +$permissionnote = $user->rights->partnership->write; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->partnership->write; // Used by the include of actions_dellink.inc.php +$usercanclose = $user->rights->partnership->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$upload_dir = $conf->partnership->multidir_output[isset($object->entity) ? $object->entity : 1]; + + +if ($conf->global->PARTNERSHIP_IS_MANAGED_FOR != 'member') accessforbidden(); +if (empty($conf->partnership->enabled)) accessforbidden(); +if (empty($permissiontoread)) accessforbidden(); +if ($action == 'edit' && empty($permissiontoadd)) accessforbidden(); + +if (($action == 'update' || $action == 'edit') && $object->status != $object::STATUS_DRAFT) { + accessforbidden(); +} + + +// Security check +$result = restrictedArea($user, 'adherent', $id, '', '', 'socid', 'rowid', 0); + + +/* + * 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'); +} + +$date_start = dol_mktime(0, 0, 0, GETPOST('date_partnership_startmonth', 'int'), GETPOST('date_partnership_startday', 'int'), GETPOST('date_partnership_startyear', 'int')); +$date_end = dol_mktime(0, 0, 0, GETPOST('date_partnership_endmonth', 'int'), GETPOST('date_partnership_endday', 'int'), GETPOST('date_partnership_endyear', 'int')); + +if (empty($reshook)) { + $error = 0; + + $backtopage = dol_buildpath('/partnership/partnership.php', 1).'?rowid='.($id > 0 ? $id : '__ID__'); + + // Actions when linking object each other + include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; +} + +$object->fields['fk_member']['visible'] = 0; +if ($object->id > 0 && $object->status == $object::STATUS_REFUSED && empty($action)) $object->fields['reason_decline_or_cancel']['visible'] = 1; +$object->fields['note_public']['visible'] = 1; + + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); + +$title = $langs->trans("Partnership"); +llxHeader('', $title); + +$form = new Form($db); + +if ($id > 0) { + $langs->load("members"); + + $object = new Adherent($db); + $result = $object->fetch($id); + + if (!empty($conf->notification->enabled)) { + $langs->load("mails"); + } + + $adht->fetch($object->typeid); + + $head = member_prepare_head($object); + + print dol_get_fiche_head($head, 'partnership', $langs->trans("ThirdParty"), -1, 'user'); + + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'rowid', $linkback); + + print '
'; + + print '
'; + print ''; + + // Login + if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) { + print ''; + } + + // Type + print '\n"; + + // Morphy + print ''; + print ''; + + // Company + print ''; + + // Civility + print ''; + print ''; + + print '
'.$langs->trans("Login").' / '.$langs->trans("Id").''.$object->login.' 
'.$langs->trans("Type").''.$adht->getNomUrl(1)."
'.$langs->trans("MemberNature").''.$object->getmorphylib().'
'.$langs->trans("Company").''.$object->company.'
'.$langs->trans("UserTitle").''.$object->getCivilityLabel().' 
'; + + print '
'; + + print dol_get_fiche_end(); +} else { + dol_print_error('', 'Parameter rowid not defined'); +} + + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + // Buttons for actions + + if ($action != 'presend') { + 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)) { + // Show + if ($permissiontoadd) { + print dolGetButtonAction($langs->trans('AddPartnership'), '', 'default', DOL_URL_ROOT.'/partnership/partnership_card.php?action=create&fk_member='.$object->id.'&backtopage='.urlencode(DOL_URL_ROOT.'/adherents/partnership.php?id='.$object->id), '', $permissiontoadd); + } + } + print '
'."\n"; + } + + + //$morehtmlright = 'partnership/partnership_card.php?action=create&backtopage=%2Fdolibarr%2Fhtdocs%2Fpartnership%2Fpartnership_list.php'; + $morehtmlright = ''; + + print load_fiche_titre($langs->trans("PartnershipDedicatedToThisMember", $langs->transnoentitiesnoconv("Partnership")), $morehtmlright, ''); + + $memberid = $object->id; + + + // TODO Replace this card with the list of all partnerships. + + $object = new Partnership($db); + $partnershipid = $object->fetch(0, "", $memberid); + + if ($partnershipid > 0) { + print '
'; + print '
'; + print '
'; + print ''."\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field + //unset($object->fields['fk_project']); // Hide field already shown in banner + //unset($object->fields['fk_member']); // Hide field already shown in banner + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + // End of subscription date + $fadherent = new Adherent($db); + $fadherent->fetch($object->fk_member); + print ''; + + print '
'.$langs->trans("SubscriptionEndDate").''; + if ($fadherent->datefin) { + print dol_print_date($fadherent->datefin, 'day'); + if ($fadherent->hasDelay()) { + print " ".img_warning($langs->trans("Late")); + } + } else { + if (!$adht->subscription) { + print $langs->trans("SubscriptionNotRecorded"); + if ($fadherent->statut > 0) { + print " ".img_warning($langs->trans("Late")); // Display a delay picto only if it is not a draft and is not canceled + } + } else { + print $langs->trans("SubscriptionNotReceived"); + if ($fadherent->statut > 0) { + print " ".img_warning($langs->trans("Late")); // Display a delay picto only if it is not a draft and is not canceled + } + } + } + print '
'; + print '
'; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/adherents/stats/index.php b/htdocs/adherents/stats/index.php index 11c0025dcc5..e820d0a0d23 100644 --- a/htdocs/adherents/stats/index.php +++ b/htdocs/adherents/stats/index.php @@ -198,8 +198,8 @@ foreach ($data as $val) { //print ''; print '
'.$val['nb'].''.price(price2num($val['total'], 'MT'), 1).''.price(price2num($val['avg'], 'MT'), 1).''.price(price2num($val['total'], 'MT'), 1).''.price(price2num($val['avg'], 'MT'), 1).'
'; + print '
'; print ''; @@ -677,7 +677,7 @@ if ($rowid > 0) { $sql .= " FROM ".MAIN_DB_PREFIX."adherent as d, ".MAIN_DB_PREFIX."subscription as c"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank as b ON c.fk_bank = b.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON b.fk_account = ba.rowid"; - $sql .= " WHERE d.rowid = c.fk_adherent AND d.rowid=".$rowid; + $sql .= " WHERE d.rowid = c.fk_adherent AND d.rowid=".((int) $rowid); $sql .= $db->order($sortfield, $sortorder); $result = $db->query($sql); diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 7322f92fccd..d3d84cb3624 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -170,7 +170,7 @@ if (isset($date_select) && $date_select != '') { } if ($search_ref) { if (is_numeric($search_ref)) { - $sql .= " AND (c.rowid = ".$db->escape($search_ref).")"; + $sql .= " AND c.rowid = ".((int) $search_ref); } else { $sql .= " AND 1 = 2"; // Always wrong } @@ -477,6 +477,7 @@ print "\n"; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < min($num, $limit)) { $obj = $db->fetch_object($result); @@ -527,7 +528,7 @@ while ($i < min($num, $limit)) { // Lastname if (!empty($arrayfields['d.lastname']['checked'])) { - print ''; + print ''; if (!$i) { $totalarray['nbfield']++; } @@ -550,7 +551,7 @@ while ($i < min($num, $limit)) { // Label if (!empty($arrayfields['t.libelle']['checked'])) { - print ''; if (!$i) { diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 25c44baa7db..033592a9afc 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -7,6 +7,7 @@ * Copyright (C) 2015 Alexandre Spangaro * Copyright (C) 2019 Thibault Foucart * Copyright (C) 2020 Josep Lluís Amador + * Copyright (C) 2021 Waël Almoman * * 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 @@ -70,6 +71,7 @@ $label = GETPOST("label", "alpha"); $morphy = GETPOST("morphy", "alpha"); $status = GETPOST("status", "int"); $subscription = GETPOST("subscription", "int"); +$amount = GETPOST('amount', 'alpha'); $duration_value = GETPOST('duration_value', 'int'); $duration_unit = GETPOST('duration_unit', 'alpha'); $vote = GETPOST("vote", "int"); @@ -114,14 +116,15 @@ if ($cancel) { if ($action == 'add' && $user->rights->adherent->configurer) { $object->label = trim($label); - $object->morphy = trim($morphy); - $object->status = (int) $status; - $object->subscription = (int) $subscription; - $object->duration_value = $duration_value; - $object->duration_unit = $duration_unit; - $object->note = trim($comment); + $object->morphy = trim($morphy); + $object->status = (int) $status; + $object->subscription = (int) $subscription; + $object->amount = ($amount == '' ? '' : price2num($amount, 'MT')); + $object->duration_value = $duration_value; + $object->duration_unit = $duration_unit; + $object->note = trim($comment); $object->mail_valid = trim($mail_valid); - $object->vote = (int) $vote; + $object->vote = (int) $vote; // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object); @@ -163,16 +166,16 @@ if ($action == 'update' && $user->rights->adherent->configurer) { $object->fetch($rowid); $object->oldcopy = clone $object; - - $object->label = trim($label); - $object->morphy = trim($morphy); - $object->status = (int) $status; + $object->label= trim($label); + $object->morphy = trim($morphy); + $object->status = (int) $status; $object->subscription = (int) $subscription; - $object->duration_value = $duration_value; - $object->duration_unit = $duration_unit; - $object->note = trim($comment); + $object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));; + $object->duration_value = $duration_value; + $object->duration_unit = $duration_unit; + $object->note = trim($comment); $object->mail_valid = trim($mail_valid); - $object->vote = (boolean) trim($vote); + $object->vote = (boolean) trim($vote); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object); @@ -222,7 +225,7 @@ llxHeader('', $langs->trans("MembersTypeSetup"), $help_url); if (!$rowid && $action != 'create' && $action != 'edit') { //print dol_get_fiche_head(''); - $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.vote, d.statut as status, d.morphy"; + $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.vote, d.statut as status, d.morphy"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql .= " WHERE d.entity IN (".getEntity('member_type').")"; @@ -268,6 +271,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { print ''; print ''; print ''; + print ''; print ''; print ''; print ''; @@ -283,6 +287,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { $membertype->label = $objp->rowid; $membertype->status = $objp->status; $membertype->subscription = $objp->subscription; + $membertype->amount = $objp->amount; print ''; print ''; print ''; + print ''; print ''; print ''; if ($user->rights->adherent->configurer) { @@ -358,6 +364,10 @@ if ($action == 'create') { print $form->selectyesno("subscription", 1, 1); print ''; + print ''; + print ''; @@ -434,6 +444,10 @@ if ($rowid > 0) { print yn($object->subscription); print ''; + print ''; + print ''; @@ -496,13 +510,13 @@ 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 as status,"; - $sql .= " t.libelle as type, t.subscription"; + $sql .= " t.libelle as type, t.subscription, t.amount"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent as d, ".MAIN_DB_PREFIX."adherent_type as t"; $sql .= " WHERE d.fk_adherent_type = t.rowid "; $sql .= " AND d.entity IN (".getEntity('adherent').")"; - $sql .= " AND t.rowid = ".$object->id; + $sql .= " AND t.rowid = ".((int) $object->id); if ($sall) { - $sql .= natural_search(array("f.firstname", "d.lastname", "d.societe", "d.email", "d.login", "d.address", "d.town", "d.note_public", "d.note_private"), $sall); + $sql .= natural_search(array("d.firstname", "d.lastname", "d.societe", "d.email", "d.login", "d.address", "d.town", "d.note_public", "d.note_private"), $sall); } if ($status != '') { $sql .= natural_search('d.statut', $status, 2); @@ -579,24 +593,24 @@ if ($rowid > 0) { $titre .= " (".$membertype->label.")"; } - $param = "&rowid=".$object->id; + $param = "&rowid=".urlencode($object->id); if (!empty($status)) { - $param .= "&status=".$status; + $param .= "&status=".urlencode($status); } if (!empty($search_lastname)) { - $param .= "&search_lastname=".$search_lastname; + $param .= "&search_lastname=".urlencode($search_lastname); } if (!empty($search_firstname)) { - $param .= "&search_firstname=".$search_firstname; + $param .= "&search_firstname=".urlencode($search_firstname); } if (!empty($search_login)) { - $param .= "&search_login=".$search_login; + $param .= "&search_login=".urlencode($search_login); } if (!empty($search_email)) { - $param .= "&search_email=".$search_email; + $param .= "&search_email=".urlencode($search_email); } if (!empty($filter)) { - $param .= "&filter=".$filter; + $param .= "&filter=".urlencode($filter); } if ($sall) { @@ -702,7 +716,7 @@ if ($rowid > 0) { print ''; } else { print ''; + print ''; + print ''; diff --git a/htdocs/adherents/type_translation.php b/htdocs/adherents/type_translation.php index 84fe883e41f..7435fc440ed 100644 --- a/htdocs/adherents/type_translation.php +++ b/htdocs/adherents/type_translation.php @@ -87,7 +87,7 @@ if ($action == 'vadd' && $cancel != $langs->trans("Cancel") && $user->rights->ad if ($object->setMultiLangs($user) > 0) { $action = ''; } else { - $action = 'add'; + $action = 'create'; setEventMessages($object->error, $object->errors, 'errors'); } } @@ -185,7 +185,7 @@ print "\n
\n"; if ($action == '') { if ($user->rights->produit->creer || $user->rights->service->creer) { - print ''.$langs->trans("Add").''; + print ''.$langs->trans("Add").''; if ($cnt_trans > 0) { print ''.$langs->trans("Update").''; } @@ -208,7 +208,13 @@ if ($action == 'edit') { if (!empty($object->multilangs)) { foreach ($object->multilangs as $key => $value) { $s = picto_from_langcode($key); - print '
'.($s ? $s.' ' : '').' '.$langs->trans('Language_'.$key).': '.img_delete('', 'class="valigntextbottom"')."
"; + print '
'; + print '
'; + print ($s ? $s.' ' : '').''.$langs->trans('Language_'.$key).':'; + print '
'; + print ''; print '
'; print '
'; print $form->select_company($object->fk_soc, 'socid', '', 1); print '
'.$adherent->getNomUrl(-1, 0, 'card', 'lastname').''.$adherent->getNomUrl(-1, 0, 'card', 'lastname').''; + print ''; print $obj->note; print ''.$langs->trans("Label").''.$langs->trans("MembersNature").''.$langs->trans("SubscriptionRequired").''.$langs->trans("Amount").''.$langs->trans("VoteAllowed").''.$langs->trans("Status").' 
'; @@ -300,6 +305,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { } print ''.yn($objp->subscription).''.(is_null($objp->amount) || $objp->amount === '' ? '' : price($objp->amount)).''.yn($objp->vote).''.$membertype->getLibStatut(5).'
'.$langs->trans("Amount").''; + print ''; + print '
'.$langs->trans("VoteAllowed").''; print $form->selectyesno("vote", GETPOSTISSET("vote") ? GETPOST('vote', 'aZ09') : 1, 1); print '
'.$langs->trans("Amount").''; + print ((is_null($object->amount) || $object->amount === '') ? '' : price($object->amount)); + print '
'.$langs->trans("VoteAllowed").''; print yn($object->vote); print '
'; - if ($objp->subscription == 'yes') { + if (!empty($objp->subscription)) { print $langs->trans("SubscriptionNotReceived"); if ($objp->status > 0) { print " ".img_warning(); @@ -781,6 +795,12 @@ if ($rowid > 0) { print $form->selectyesno("subscription", $object->subscription, 1); print '
'.$langs->trans("Amount").''; + print ''; + print '
'.$langs->trans("VoteAllowed").''; print $form->selectyesno("vote", $object->vote, 1); print '
'; @@ -231,11 +237,17 @@ if ($action == 'edit') { print ''; print ''; -} elseif ($action != 'add') { +} elseif ($action != 'create') { if (!empty($object->multilangs)) { foreach ($object->multilangs as $key => $value) { $s = picto_from_langcode($key); - print ($s ? $s.' ' : '')." ".$langs->trans('Language_'.$key).": ".''.img_delete('', 'class="valigntextbottom"').''; + print '
'; + print ($s ? $s.' ' : '').''.$langs->trans('Language_'.$key).':'; + print '
'; + print ''; + print '
'; print '
'; @@ -244,9 +256,11 @@ if ($action == 'edit') { print '
'; print '
'.$langs->trans('Description').''.$object->multilangs[$key]["description"].'
'; print ''; + + print '
'; } } - if (!$cnt_trans && $action != 'add') { + if (!$cnt_trans && $action != 'create') { print '
'.$langs->trans('NoTranslation').'
'; } } @@ -257,7 +271,7 @@ if ($action == 'edit') { * Form to add a new translation */ -if ($action == 'add' && $user->rights->adherent->configurer) { +if ($action == 'create' && $user->rights->adherent->configurer) { //WYSIWYG Editor require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; diff --git a/htdocs/admin/accountant.php b/htdocs/admin/accountant.php index 3ed43f1664f..56c9605c460 100644 --- a/htdocs/admin/accountant.php +++ b/htdocs/admin/accountant.php @@ -17,7 +17,7 @@ /** * \file htdocs/admin/accountant.php - * \ingroup accountant + * \ingroup core * \brief Setup page to configure accountant / auditor */ diff --git a/htdocs/admin/accounting.php b/htdocs/admin/accounting.php new file mode 100644 index 00000000000..e775f5bd8e3 --- /dev/null +++ b/htdocs/admin/accounting.php @@ -0,0 +1,68 @@ + + * + * 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/admin/accounting.php + * \ingroup accounting + * \brief Setup page to configure accountanting module + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + +$action = GETPOST('action', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'adminaccoutant'; // To manage different context of search + +// Load translation files required by the page +$langs->loadLangs(array('admin', 'companies')); + +if (!$user->admin) { + accessforbidden(); +} + +$error = 0; + + +/* + * Actions + */ + +// Nothing + + +/* + * View + */ + +$help_url = ''; +llxHeader('', $langs->trans("ConfigAccountingExpert"), $help_url); + +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans("ConfigAccountingExpert"), $linkback, 'title_setup'); + +print "
\n"; +print ''.$langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("Accounting").' - '.$langs->transnoentitiesnoconv("Setup"))."
\n"; +print "
\n"; + +llxFooter(); + +$db->close(); diff --git a/htdocs/admin/agenda.php b/htdocs/admin/agenda.php index 9829be288a5..a3d725bee93 100644 --- a/htdocs/admin/agenda.php +++ b/htdocs/admin/agenda.php @@ -112,8 +112,11 @@ if ($action == "save" && empty($cancel)) { * View */ -$wikihelp = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:Módulo_Agenda'; -llxHeader('', $langs->trans("AgendaSetup"), $wikihelp); +// $wikihelp = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:Módulo_Agenda'; + +$help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:Módulo_Agenda'; + +llxHeader('', $langs->trans("AgendaSetup"), $help_url); $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans("AgendaSetup"), $linkback, 'title_setup'); diff --git a/htdocs/admin/boxes.php b/htdocs/admin/boxes.php index e8793ca3c30..ae33ef3b6fa 100644 --- a/htdocs/admin/boxes.php +++ b/htdocs/admin/boxes.php @@ -114,8 +114,8 @@ if ($action == 'add') { 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 .= ") VALUES ("; + $sql .= ((int) $boxid['value']).", ".((int) $pos).", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".((int) $fk_user).", ".$conf->entity; $sql .= ")"; dol_syslog("boxes.php activate box", LOG_DEBUG); @@ -149,14 +149,9 @@ if ($action == 'delete') { if (!empty($obj->box_id)) { $db->begin(); - // Remove all personalized setup when a box is activated or disabled (why removing all ? We removed only removed boxes) - // $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_param"; - // $sql.= " WHERE param LIKE 'MAIN_BOXES_%'"; - // $resql = $db->query($sql); - $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes"; $sql .= " WHERE entity = ".$conf->entity; - $sql .= " AND box_id=".$obj->box_id; + $sql .= " AND box_id=".((int) $obj->box_id); $resql = $db->query($sql); @@ -184,6 +179,7 @@ if ($action == 'switch') { $newsecondnum = preg_replace('/[a-zA-Z]+/', '', $newsecond); $newsecond = sprintf("%s%02d", $newsecondchar ? $newsecondchar : 'A', $newsecondnum + 1); } + $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($newfirst)."' WHERE rowid=".((int) $objfrom->rowid); dol_syslog($sql); $resultupdatefrom = $db->query($sql); @@ -255,7 +251,7 @@ if ($resql) { // We renumber the order of the boxes if one of them is in '' // This occurs just after an insert. if ($decalage) { - $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($decalage)."' WHERE rowid=".$obj->rowid; + $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($decalage)."' WHERE rowid=".((int) $obj->rowid); $db->query($sql); } } @@ -427,11 +423,11 @@ foreach ($boxactivated as $key => $box) { $hasprevious = ($key != 0); print '
'.($key + 1).''; - print ($hasnext ? ''.img_down().' ' : ''); - print ($hasprevious ? ''.img_up().'' : ''); + print ($hasnext ? ''.img_down().' ' : ''); + print ($hasprevious ? ''.img_up().'' : ''); print ''; - print ''.img_delete().''; + print ''.img_delete().''; print '
'; print ''; print ''; - print ''; + print ''; print ''; $showemptyline = ''; @@ -2142,18 +2158,26 @@ if ($id) { $value = $tabname[$i]; print ''; print ''; - print ''; + print ''; + print ''; $lastlineisempty = false; } else { if (!$lastlineisempty) { @@ -2367,10 +2391,10 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') $transkey = ''; if (in_array($fieldlist[$field], array('label', 'libelle'))) { // For label // Special case for labels - if ($tabname == MAIN_DB_PREFIX.'c_civility') { + if ($tabname == MAIN_DB_PREFIX.'c_civility' && !empty($obj->code)) { $transkey = "Civility".strtoupper($obj->code); } - if ($tabname == MAIN_DB_PREFIX.'c_payment_term') { + if ($tabname == MAIN_DB_PREFIX.'c_payment_term' && !empty($obj->code)) { $langs->load("bills"); $transkey = "PaymentConditionShort".strtoupper($obj->code); } diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index ea7c7bed042..9e5a1e8bce1 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -322,7 +322,7 @@ class Dolistore $html .= ''; // do not load if display none //$html .= ''; diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index b8b43914824..a57df57d782 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -61,11 +61,15 @@ $arrayofparameters = array( 'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_SPEAKER'=>array('type'=>'emailtemplate:eventorganization_send', 'enabled'=>1), 'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES'=>array('type'=>'emailtemplate:eventorganization_send', 'enabled'=>1), 'EVENTORGANIZATION_SECUREKEY'=>array('type'=>'securekey', 'enabled'=>1), + 'SERVICE_BOOTH_LOCATION'=>array('type'=>'product', 'enabled'=>1), + 'SERVICE_CONFERENCE_ATTENDEE_SUBSCRIPTION'=>array('type'=>'product', 'enabled'=>1), ); $error = 0; $setupnotempty = 0; +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + /* * Actions @@ -180,15 +184,14 @@ if ($action == 'updateMask') { $form = new Form($db); -//$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); - $page_name = "EventOrganizationSetup"; + llxHeader('', $langs->trans($page_name)); // Subheader $linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans($page_name), $linkback, 'eventorganization'); +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); // Configuration header $head = eventorganizationAdminPrepareHead(); @@ -276,8 +279,13 @@ if ($action == 'edit') { });'; print ''; } + } elseif ($val['type'] == 'product') { + if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $form->select_produits($selected, $constname, '', 0); + } } else { - print ''; + print ''; } print ''; } @@ -346,6 +354,14 @@ if ($action == 'edit') { } elseif ($conf->global->{$constname}==0) { print $langs->trans("NorProspectNorCustomer"); } + } elseif ($val['type'] == 'product') { + $product = new Product($db); + $resprod = $product->fetch($conf->global->{$constname}); + if ($resprod > 0) { + print $product->ref; + } elseif ($resprod < 0) { + setEventMessages(null, $object->errors, "errors"); + } } else { print $conf->global->{$constname}; } diff --git a/htdocs/admin/eventorganization_confbooth_extrafields.php b/htdocs/admin/eventorganization_confbooth_extrafields.php index 4b6f9bdc46a..6e19bde8268 100644 --- a/htdocs/admin/eventorganization_confbooth_extrafields.php +++ b/htdocs/admin/eventorganization_confbooth_extrafields.php @@ -59,12 +59,14 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; * View */ +$help_url = ''; +$page_name = "EventOrganizationSetup"; -llxHeader('', $langs->trans("EventOrganizationSetup")); +llxHeader('', $langs->trans($page_name), $help_url); $linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("EventOrganizationSetup"), $linkback, 'eventorganization'); +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); $head = eventorganizationAdminPrepareHead(); diff --git a/htdocs/admin/eventorganization_confboothattendee_extrafields.php b/htdocs/admin/eventorganization_confboothattendee_extrafields.php index d9dd448bb42..6b201e6b923 100644 --- a/htdocs/admin/eventorganization_confboothattendee_extrafields.php +++ b/htdocs/admin/eventorganization_confboothattendee_extrafields.php @@ -63,17 +63,19 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; * View */ +$help_url = ''; +$page_name = 'EventOrganizationSetup'; -llxHeader('', $langs->trans("EventOrganizationSetup"), $help_url); +llxHeader('', $langs->trans($page_name), $help_url); $linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("EventOrganizationSetup"), $linkback, 'title_setup'); +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); $head = eventorganizationAdminPrepareHead(); -print dol_get_fiche_head($head, 'conferenceorboothattendee_extrafields', $langs->trans("ConferenceOrBoothAttendeeExtraFields"), -1, 'account'); +print dol_get_fiche_head($head, 'conferenceorboothattendee_extrafields', $langs->trans("ConferenceOrBoothAttendeeExtraFields"), -1, 'eventorganization'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/external_rss.php b/htdocs/admin/external_rss.php index b8b412ad6f8..71086096e4f 100644 --- a/htdocs/admin/external_rss.php +++ b/htdocs/admin/external_rss.php @@ -136,7 +136,7 @@ if (GETPOST("delete")) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes"; $sql .= " WHERE entity = ".$conf->entity; - $sql .= " AND box_id = ".$obj->rowid; + $sql .= " AND box_id = ".((int) $obj->rowid); $resql = $db->query($sql); $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes_def"; diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index 8b799c9c7de..0ac40741ab3 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -211,11 +211,12 @@ if ($action == 'update') { dolibarr_set_const($db, "MAIN_DEFAULT_WORKING_DAYS", GETPOST("MAIN_DEFAULT_WORKING_DAYS", 'alphanohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_DEFAULT_WORKING_HOURS", GETPOST("MAIN_DEFAULT_WORKING_HOURS", 'alphanohtml'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_BUGTRACK_ENABLELINK", GETPOST("MAIN_BUGTRACK_ENABLELINK", 'alpha'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_FIRSTNAME_NAME_POSITION", GETPOST("MAIN_FIRSTNAME_NAME_POSITION", 'aZ09'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_MOTD", dol_htmlcleanlastbr(GETPOST("main_motd", 'restricthtml')), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_HOME", dol_htmlcleanlastbr(GETPOST("main_home", 'restricthtml')), 'chaine', 0, '', $conf->entity); - //dolibarr_set_const($db, "MAIN_BUGTRACK_ENABLELINK", GETPOST('MAIN_BUGTRACK_ENABLELINK', 'aZ09'), 'chaine', 0, '', $conf->entity); //dolibarr_set_const($db, "MAIN_HELP_DISABLELINK", GETPOST("MAIN_HELP_DISABLELINK", 'aZ09'), 'chaine', 0, '', 0); // Param for all entities $varforimage = 'imagebackground'; $dirforimage = $conf->mycompany->dir_output.'/logos/'; @@ -311,8 +312,9 @@ print '
'; // Other print '
'; -print '
'.$langs->trans("Dictionary").''.$langs->trans("Table").'
'; if (!empty($tabcond[$i])) { - print ''.$langs->trans($tablib[$i]).''; + $tabnamenoprefix = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabname[$i]); + print ''; + if (!empty($tabcomplete[$tabnamenoprefix]['picto'])) { + print img_picto('', $tabcomplete[$tabnamenoprefix]['picto'], 'class="pictofixedwidth paddingrightonly"'); + } + print $langs->trans($tablib[$i]); + print ''; } else { print $langs->trans($tablib[$i]); } print ''; - /*if (empty($tabcond[$i])) - { - print info_admin($langs->trans("DictionaryDisabledSinceNoModuleNeedIt"),1); - }*/ + print ''; + print img_picto('Edit', 'edit', ''); + print ''; print ''.$tabname[$i].'
'; + print $form->textwithpicto('', $langs->trans("Table").': '.$tabname[$i]); + print '
'.$newapp.$images.'

'.$product->name->language[$this->lang - 1] - .'
'.$version.'

+ .'
'.$version.' '.dol_print_date(dol_stringtotime($product->date_upd), 'dayhour').' - '.$langs->trans('Ref').': '.$product->reference.' - '.$langs->trans('Id').': '.$product->id.'

'.$product->description_short->language[$this->lang - 1].'
'; -print ''; +print '
'.$langs->trans("Miscellaneous").'
'; +print ''; +print ''; print ''; @@ -401,8 +403,7 @@ print ''; // Show bugtrack link print ''; print ''; print ''; @@ -441,8 +442,9 @@ print '
'; // Other print '
'; -print '
'.$langs->trans("Miscellaneous").' '; print '
'.$langs->trans("ShowBugTrackLink", $langs->transnoentitiesnoconv("FindBug")).''; -print ajax_constantonoff("MAIN_BUGTRACK_ENABLELINK", array(), $conf->entity, 0, 0, 1, 0); -//print $form->selectyesno('MAIN_BUGTRACK_ENABLELINK', $conf->global->MAIN_BUGTRACK_ENABLELINK, 1); +print ''; print ' 
'; -print ''; +print '
'.$langs->trans("LoginPage").'
'; +print ''; +print ''; print ''; print ''; diff --git a/htdocs/admin/index.php b/htdocs/admin/index.php index a97717412a9..396570b2155 100644 --- a/htdocs/admin/index.php +++ b/htdocs/admin/index.php @@ -75,7 +75,7 @@ print $langs->trans("SetupDescription2", $langs->transnoentities("MenuCompanySet print "

"; print ''; -print '
'; +print '

'; // Show info setup company if (empty($conf->global->MAIN_INFO_SOCIETE_NOM) || empty($conf->global->MAIN_INFO_SOCIETE_COUNTRY)) { diff --git a/htdocs/admin/knowledgemanagement.php b/htdocs/admin/knowledgemanagement.php new file mode 100644 index 00000000000..b8434773f67 --- /dev/null +++ b/htdocs/admin/knowledgemanagement.php @@ -0,0 +1,607 @@ + + * Copyright (C) 2021 SuperAdmin + * + * 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 knowledgemanagement/admin/setup.php + * \ingroup knowledgemanagement + * \brief KnowledgeManagement setup page. + */ + +// Load Dolibarr environment +require '../main.inc.php'; + +global $langs, $user; + +// Libraries +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; +require_once DOL_DOCUMENT_ROOT."/knowledgemanagement/lib/knowledgemanagement.lib.php"; + +// Translations +$langs->loadLangs(array("admin", "knowledgemanagement")); + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type = 'knowledgemanagement'; + +$arrayofparameters = array( + 'KNOWLEDGEMANAGEMENT_MYPARAM1'=>array('type'=>'string', 'css'=>'minwidth500' ,'enabled'=>0), + //'KNOWLEDGEMANAGEMENT_MYPARAM2'=>array('type'=>'textarea','enabled'=>1), + //'KNOWLEDGEMANAGEMENT_MYPARAM3'=>array('type'=>'category:'.Categorie::TYPE_CUSTOMER, 'enabled'=>1), + //'KNOWLEDGEMANAGEMENT_MYPARAM4'=>array('type'=>'emailtemplate:thirdparty', 'enabled'=>1), + //'KNOWLEDGEMANAGEMENT_MYPARAM5'=>array('type'=>'yesno', 'enabled'=>1), + //'KNOWLEDGEMANAGEMENT_MYPARAM5'=>array('type'=>'thirdparty_type', 'enabled'=>1), +); + +$error = 0; +$setupnotempty = 0; + +// Access control +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +if ((float) DOL_VERSION >= 6) { + include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; +} + +if ($action == 'updateMask') { + $maskconstorder = GETPOST('maskconstorder', 'alpha'); + $maskorder = GETPOST('maskorder', 'alpha'); + + if ($maskconstorder) { + $res = dolibarr_set_const($db, $maskconstorder, $maskorder, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen') { + $modele = GETPOST('module', 'alpha'); + $tmpobjectkey = GETPOST('object'); + + $tmpobject = new $tmpobjectkey($db); + $tmpobject->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/knowledgemanagement/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".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($tmpobject, $langs) > 0) { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=".strtolower($tmpobjectkey)."&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); + } +} elseif ($action == 'setmod') { + // TODO Check if numbering module chosen can be activated by calling method canBeActivated + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'KNOWLEDGEMANAGEMENT_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); + } +} elseif ($action == 'set') { + // Activate a model + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') { + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'KNOWLEDGEMANAGEMENT_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if ($conf->global->$constforval == "$value") { + dolibarr_del_const($db, $constforval, $conf->entity); + } + } + } +} elseif ($action == 'setdoc') { + // Set or unset default model + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'KNOWLEDGEMANAGEMENT_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $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->$constforval = $value; + } + + // We disable/enable the document template (into llx_document_model table) + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $ret = addDocumentModel($value, $type, $label, $scandir); + } + } +} elseif ($action == 'unsetdoc') { + $tmpobjectkey = GETPOST('object'); + if (!empty($tmpobjectkey)) { + $constforval = 'KNOWLEDGEMANAGEMENT_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + dolibarr_del_const($db, $constforval, $conf->entity); + } +} + + + +/* + * View + */ + +$form = new Form($db); + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + +$page_name = "KnowledgeManagementSetup"; +llxHeader('', $langs->trans($page_name)); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + +// Configuration header +$head = knowledgemanagementAdminPrepareHead(); +print dol_get_fiche_head($head, 'setup', $langs->trans('ModuleKnowledgeManagementName'), -1, "knowledgemanagement"); + +// Setup page goes here +echo ''.$langs->trans("KnowledgeManagementSetupPage").'

'; + + +if ($action == 'edit') { + print '
'; + print ''; + print ''; + + print '
'.$langs->trans("LoginPage").' 
'; + print ''; + + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print ''.$form->textwithpicto($langs->trans($constname), $tooltiphelp, 1, 'info', '', 0, 3, 'tootips'.$constname).''; + print ''; + + if ($val['type'] == 'textarea') { + print '\n"; + } elseif ($val['type']== 'html') { + require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; + $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor->Create(); + } elseif ($val['type'] == 'yesno') { + print $form->selectyesno($constname, $conf->global->{$constname}, 1); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + $nboftemplates = $formmail->fetchAllEMailTemplate($tmp[1], $user, null, 1); // We set lang=null to get in priority record with no lang + //$arraydefaultmessage = $formmail->getEMailTemplate($db, $tmp[1], $user, null, 0, 1, ''); + $arrayofmessagename = array(); + if (is_array($formmail->lines_model)) { + foreach ($formmail->lines_model as $modelmail) { + //var_dump($modelmail); + $moreonlabel = ''; + if (!empty($arrayofmessagename[$modelmail->label])) { + $moreonlabel = ' (' . $langs->trans("SeveralLangugeVariatFound") . ')'; + } + // The 'label' is the key that is unique if we exclude the language + $arrayofmessagename[$modelmail->id] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)) . $moreonlabel; + } + } + print $form->selectarray($constname, $arrayofmessagename, $conf->global->{$constname}, 'None', 0, 0, '', 0, 0, 0, '', '', 1); + } elseif (preg_match('/category:/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + $formother = new FormOther($db); + + $tmp = explode(':', $val['type']); + print img_picto('', 'category', 'class="pictofixedwidth"'); + print $formother->select_categories($tmp[1], $conf->global->{$constname}, $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + $formcompany = new FormCompany($db); + print $formcompany->selectProspectCustomerType($conf->global->{$constname}, $constname); + } else { + print ''; + } + print '
'; + + print '
'; + print ''; + print '
'; + + print ''; + print '
'; +} else { + if (!empty($arrayofparameters)) { + print ''; + print ''; + + foreach ($arrayofparameters as $constname => $val) { + if ($val['enabled']==1) { + $setupnotempty++; + print ''; + } + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($constname . 'Tooltip') != $constname . 'Tooltip') ? $langs->trans($constname . 'Tooltip') : ''); + print $form->textwithpicto($langs->trans($constname), $tooltiphelp); + print ''; + + if ($val['type'] == 'textarea') { + print dol_nl2br($conf->global->{$constname}); + } elseif ($val['type']== 'html') { + print $conf->global->{$constname}; + } elseif ($val['type'] == 'yesno') { + print ajax_constantonoff($constname); + } elseif (preg_match('/emailtemplate:/', $val['type'])) { + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + + $tmp = explode(':', $val['type']); + + $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, $conf->global->{$constname}); + if ($template<0) { + setEventMessages(null, $formmail->errors, 'errors'); + } + print $langs->trans($template->label); + } elseif (preg_match('/category:/', $val['type'])) { + $c = new Categorie($db); + $result = $c->fetch($conf->global->{$constname}); + if ($result < 0) { + setEventMessages(null, $c->errors, 'errors'); + } + $ways = $c->print_all_ways(' >> ', 'none', 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text + $toprint = array(); + foreach ($ways as $way) { + $toprint[] = '
  • color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '
  • '; + } + print '
      ' . implode(' ', $toprint) . '
    '; + } elseif (preg_match('/thirdparty_type/', $val['type'])) { + if ($conf->global->{$constname}==2) { + print $langs->trans("Prospect"); + } elseif ($conf->global->{$constname}==3) { + print $langs->trans("ProspectCustomer"); + } elseif ($conf->global->{$constname}==1) { + print $langs->trans("Customer"); + } elseif ($conf->global->{$constname}==0) { + print $langs->trans("NorProspectNorCustomer"); + } + } else { + print $conf->global->{$constname}; + } + print '
    '; + + print '
    '; + print ''.$langs->trans("Modify").''; + print '
    '; + } else { + //print '
    '.$langs->trans("NothingToSetup"); + } +} + + +$moduledir = 'knowledgemanagement'; +$myTmpObjects = array(); +$myTmpObjects['MyObject'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); + + +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'MyObject') { + continue; + } + if ($myTmpObjectArray['includerefgeneration']) { + /* + * Orders Numbering model + */ + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectKey), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { + continue; + } + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { + continue; + } + + if ($module->isEnabled()) { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $mytmpinstance = new $myTmpObjectKey($db); + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
    '; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') { + $nextval = $langs->trans($nextval); + } + $htmltooltip .= $nextval.'
    '; + } else { + $htmltooltip .= $langs->trans($module->error).'
    '; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
    '.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
    '.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
    '.$langs->trans($tmp).'
    '; + } elseif ($tmp == 'NotConfigured') { + print $langs->trans($tmp); + } else { + print $tmp; + } + print '
    '; + $constforvar = 'KNOWLEDGEMANAGEMENT_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $file) { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

    \n"; + } + + if ($myTmpObjectArray['includedocgeneration']) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($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/".$moduledir.$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 "'; + $constforvar = 'KNOWLEDGEMANAGEMENT_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $name) { + //print img_picto($langs->trans("Default"), 'on'); + // Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset + print 'scandir.'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), '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"), 'pdf').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
    '; + } +} + +if (empty($setupnotempty)) { + print '
    '.$langs->trans("NothingToSetup"); +} + +// Page end +print dol_get_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/htdocs/admin/knowledgerecord_extrafields.php b/htdocs/admin/knowledgerecord_extrafields.php new file mode 100644 index 00000000000..d6c94e4ceeb --- /dev/null +++ b/htdocs/admin/knowledgerecord_extrafields.php @@ -0,0 +1,118 @@ + + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2012 Regis Houssin + * Copyright (C) 2014 Florian Henry + * Copyright (C) 2015 Jean-François Ferry + * + * 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 admin/knowledgerecord_extrafields.php + * \ingroup knowledgemanagement + * \brief Page to setup extra fields of knowledgerecord + */ + +// Load Dolibarr environment +require '../main.inc.php'; + +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/lib/knowledgemanagement.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array('knowledgemanagement', 'admin')); + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label = ExtraFields::$type2label; +$type2label = array(''); +foreach ($tmptype2label as $key => $val) { + $type2label[$key] = $langs->transnoentitiesnoconv($val); +} + +$action = GETPOST('action', 'aZ09'); +$attrname = GETPOST('attrname', 'alpha'); +$elementtype = 'knowledgemanagement_knowledgerecord'; //Must be the $table_element of the class that manage extrafield + +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; + + + +/* + * View + */ + +$help_url = ''; +$page_name = 'KnowledgeManagementSetup'; + +llxHeader('', $langs->trans($page_name), $help_url); + + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); + + +$head = knowledgemanagementAdminPrepareHead(); + +print dol_get_fiche_head($head, 'extra', $langs->trans("KnowledgeRecordExtraFields"), -1, 'knowledgemanagement'); + +require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; + +print dol_get_fiche_end(); + + +// Buttons +if ($action != 'create' && $action != 'edit') { + print '
    '; + print "".$langs->trans("NewAttribute").""; + print "
    "; +} + + +/* + * Creation of an optional field + */ +if ($action == 'create') { + print '
    '; + print load_fiche_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php'; +} + +/* + * Edition of an optional field + */ +if ($action == 'edit' && !empty($attrname)) { + print "
    "; + print load_fiche_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 0252f149d10..e86c78763ee 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -48,7 +48,7 @@ $substitutionarrayfortest = array( '__DOL_MAIN_URL_ROOT__'=>DOL_MAIN_URL_ROOT, '__ID__' => 'RecipientIdRecord', //'__EMAIL__' => 'RecipientEMail', // Done into actions_sendmails - '__CHECK_READ__' => (is_object($object) && !empty($object->thirdparty) && is_object($object->thirdparty)) ? '' : '', + '__CHECK_READ__' => (!empty($object) && is_object($object) && is_object($object->thirdparty)) ? '' : '', '__USER_SIGNATURE__' => (($user->signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? $usersignature : ''), // Done into actions_sendmails '__LOGIN__' => 'RecipientLogin', '__LASTNAME__' => 'RecipientLastname', @@ -302,7 +302,7 @@ if ($action == 'edit') { // Disable print ''.$langs->trans("MAIN_DISABLE_ALL_MAILS").''; - print $form->selectyesno('MAIN_DISABLE_ALL_MAILS', $conf->global->MAIN_DISABLE_ALL_MAILS, 1); + print $form->selectyesno('MAIN_DISABLE_ALL_MAILS', getDolGlobalString('MAIN_DISABLE_ALL_MAILS'), 1); print ''; // Force e-mail recipient @@ -514,7 +514,7 @@ if ($action == 'edit') { $liste['company'] = $langs->trans('CompanyEmail').' ('.(empty($conf->global->MAIN_INFO_SOCIETE_MAIL) ? $langs->trans("NotDefined") : $conf->global->MAIN_INFO_SOCIETE_MAIL).')'; print ''.$langs->trans('MAIN_MAIL_DEFAULT_FROMTYPE').''; - print $form->selectarray('MAIN_MAIL_DEFAULT_FROMTYPE', $liste, $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE, 0); + print $form->selectarray('MAIN_MAIL_DEFAULT_FROMTYPE', $liste, getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE'), 0); print ''; // From @@ -529,7 +529,7 @@ if ($action == 'edit') { // Add user to select destinaries list print ''.$langs->trans("MAIN_MAIL_ENABLED_USER_DEST_SELECT").''; - print $form->selectyesno('MAIN_MAIL_ENABLED_USER_DEST_SELECT', $conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT, 1); + print $form->selectyesno('MAIN_MAIL_ENABLED_USER_DEST_SELECT', getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT'), 1); print ''; print ''; @@ -719,7 +719,7 @@ if ($action == 'edit') { $liste['user'] = $langs->trans('UserEmail'); $liste['company'] = $langs->trans('CompanyEmail').' ('.(empty($conf->global->MAIN_INFO_SOCIETE_MAIL) ? $langs->trans("NotDefined") : $conf->global->MAIN_INFO_SOCIETE_MAIL).')'; $sql = 'SELECT rowid, label, email FROM '.MAIN_DB_PREFIX.'c_email_senderprofile'; - $sql .= ' WHERE active = 1 AND (private = 0 OR private = '.$user->id.')'; + $sql .= ' WHERE active = 1 AND (private = 0 OR private = '.((int) $user->id).')'; $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); @@ -737,14 +737,14 @@ if ($action == 'edit') { print ''.$langs->trans('MAIN_MAIL_DEFAULT_FROMTYPE').''; print ''; - if (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'robot') { + if (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'robot') { print $langs->trans('RobotEmail'); - } elseif (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'user') { + } elseif (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'user') { print $langs->trans('UserEmail'); - } elseif (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'company') { + } elseif (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'company') { print $langs->trans('CompanyEmail').' '.dol_escape_htmltag('<'.$mysoc->email.'>'); } else { - $id = preg_replace('/senderprofile_/', '', !empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) ? $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE : ''); + $id = preg_replace('/senderprofile_/', '', getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE')); if ($id > 0) { include_once DOL_DOCUMENT_ROOT.'/core/class/emailsenderprofile.class.php'; $emailsenderprofile = new EmailSenderProfile($db); @@ -756,7 +756,7 @@ if ($action == 'edit') { // Errors To print ''.$langs->trans("MAIN_MAIL_ERRORS_TO").''; - print ''.(!empty($conf->global->MAIN_MAIL_ERRORS_TO) ? $conf->global->MAIN_MAIL_ERRORS_TO : ''); + print ''.(getDolGlobalString('MAIN_MAIL_ERRORS_TO')); if (!empty($conf->global->MAIN_MAIL_ERRORS_TO) && !isValidEmail($conf->global->MAIN_MAIL_ERRORS_TO)) { print img_warning($langs->trans("ErrorBadEMail")); } diff --git a/htdocs/admin/mails_senderprofile_list.php b/htdocs/admin/mails_senderprofile_list.php index 7da20aa36c7..44982fc3ece 100644 --- a/htdocs/admin/mails_senderprofile_list.php +++ b/htdocs/admin/mails_senderprofile_list.php @@ -88,7 +88,7 @@ foreach ($object->fields as $key => $val) { // List of fields to search into when doing a "search in all" $fieldstosearchall = array(); foreach ($object->fields as $key => $val) { - if ($val['searchall']) { + if (!empty($val['searchall'])) { $fieldstosearchall['t.'.$key] = $val['label']; } } @@ -102,7 +102,7 @@ foreach ($object->fields as $key => $val) { } } // Extra fields -if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) { +if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) { $arrayfields["ef.".$key] = array( @@ -240,7 +240,7 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $obje $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; -if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { +if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; } if ($object->ismultientitymanaged == 1) { @@ -497,11 +497,11 @@ foreach ($object->fields as $key => $val) { if (!empty($arrayfields['t.'.$key]['checked'])) { print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], empty($search[$key]) ? '' : $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); } elseif (strpos($val['type'], 'integer:') === 0) { print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth150', 1); } elseif (!preg_match('/^(date|timestamp)/', $val['type'])) { - print ''; + print ''; } print ''; } @@ -552,7 +552,7 @@ print ''."\n"; // Detect if we need a fetch on each output line $needToFetchEachLine = 0; -if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { +if (!empty($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { if (preg_match('/\$object/', $val)) { $needToFetchEachLine++; // There is at least one compute field that use $object diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index cdb9c10ec87..c2a54e31a3a 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -11,7 +11,7 @@ * Copyright (C) 2011-2016 Alexandre Spangaro * Copyright (C) 2015 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud - * Copyright (C) 2018-2020 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,16 +45,17 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; // Load translation files required by the page $langsArray=array("errors", "admin", "mails", "languages"); -if ($conf->adherent->enabled) { +if (!empty($conf->adherent->enabled)) { $langsArray[]='members'; } -if ($conf->eventorganization->enabled) { +if (!empty($conf->eventorganization->enabled)) { $langsArray[]='eventorganization'; } $langs->loadLangs($langsArray); $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; +$massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation $id = GETPOST('id', 'int'); @@ -73,8 +74,8 @@ $acts = array(); $actl = array(); $acts[0] = "activate"; $acts[1] = "disable"; -$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); -$actl[1] = img_picto($langs->trans("Activated"), 'switch_on'); +$actl[0] = img_picto($langs->trans("Disabled"), 'switch_off', 'class="size15x"'); +$actl[1] = img_picto($langs->trans("Activated"), 'switch_on', 'class="size15x"'); $listoffset = GETPOST('listoffset', 'alpha'); $listlimit = GETPOST('listlimit', 'alpha') > 0 ?GETPOST('listlimit', 'alpha') : 1000; @@ -159,19 +160,15 @@ if (empty($conf->global->MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES)) { $tabhelp = array(); $tabhelp[25] = array( - 'topic'=>$helpsubstit, + 'topic'=>''.$helpsubstit.'', 'joinfiles'=>$langs->trans('AttachMainDocByDefault'), - 'content'=>$helpsubstit, - 'content_lines'=>$helpsubstitforlines, + 'content'=>''.$helpsubstit.'', + 'content_lines'=>''.$helpsubstitforlines.'', 'type_template'=>$langs->trans("TemplateForElement"), 'private'=>$langs->trans("TemplateIsVisibleByOwnerOnly"), 'position'=>$langs->trans("PositionIntoComboList") ); -// List of check for fields (NOT USED YET) -$tabfieldcheck = array(); -$tabfieldcheck[25] = array(); - $elementList = array(); @@ -181,55 +178,55 @@ $elementList = array(); $elementList['all'] = '-- '.dol_escape_htmltag($langs->trans("All")).' --'; $elementList['none'] = '-- '.dol_escape_htmltag($langs->trans("None")).' --'; $elementList['user'] = img_picto('', 'user', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToUser')); -if ($conf->adherent->enabled && $user->rights->adherent->lire) { +if (!empty($conf->adherent->enabled) && !empty($user->rights->adherent->lire)) { $elementList['member'] = img_picto('', 'object_member', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToMember')); } -if ($conf->recruitment->enabled && $user->rights->recruitment->recruitmentjobposition->read) { +if (!empty($conf->recruitment->enabled) && !empty($user->rights->recruitment->recruitmentjobposition->read)) { $elementList['recruitmentcandidature_send'] = img_picto('', 'recruitmentcandidature', 'class="paddingright"').dol_escape_htmltag($langs->trans('RecruitmentCandidatures')); } -if ($conf->societe->enabled && $user->rights->societe->lire) { +if (!empty($conf->societe->enabled) && !empty($user->rights->societe->lire)) { $elementList['thirdparty'] = img_picto('', 'company', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToThirdparty')); } -if ($conf->projet->enabled) { +if (!empty($conf->projet->enabled)) { $elementList['project'] = img_picto('', 'project', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToProject')); } -if ($conf->propal->enabled && $user->rights->propal->lire) { +if (!empty($conf->propal->enabled) && !empty($user->rights->propal->lire)) { $elementList['propal_send'] = img_picto('', 'propal', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendProposal')); } -if ($conf->commande->enabled && $user->rights->commande->lire) { +if (!empty($conf->commande->enabled) && !empty($user->rights->commande->lire)) { $elementList['order_send'] = img_picto('', 'order', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendOrder')); } -if ($conf->facture->enabled && $user->rights->facture->lire) { +if (!empty($conf->facture->enabled) && !empty($user->rights->facture->lire)) { $elementList['facture_send'] = img_picto('', 'bill', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendInvoice')); } -if ($conf->expedition->enabled) { +if (!empty($conf->expedition->enabled)) { $elementList['shipping_send'] = img_picto('', 'dolly', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendShipment')); } -if ($conf->reception->enabled) { +if (!empty($conf->reception->enabled)) { $elementList['reception_send'] = img_picto('', 'dolly', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendReception')); } -if ($conf->ficheinter->enabled) { +if (!empty($conf->ficheinter->enabled)) { $elementList['fichinter_send'] = img_picto('', 'intervention', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendIntervention')); } -if ($conf->supplier_proposal->enabled) { +if (!empty($conf->supplier_proposal->enabled)) { $elementList['supplier_proposal_send'] = img_picto('', 'propal', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendSupplierRequestForQuotation')); } -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)) { +if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->commande->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire))) { $elementList['order_supplier_send'] = img_picto('', 'order', 'class="paddingright"').dol_escape_htmltag($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)) { +if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->facture->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { $elementList['invoice_supplier_send'] = img_picto('', 'bill', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendSupplierInvoice')); } -if ($conf->contrat->enabled && $user->rights->contrat->lire) { +if (!empty($conf->contrat->enabled) && !empty($user->rights->contrat->lire)) { $elementList['contract'] = img_picto('', 'contract', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendContract')); } -if ($conf->ticket->enabled && $user->rights->ticket->read) { +if (!empty($conf->ticket->enabled) && !empty($user->rights->ticket->read)) { $elementList['ticket_send'] = img_picto('', 'ticket', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToTicket')); } -if ($conf->agenda->enabled) { +if (!empty($conf->agenda->enabled)) { $elementList['actioncomm_send'] = img_picto('', 'action', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendEventPush')); } -if ($conf->eventorganization->enabled && $user->rights->eventorganization->read) { +if (!empty($conf->eventorganization->enabled) && !empty($user->rights->eventorganization->read)) { $elementList['eventorganization_send'] = img_picto('', 'action', 'class="paddingright"').dol_escape_htmltag($langs->trans('MailToSendEventOrganization')); } @@ -336,13 +333,13 @@ if (empty($reshook)) { } } - // Si verif ok et action add, on ajoute la ligne + // If previous test is ok action is add, we add the line if ($ok && GETPOST('actionadd')) { // Add new entry $sql = "INSERT INTO ".$tabname[$id]." ("; // List of fields $sql .= $tabfieldinsert[$id]; - $sql .= ",active)"; + $sql .= ", active, enabled)"; $sql .= " VALUES("; // List of values @@ -393,7 +390,7 @@ if (empty($reshook)) { } $i++; } - $sql .= ", 1)"; + $sql .= ", 1, 1)"; dol_syslog("actionadd", LOG_DEBUG); $result = $db->query($sql); @@ -1002,7 +999,7 @@ if ($resql) { print ''; $tmpaction = 'view'; - $parameters = array('var'=>$var, 'fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]); + $parameters = array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]); $reshook = $hookmanager->executeHooks('viewEmailTemplateFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks $error = $hookmanager->error; $errors = $hookmanager->errors; @@ -1015,6 +1012,7 @@ if ($resql) { $showfield = 1; $align = ""; $class = "tddict"; + $title = ''; $valuetoshow = $obj->{$fieldlist[$field]}; if ($value == 'label' || $value == 'topic') { if ($langs->trans($valuetoshow) != $valuetoshow) { @@ -1024,11 +1022,10 @@ if ($resql) { } if ($value == 'label') { $class .= ' tdoverflowmax100'; - $valuetoshow = ''.$valuetoshow.''; } - /*if ($value == 'topic') { - $class .= ' tdoverflowmax300'; - }*/ + if ($value == 'topic') { + $class .= 'tdoverflowmax200 small'; + } if ($value == 'type_template') { $valuetoshow = isset($elementList[$valuetoshow]) ? $elementList[$valuetoshow] : $valuetoshow; $align = "center"; @@ -1069,7 +1066,13 @@ if ($resql) { // Show value for field if ($showfield) { print ''; - print ''.$valuetoshow.''; + print ''; + print $valuetoshow; + print ''; } } } @@ -1086,12 +1089,11 @@ if ($resql) { if ($param) { $url .= '&'.$param; } - $url .= '&'; // Status / Active print ''; if ($canbedisabled) { - print ''.$actl[$obj->active].''; + print ''.$actl[$obj->active].''; } else { print ''.$actl[$obj->active].''; } @@ -1100,10 +1102,10 @@ if ($resql) { // Modify link / Delete link print ''; if ($canbemodified) { - print ''.img_edit().''; + print ''.img_edit().''; } if ($iserasable) { - print ''.img_delete().''; + print ''.img_delete().''; //else print ''.img_delete().''; // Some dictionary can be edited by other profile than admin } print ''; @@ -1178,98 +1180,98 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') $formadmin = new FormAdmin($db); foreach ($fieldlist as $field => $value) { - if ($fieldlist[$field] == 'fk_user') { + if ($value == 'fk_user') { print ''; if ($user->admin) { - print $form->select_dolusers($obj->{$fieldlist[$field]}, 'fk_user', 1, null, 0, ($user->admin ? '' : 'hierarchyme'), null, 0, 0, 1, '', 0, '', 'maxwidth200'); + print $form->select_dolusers(empty($obj->{$value}) ? '' : $obj->{$value}, 'fk_user', 1, null, 0, ($user->admin ? '' : 'hierarchyme'), null, 0, 0, 1, '', 0, '', 'maxwidth200'); } else { if ($context == 'add') { // I am not admin and we show the add form print $user->getNomUrl(1); // Me $forcedvalue = $user->id; } else { - if ($obj && !empty($obj->{$fieldlist[$field]}) && $obj->{$fieldlist[$field]} > 0) { + if ($obj && !empty($obj->{$value}) && $obj->{$value} > 0) { $fuser = new User($db); - $fuser->fetch($obj->{$fieldlist[$field]}); + $fuser->fetch($obj->{$value}); print $fuser->getNomUrl(1); $forcedvalue = $fuser->id; } else { - $forcedvalue = $obj->{$fieldlist[$field]}; + $forcedvalue = $obj->{$value}; } } - $keyname = $fieldlist[$field]; + $keyname = $value; print ''; } print ''; - } elseif ($fieldlist[$field] == 'lang') { + } elseif ($value == 'lang') { print ''; if (!empty($conf->global->MAIN_MULTILANGS)) { $selectedlang = GETPOSTISSET('langcode') ?GETPOST('langcode', 'aZ09') : $langs->defaultlang; if ($context == 'edit') { - $selectedlang = $obj->{$fieldlist[$field]}; + $selectedlang = $obj->{$value}; } print $formadmin->select_language($selectedlang, 'langcode', 0, null, 1, 0, 0, 'maxwidth150'); } else { - if (!empty($obj->{$fieldlist[$field]})) { - print $obj->{$fieldlist[$field]}.' - '.$langs->trans('Language_'.$obj->{$fieldlist[$field]}); + if (!empty($obj->{$value})) { + print $obj->{$value}.' - '.$langs->trans('Language_'.$obj->{$value}); } - $keyname = $fieldlist[$field]; + $keyname = $value; if ($keyname == 'lang') { $keyname = 'langcode'; // Avoid conflict with lang param } - print ''; + print ''; } print ''; - } elseif ($fieldlist[$field] == 'type_template') { + } elseif ($value == 'type_template') { // Le type de template print ''; - if ($context == 'edit' && !empty($obj->{$fieldlist[$field]}) && !in_array($obj->{$fieldlist[$field]}, array_keys($elementList))) { + if ($context == 'edit' && !empty($obj->{$value}) && !in_array($obj->{$value}, array_keys($elementList))) { // Current template type is an unknown type, so we must keep it as it is. - print ''; - print $obj->{$fieldlist[$field]}; + print ''; + print $obj->{$value}; } else { - print $form->selectarray('type_template', $elementList, (!empty($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]}:''), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200', 1, '', 0, 1); + print $form->selectarray('type_template', $elementList, (!empty($obj->{$value}) ? $obj->{$value}:''), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200', 1, '', 0, 1); } print ''; - } elseif ($context == 'add' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) { + } elseif ($context == 'add' && in_array($value, array('topic', 'joinfiles', 'content', 'content_lines'))) { continue; - } elseif ($context == 'edit' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) { + } elseif ($context == 'edit' && in_array($value, array('topic', 'joinfiles', 'content', 'content_lines'))) { continue; - } elseif ($context == 'hide' && in_array($fieldlist[$field], array('topic', 'joinfiles', 'content', 'content_lines'))) { + } elseif ($context == 'hide' && in_array($value, array('topic', 'joinfiles', 'content', 'content_lines'))) { continue; } else { $size = ''; $class = ''; $classtd = ''; - if ($fieldlist[$field] == 'code') { + if ($value == 'code') { $class = 'maxwidth100'; } - if ($fieldlist[$field] == 'label') { + if ($value == 'label') { $class = 'maxwidth200'; } - if ($fieldlist[$field] == 'private') { + if ($value == 'private') { $class = 'maxwidth50'; $classtd = 'center'; } - if ($fieldlist[$field] == 'position') { + if ($value == 'position') { $class = 'maxwidth50'; $classtd = 'center'; } - if ($fieldlist[$field] == 'libelle') { + if ($value == 'libelle') { $class = 'quatrevingtpercent'; } - if ($fieldlist[$field] == 'topic') { + if ($value == 'topic') { $class = 'quatrevingtpercent'; } - if ($fieldlist[$field] == 'sortorder' || $fieldlist[$field] == 'sens' || $fieldlist[$field] == 'category_type') { + if ($value == 'sortorder' || $value == 'sens' || $value == 'category_type') { $size = 'size="2" '; } print ''; - if ($fieldlist[$field] == 'private') { + if ($value == 'private') { if (empty($user->admin)) { - print $form->selectyesno($fieldlist[$field], '1', 1); + print $form->selectyesno($value, '1', 1); } else { //print ''; - print $form->selectyesno($fieldlist[$field], (isset($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]}:''), 1); + print $form->selectyesno($value, (isset($obj->{$value}) ? $obj->{$value}:''), 1); } } else { - print ''; + print ''; } print ''; } diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index fbe1ae98619..5dc660adb9b 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -8,6 +8,7 @@ * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2018 Nicolas ZABOURI + * Copyright (C) 2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -246,6 +247,7 @@ if ($action == 'install') { if ($action == 'set' && $user->admin) { $resarray = activateModule($value); + dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity); if (!empty($resarray['errors'])) { setEventMessages('', $resarray['errors'], 'errors'); } else { @@ -269,6 +271,7 @@ if ($action == 'set' && $user->admin) { exit; } elseif ($action == 'reset' && $user->admin && GETPOST('confirm') == 'yes') { $result = unActivateModule($value); + dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } @@ -386,7 +389,8 @@ foreach ($modulesdir as $dir) { } $moduleposition = ($objMod->module_position ? $objMod->module_position : '50'); - if ($moduleposition == '50' && ($objMod->isCoreOrExternalModule() == 'external')) { + if ($objMod->isCoreOrExternalModule() == 'external' && $moduleposition < 100000) { + // an external module should never return a value lower than '80'. $moduleposition = '80'; // External modules at end by default } @@ -520,9 +524,11 @@ if ($mode == 'common' || $mode == 'commonkanban') { $moreforfilter = '
    '; - $moreforfilter .= ''; diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 3a479480812..373ab0e0f48 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -156,8 +156,9 @@ if ($resql) { $form = new Form($db); $page_name = "MultiCurrencySetup"; +$help_url = ''; -llxHeader('', $langs->trans($page_name)); +llxHeader('', $langs->trans($page_name), $help_url); // Subheader $linkback = ''.$langs->trans("BackToModuleList").''; @@ -165,7 +166,7 @@ print load_fiche_titre($langs->trans($page_name), $linkback); // Configuration header $head = multicurrencyAdminPrepareHead(); -print dol_get_fiche_head($head, 'settings', $langs->trans("ModuleSetup"), -1, "multicurrency"); +print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "multicurrency"); print ''; @@ -303,7 +304,7 @@ print ''; print ''; print ''; print ''; print ''; @@ -328,7 +329,7 @@ foreach ($TCurrency as &$currency) { print ''; print ''; print '1 '.$conf->currency.' = '; - print ' '.$currency->code.' '; + print ' '.$currency->code.' '; print ' '; print ''; print ''; diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index e1cf115626f..c0c6b45464f 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -243,7 +243,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { $elementLabel = $langs->trans('Intervention'); } elseif ($notifiedevent['elementtype'] == 'shipping') { $elementLabel = $langs->trans('Shipping'); - } elseif ($notifiedevent['elementtype'] == 'expensereport') { + } elseif ($notifiedevent['elementtype'] == 'expensereport' || $notifiedevent['elementtype'] == 'expense_report') { $elementLabel = $langs->trans('ExpenseReport'); } @@ -271,6 +271,8 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { $helptext = ''; form_constantes($constantes, 3, $helptext); + + print '
    '; } else { print '
    '.$form->selectCurrency('', 'code', 1).''; -print ' '; +print ' '; print ''; print '
    '; print ''; @@ -300,7 +302,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { $elementLabel = $langs->trans('Intervention'); } elseif ($notifiedevent['elementtype'] == 'shipping') { $elementLabel = $langs->trans('Shipping'); - } elseif ($notifiedevent['elementtype'] == 'expensereport') { + } elseif ($notifiedevent['elementtype'] == 'expensereport' || $notifiedevent['elementtype'] == 'expense_report') { $elementLabel = $langs->trans('ExpenseReport'); } @@ -316,7 +318,13 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { print '
    '; } -print '
    '; + +print '
    '; +print '* '.$langs->trans("GoOntoUserCardToAddMore").'
    '; +if (!empty($conf->societe->enabled)) { + print '** '.$langs->trans("GoOntoContactCardToAddMore").'
    '; +} +print '
    '; print ''; @@ -343,28 +351,38 @@ print "\n"; foreach ($listofnotifiedevents as $notifiedevent) { $label = $langs->trans("Notify_".$notifiedevent['code']); //!=$langs->trans("Notify_".$notifiedevent['code'])?$langs->trans("Notify_".$notifiedevent['code']):$notifiedevent['label']; + $elementPicto = $notifiedevent['elementtype']; $elementLabel = $langs->trans(ucfirst($notifiedevent['elementtype'])); // Special cases if ($notifiedevent['elementtype'] == 'order_supplier') { + $elementPicto = 'supplier_order'; $elementLabel = $langs->trans('SupplierOrder'); } elseif ($notifiedevent['elementtype'] == 'propal') { $elementLabel = $langs->trans('Proposal'); } elseif ($notifiedevent['elementtype'] == 'facture') { + $elementPicto = 'bill'; $elementLabel = $langs->trans('Bill'); } elseif ($notifiedevent['elementtype'] == 'commande') { + $elementPicto = 'order'; $elementLabel = $langs->trans('Order'); } elseif ($notifiedevent['elementtype'] == 'ficheinter') { + $elementPicto = 'intervention'; $elementLabel = $langs->trans('Intervention'); } elseif ($notifiedevent['elementtype'] == 'shipping') { + $elementPicto = 'shipment'; $elementLabel = $langs->trans('Shipping'); - } elseif ($notifiedevent['elementtype'] == 'expensereport') { + } elseif ($notifiedevent['elementtype'] == 'expensereport' || $notifiedevent['elementtype'] == 'expense_report') { + $elementPicto = 'expensereport'; $elementLabel = $langs->trans('ExpenseReport'); } print ''; - print ''.$elementLabel.''; + print ''; + print img_picto('', $elementPicto, 'class="pictofixedwidth"'); + print $elementLabel; + print ''; print ''.$notifiedevent['code'].''; - print ''.$label.''; + print ''.$label.''; print ''; // Notification with threshold foreach ($conf->global as $key => $val) { @@ -417,14 +435,6 @@ foreach ($listofnotifiedevents as $notifiedevent) { } print ''; -print '
    '; -print '* '.$langs->trans("GoOntoUserCardToAddMore").'
    '; -if (!empty($conf->societe->enabled)) { - print '** '.$langs->trans("GoOntoContactCardToAddMore").'
    '; -} - -print '
    '; - print '
    '; print '
    '; diff --git a/htdocs/admin/payment.php b/htdocs/admin/payment.php index e540d561d04..9b380b676b4 100644 --- a/htdocs/admin/payment.php +++ b/htdocs/admin/payment.php @@ -189,7 +189,7 @@ foreach ($dirmodels as $reldir) { if ($conf->global->PAYMENT_ADDON == $file || $conf->global->PAYMENT_ADDON.'.php' == $file) { print img_picto($langs->trans("Activated"), 'switch_on'); } else { - print ''.img_picto($langs->trans("Disabled"), 'switch_off').''; + print ''.img_picto($langs->trans("Disabled"), 'switch_off').''; } print ''; diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index a5c2770a9c4..7d7b5e36a40 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('admin', 'languages', 'other', 'companies', 'products', 'members', 'stocks')); +$langs->loadLangs(array('admin', 'languages', 'other', 'companies', 'products', 'members', 'stocks', 'Trips')); if (!$user->admin) { accessforbidden(); @@ -161,6 +161,10 @@ if (class_exists('TCPDI')) { print load_fiche_titre($langs->trans("PDF"), '', 'title_setup'); +$head = pdf_admin_prepare_head(); + +print dol_get_fiche_head($head, 'general', $langs->trans("PDF"), -1, 'pdf'); + print ''.$form->textwithpicto($langs->trans("PDFDesc"), $s)."
    \n"; print "
    \n"; @@ -178,7 +182,7 @@ print load_fiche_titre($langs->trans("DictionaryPaperFormat"), '', ''); print '
    '; print ''; -print ''; +print ''; $selected = (isset($conf->global->MAIN_PDF_FORMAT) ? $conf->global->MAIN_PDF_FORMAT : ''); if (empty($selected)) { @@ -215,12 +219,16 @@ print load_fiche_titre($langs->trans("PDFAddressForging"), '', ''); print '
    '; print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '; -print ''; +print ''; // Hide VAT Intra on address print ''; // Show prof id in address into pdf @@ -236,7 +244,11 @@ for ($i = 1; $i <= 6; $i++) { if ($pid) { print ''; } } @@ -254,16 +266,24 @@ $text = ''; if ($mysoc->useLocalTax(1) || $mysoc->useLocalTax(2)) { if ($mysoc->useLocalTax(1)) { $locales = $langs->transcountry("LT1", $mysoc->country_code); - $text = ''; } if ($mysoc->useLocalTax(2)) { $locales .= ($locales ? ' & ' : '').$langs->transcountry("LT2", $mysoc->country_code); - $text .= ''; } } @@ -273,15 +293,20 @@ if ($mysoc->useLocalTax(1) || $mysoc->useLocalTax(2)) { $title .= ' - '.$langs->trans("PDFLocaltax", $locales); } + print load_fiche_titre($title, '', ''); print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("ShowVATIntaInAddress").''; -print $form->selectyesno('MAIN_TVAINTRA_NOT_IN_ADDRESS', (!empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS)) ? $conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_TVAINTRA_NOT_IN_ADDRESS'); +} else { + print $form->selectyesno('MAIN_TVAINTRA_NOT_IN_ADDRESS', (!empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS)) ? $conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS : 0, 1); +} print '
    '.$langs->trans("ShowProfIdInAddress").' - '.$pid.''; $keyforconstant = 'MAIN_PROFID'.$i.'_IN_ADDRESS'; - print $form->selectyesno($keyforconstant, isset($conf->global->$keyforconstant) ? $conf->global->$keyforconstant : 0, 1, $noCountryCode); + if ($conf->use_javascript_ajax) { + print ajax_constantonoff($keyforconstant); + } else { + print $form->selectyesno($keyforconstant, isset($conf->global->$keyforconstant) ? $conf->global->$keyforconstant : 0, 1, $noCountryCode); + } print '
    '.$langs->trans("HideLocalTaxOnPDF", $langs->transcountry("LT1", $mysoc->country_code)).''; - $text .= $form->selectyesno('MAIN_PDF_MAIN_HIDE_SECOND_TAX', (!empty($conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX)) ? $conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX : 0, 1); + $text = '
    '.$langs->trans("HideLocalTaxOnPDF", $langs->transcountry("LT1", $mysoc->country_code)).''; + if ($conf->use_javascript_ajax) { + $text .= ajax_constantonoff('MAIN_PDF_MAIN_HIDE_SECOND_TAX'); + } else { + $text .= $form->selectyesno('MAIN_PDF_MAIN_HIDE_SECOND_TAX', (!empty($conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX)) ? $conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX : 0, 1); + } $text .= '
    '.$langs->trans("HideLocalTaxOnPDF", $langs->transcountry("LT2", $mysoc->country_code)).''; - $text .= $form->selectyesno('MAIN_PDF_MAIN_HIDE_THIRD_TAX', (!empty($conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX)) ? $conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX : 0, 1); + $text .= '
    '.$langs->trans("HideLocalTaxOnPDF", $langs->transcountry("LT2", $mysoc->country_code)).''; + if ($conf->use_javascript_ajax) { + $text .= ajax_constantonoff('MAIN_PDF_MAIN_HIDE_THIRD_TAX'); + } else { + $text .= $form->selectyesno('MAIN_PDF_MAIN_HIDE_THIRD_TAX', (!empty($conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX)) ? $conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX : 0, 1); + } $text .= '
    '; -print ''; +print ''; // Hide any information on Sale tax / VAT print ''; // Locataxes @@ -317,13 +342,21 @@ if (!empty($conf->projet->enabled)) { //Invert sender and recipient print ''; // Place customer adress to the ISO location print ''; // Use 2 languages into PDF @@ -341,25 +374,41 @@ print ''; //Desc print ''; //Ref print ''; //Details print ''; // SHOW_SUBPRODUCT_REF_IN_PDF - Option to show the detail of product ref for kits. print ''; // Show more details in footer diff --git a/htdocs/admin/pdf_other.php b/htdocs/admin/pdf_other.php new file mode 100644 index 00000000000..03c27fd3721 --- /dev/null +++ b/htdocs/admin/pdf_other.php @@ -0,0 +1,129 @@ + + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2012-2107 Juanjo Menent + * Copyright (C) 2019 Ferran Marcet + * Copyright (C) 2021 Anthony Berton + * + * 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/admin/pdf.php + * \brief Page to setup PDF options + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array('admin', 'languages', 'other', 'companies', 'products', 'members', 'stocks', 'Trips')); + +if (!$user->admin) { + accessforbidden(); +} + +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'alpha'); + + +/* + * Actions + */ + +if ($cancel) { + $action = ''; +} + +if ($action == 'update') { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + + header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); + exit; +} + + + +/* + * View + */ + +$wikihelp = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones'; +llxHeader('', $langs->trans("Setup"), $wikihelp); + +$form = new Form($db); +$formother = new FormOther($db); +$formadmin = new FormAdmin($db); + +print load_fiche_titre($langs->trans("PDF"), '', 'title_setup'); + +$head = pdf_admin_prepare_head(); + +print dol_get_fiche_head($head, 'other', $langs->trans("other"), -1, 'pdf'); + +print ''.$form->textwithpicto($langs->trans("PDFOtherDesc"), $s)."
    \n"; +print "
    \n"; + +print load_fiche_titre($langs->trans("Proposal"), '', ''); + +print '
    '; +print ''; +print ''; + +print '
    '; +print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("HideAnyVATInformationOnPDF").''; -print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT'); +} else { + print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT : 0, 1); +} print '
    '.$langs->trans("SwapSenderAndRecipientOnPDF").''; -print $form->selectyesno('MAIN_INVERT_SENDER_RECIPIENT', (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) ? $conf->global->MAIN_INVERT_SENDER_RECIPIENT : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_INVERT_SENDER_RECIPIENT'); +} else { + print $form->selectyesno('MAIN_INVERT_SENDER_RECIPIENT', (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) ? $conf->global->MAIN_INVERT_SENDER_RECIPIENT : 0, 1); +} print '
    '.$langs->trans("PlaceCustomerAddressToIsoLocation").''; -print $form->selectyesno('MAIN_PDF_USE_ISO_LOCATION', (!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION)) ? $conf->global->MAIN_PDF_USE_ISO_LOCATION : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_PDF_USE_ISO_LOCATION'); +} else { + print $form->selectyesno('MAIN_PDF_USE_ISO_LOCATION', (!empty($conf->global->MAIN_PDF_USE_ISO_LOCATION)) ? $conf->global->MAIN_PDF_USE_ISO_LOCATION : 0, 1); +} print '
    '.$langs->trans("HideDescOnPDF").''; -print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_DESC', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_GENERATE_DOCUMENTS_HIDE_DESC'); +} else { + print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_DESC', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC : 0, 1); +} print '
    '.$langs->trans("HideRefOnPDF").''; -print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_REF', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_GENERATE_DOCUMENTS_HIDE_REF'); +} else { + print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_REF', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF : 0, 1); +} print '
    '.$langs->trans("HideDetailsOnPDF").''; -print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS'); +} else { + print $form->selectyesno('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS', (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS)) ? $conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS : 0, 1); +} print '
    '.$langs->trans("SHOW_SUBPRODUCT_REF_IN_PDF", $langs->transnoentitiesnoconv("AssociatedProductsAbility"), $langs->transnoentitiesnoconv("Products")).''; -print $form->selectyesno('SHOW_SUBPRODUCT_REF_IN_PDF', (!empty($conf->global->SHOW_SUBPRODUCT_REF_IN_PDF)) ? $conf->global->SHOW_SUBPRODUCT_REF_IN_PDF : 0, 1); +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('SHOW_SUBPRODUCT_REF_IN_PDF'); +} else { + print $form->selectyesno('SHOW_SUBPRODUCT_REF_IN_PDF', (!empty($conf->global->SHOW_SUBPRODUCT_REF_IN_PDF)) ? $conf->global->SHOW_SUBPRODUCT_REF_IN_PDF : 0, 1); +} print '
    '; +print ''; + +print ''; + +/* +print ''; +*/ + +print '
    '.$langs->trans("Parameter").''.$langs->trans("Value").'
    '.$langs->trans("MAIN_GENERATE_PROPOSALS_WITH_PICTURE"); +print ' ('.$langs->trans("RandomlySelectedIfSeveral").')'; +print ''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_GENERATE_PROPOSALS_WITH_PICTURE'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("MAIN_GENERATE_PROPOSALS_WITH_PICTURE", $arrval, $conf->global->MAIN_GENERATE_PROPOSALS_WITH_PICTURE); +} +print '
    '.$langs->trans("MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING", $arrval, $conf->global->MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING); +} +print '
    '; +print '
    '; + + +print '
    '; +print ''; +print '
    '; + +print ''; + + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/admin/receiptprinter.php b/htdocs/admin/receiptprinter.php index 704473ac597..f1b74146c5e 100644 --- a/htdocs/admin/receiptprinter.php +++ b/htdocs/admin/receiptprinter.php @@ -431,7 +431,9 @@ if ($mode == 'template' && $user->admin) { print ''; print ''; print ''; - print ''; + print ''; + print '
    '; + print ''; } else { print ''.$printer->listprinterstemplates[$line]['name'].''; print ''.dol_htmlentitiesbr($printer->listprinterstemplates[$line]['template']).''; @@ -459,18 +461,15 @@ if ($mode == 'template' && $user->admin) { print ''; print ''; - print ''; + print ''; + print ''; + print ''; + print ''; print ''; } print ''; - if ($action != 'edittemplate') { - print ''; - print '
    '; - } else { - print '
    '; - } print ''; print dol_get_fiche_end(); diff --git a/htdocs/admin/reception_extrafields.php b/htdocs/admin/reception_extrafields.php index ab7d18b1331..8e4205a7bdc 100644 --- a/htdocs/admin/reception_extrafields.php +++ b/htdocs/admin/reception_extrafields.php @@ -84,7 +84,7 @@ print "
    \n"; $head = reception_admin_prepare_head(); -print dol_get_fiche_head($head, 'attributes_reception', $langs->trans("Receptions"), -1, 'sending'); +print dol_get_fiche_head($head, 'attributes_reception', $langs->trans("Receptions"), -1, 'reception'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/admin/reception_setup.php b/htdocs/admin/reception_setup.php index 734c953a092..7cc9ae3e3be 100644 --- a/htdocs/admin/reception_setup.php +++ b/htdocs/admin/reception_setup.php @@ -172,12 +172,13 @@ print load_fiche_titre($langs->trans("ReceptionsSetup"), $linkback, 'title_setup print '
    '; $head = reception_admin_prepare_head(); -print dol_get_fiche_head($head, 'reception', $langs->trans("Receptions"), -1, 'sending'); +print dol_get_fiche_head($head, 'reception', $langs->trans("Receptions"), -1, 'reception'); // Reception numbering model print load_fiche_titre($langs->trans("ReceptionsNumberingModules")); +print '
    '; print ''; print ''; print ''; @@ -272,8 +273,10 @@ foreach ($dirmodels as $reldir) { } } -print '
    '.$langs->trans("Name").'

    '; +print ''; +print '
    '; +print '
    '; /* * Documents models for Receptions Receipt @@ -302,6 +305,7 @@ if ($resql) { dol_print_error($db); } +print '
    '; print ''; print ''; print ''; @@ -417,6 +421,8 @@ foreach ($dirmodels as $reldir) { } print '
    '.$langs->trans("Name").'
    '; +print '
    '; + print '
    '; diff --git a/htdocs/admin/resource.php b/htdocs/admin/resource.php index b8bb566c79b..06ae59d64a3 100644 --- a/htdocs/admin/resource.php +++ b/htdocs/admin/resource.php @@ -74,6 +74,7 @@ print '
    '; print ''; print ''; +print '
    '; print ''; print ''; print ''."\n"; @@ -132,6 +133,7 @@ print ''; print ''; print '
    '.$langs->trans("Parameters").'
    '; +print '
    '; print '
    '; diff --git a/htdocs/admin/security.php b/htdocs/admin/security.php index 9ce22b7c08e..b1dd28956dc 100644 --- a/htdocs/admin/security.php +++ b/htdocs/admin/security.php @@ -71,7 +71,7 @@ if ($action == 'activate_encrypt') { if (dol_hash($obj->pass)) { $sql = "UPDATE ".MAIN_DB_PREFIX."user"; $sql .= " SET pass_crypted = '".dol_hash($obj->pass)."', pass = NULL"; - $sql .= " WHERE rowid=".$obj->rowid; + $sql .= " WHERE rowid=".((int) $obj->rowid); //print $sql; $resql2 = $db->query($sql); @@ -394,18 +394,18 @@ print ''; print ''; print ''.$langs->trans("DoNotStoreClearPassword").''; print ''; -if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) { +if (getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { print img_picto($langs->trans("Active"), 'tick'); } print ''; -if (!$conf->global->DATABASE_PWD_ENCRYPTED) { +if (!getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { print ''; print ''.$langs->trans("Activate").''; print ""; } // Database conf file encryption -if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) { +if (getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { print ''; if ($allow_disable_encryption) { //On n'autorise pas l'annulation de l'encryption car les mots de passe ne peuvent pas etre decodes @@ -453,16 +453,16 @@ print ''; print ''; print ''.$langs->trans("DisableForgetPasswordLinkOnLogonPage").''; print ''; -if (!empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK)) { +if (getDolGlobalString('MAIN_SECURITY_DISABLEFORGETPASSLINK')) { print img_picto($langs->trans("Active"), 'tick'); } print ''; -if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK)) { +if (!getDolGlobalString('MAIN_SECURITY_DISABLEFORGETPASSLINK')) { print ''; print ''.$langs->trans("Activate").''; print ""; } -if (!empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK)) { +if (getDolGlobalString('MAIN_SECURITY_DISABLEFORGETPASSLINK')) { print ''; print ''.$langs->trans("Disable").''; print ""; @@ -481,8 +481,8 @@ if (GETPOST('info', 'int') > 0) { } else { print $langs->trans("Note: The function password_hash does not exists on your PHP")."
    \n"; } - print 'MAIN_SECURITY_HASH_ALGO = '.$conf->global->MAIN_SECURITY_HASH_ALGO."
    \n"; - print 'MAIN_SECURITY_SALT = '.$conf->global->MAIN_SECURITY_SALT."
    \n"; + print 'MAIN_SECURITY_HASH_ALGO = '.getDolGlobalString('MAIN_SECURITY_HASH_ALGO')."
    \n"; + print 'MAIN_SECURITY_SALT = '.getDolGlobalString('MAIN_SECURITY_SALT')."
    \n"; } print '
    '; diff --git a/htdocs/admin/security_file.php b/htdocs/admin/security_file.php index 2b6a4e81fb4..12c90cf3c21 100644 --- a/htdocs/admin/security_file.php +++ b/htdocs/admin/security_file.php @@ -66,7 +66,7 @@ if ($action == 'updateform') { } elseif ($action == 'delete') { // Delete file $langs->load("other"); - $file = $conf->admin->dir_temp.'/'.GETPOST('urlfile', 'alpha'); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). + $file = $conf->admin->dir_temp.'/'.GETPOST('urlfile', 'alpha'); $ret = dol_delete_file($file); if ($ret) { setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile', 'alpha')), null, 'mesgs'); diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 55d6a518250..a4a9e91e3ff 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -743,6 +743,23 @@ if ($conf->use_javascript_ajax) { } print "\n"; print "\n"; + +/* Disabled. Would be better to be managed with a user cookie +if (!empty($conf->productbatch->enabled)) { + print ''; + print '' . $langs->trans("ShowAllBatchByDefault") . ''; + print ''; + if ($conf->use_javascript_ajax) { + print ajax_constantonoff('STOCK_SHOW_ALL_BATCH_BY_DEFAULT'); + } else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("STOCK_SHOW_ALL_BATCH_BY_DEFAULT", $arrval, $conf->global->STOCK_SHOW_ALL_BATCH_BY_DEFAULT); + } + print "\n"; + print "\n"; +} +*/ + print ''; print ''; diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index b4131a4bdde..9af09164469 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -139,8 +139,8 @@ if (preg_match('/[a-z]+/i', $version)) { } print ''."\n"; -print ''.$langs->trans("VersionLastUpgrade").' ('.$langs->trans("Database").')'.$conf->global->MAIN_VERSION_LAST_UPGRADE.''."\n"; -print ''.$langs->trans("VersionLastInstall").''.$conf->global->MAIN_VERSION_LAST_INSTALL.''."\n"; +print ''.$langs->trans("VersionLastUpgrade").' ('.$langs->trans("Database").')'.getDolGlobalString('MAIN_VERSION_LAST_UPGRADE').''."\n"; +print ''.$langs->trans("VersionLastInstall").''.getDolGlobalString('MAIN_VERSION_LAST_INSTALL').''."\n"; print ''; print ''; print '
    '; diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index 3869c37ce7d..212fcc6228a 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -53,8 +53,8 @@ print ''.$langs->trans("FileCheckDesc").'
    print '
    '; print ''; print ''."\n"; -print ''."\n"; -print ''."\n"; +print ''."\n"; +print ''."\n"; print ''; + print ''; } if ($arrayfields['id']['checked']) { diff --git a/htdocs/admin/system/perf.php b/htdocs/admin/system/perf.php index b1014cc98c7..2a8dfa975cd 100644 --- a/htdocs/admin/system/perf.php +++ b/htdocs/admin/system/perf.php @@ -75,7 +75,7 @@ print '
    '; print ''.$langs->trans("Syslog").': '; $test = empty($conf->syslog->enabled); if ($test) { - print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotSlowedDownByThis"); + print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' '.$langs->trans("NotSlowedDownByThis").''; } else { if ($conf->global->SYSLOG_LEVEL > LOG_NOTICE) { print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedWithTooHighLogLevel", $langs->transnoentities("Syslog")); @@ -91,7 +91,7 @@ print '
    '; print ''.$langs->trans("DebugBar").': '; $test = empty($conf->debugbar->enabled); if ($test) { - print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotSlowedDownByThis"); + print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' '.$langs->trans("NotSlowedDownByThis").''; } else { print img_picto('', 'warning').' '.$langs->trans("ModuleActivated", $langs->transnoentities("DebugBar")); //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; @@ -111,7 +111,7 @@ if ($test) { print ' Memcached module admin page'; } } else { - print img_picto('', 'warning').' '.$langs->trans("MemcachedNotAvailable"); + print $langs->trans("MemcachedNotAvailable"); } print '
    '; @@ -464,11 +464,99 @@ if ($conf->db->type == 'mysql' || $conf->db->type == 'mysqli') { print '
    '; } -// Product search +print '
    '; +print ''.$langs->trans("ComboListOptim").': '; +print '
    '; +// Product combo list +$sql = "SELECT COUNT(*) as nb"; +$sql .= " FROM ".MAIN_DB_PREFIX."product as p"; +$resql = $db->query($sql); +if ($resql) { + $limitforoptim = 5000; + $num = $db->num_rows($resql); + $obj = $db->fetch_object($resql); + $nb = $obj->nb; + if ($nb > $limitforoptim) { + if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { + print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseComboOptim", $nb, $langs->transnoentitiesnoconv("ProductsOrServices"), 'PRODUIT_USE_SEARCH_TO_SELECT'); + } else { + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ProductsOrServices"), 'PRODUIT_USE_SEARCH_TO_SELECT', $conf->global->PRODUIT_USE_SEARCH_TO_SELECT); + } + } else { + print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("ProductsOrServices")); + } + print '
    '; + $db->free($resql); +} +// Thirdparty combo list +$sql = "SELECT COUNT(*) as nb"; +$sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; +$resql = $db->query($sql); +if ($resql) { + $limitforoptim = 5000; + $num = $db->num_rows($resql); + $obj = $db->fetch_object($resql); + $nb = $obj->nb; + if ($nb > $limitforoptim) { + if (empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT)) { + print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseComboOptim", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'COMPANY_USE_SEARCH_TO_SELECT'); + } else { + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'COMPANY_USE_SEARCH_TO_SELECT', $conf->global->COMPANY_USE_SEARCH_TO_SELECT); + } + } else { + print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("ThirdParties")); + } + print '
    '; + $db->free($resql); +} +// Contact combo list +$sql = "SELECT COUNT(*) as nb"; +$sql .= " FROM ".MAIN_DB_PREFIX."socpeople as s"; +$resql = $db->query($sql); +if ($resql) { + $limitforoptim = 5000; + $num = $db->num_rows($resql); + $obj = $db->fetch_object($resql); + $nb = $obj->nb; + if ($nb > $limitforoptim) { + if (empty($conf->global->CONTACT_USE_SEARCH_TO_SELECT)) { + print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseComboOptim", $nb, $langs->transnoentitiesnoconv("Contacts"), 'CONTACT_USE_SEARCH_TO_SELECT'); + } else { + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("Contacts"), 'CONTACT_USE_SEARCH_TO_SELECT', $conf->global->CONTACT_USE_SEARCH_TO_SELECT); + } + } else { + print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("Contacts")); + } + print '
    '; + $db->free($resql); +} +// Contact combo list +$sql = "SELECT COUNT(*) as nb"; +$sql .= " FROM ".MAIN_DB_PREFIX."projet as s"; +$resql = $db->query($sql); +if ($resql) { + $limitforoptim = 5000; + $num = $db->num_rows($resql); + $obj = $db->fetch_object($resql); + $nb = $obj->nb; + if ($nb > $limitforoptim) { + if (empty($conf->global->PROJECT_USE_SEARCH_TO_SELECT)) { + print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseComboOptim", $nb, $langs->transnoentitiesnoconv("Projects"), 'PROJECT_USE_SEARCH_TO_SELECT'); + } else { + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("Projects"), 'PROJECT_USE_SEARCH_TO_SELECT', $conf->global->PROJECT_USE_SEARCH_TO_SELECT); + } + } else { + print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("Projects")); + } + print '
    '; + $db->free($resql); +} + + print '
    '; print ''.$langs->trans("SearchOptim").': '; print '
    '; -$tab = array(); +// Product search $sql = "SELECT COUNT(*) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; $resql = $db->query($sql); @@ -480,8 +568,9 @@ if ($resql) { if ($nb > $limitforoptim) { if (empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE)) { print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseSearchOptim", $nb, $langs->transnoentitiesnoconv("ProductsOrServices"), 'PRODUCT_DONOTSEARCH_ANYWHERE'); + print $langs->trans("YouHaveXObjectUseSearchOptimDesc"); } else { - print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ProductsOrServices")); + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ProductsOrServices"), 'PRODUCT_DONOTSEARCH_ANYWHERE', $conf->global->PRODUCT_DONOTSEARCH_ANYWHERE); } } else { print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("ProductsOrServices")); @@ -491,20 +580,20 @@ if ($resql) { } // Thirdparty search -$tab = array(); $sql = "SELECT COUNT(*) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $resql = $db->query($sql); if ($resql) { - $limitforoptim = 10000; + $limitforoptim = 100000; $num = $db->num_rows($resql); $obj = $db->fetch_object($resql); $nb = $obj->nb; if ($nb > $limitforoptim) { if (empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)) { print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseSearchOptim", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'COMPANY_DONOTSEARCH_ANYWHERE'); + print $langs->trans("YouHaveXObjectUseSearchOptimDesc"); } else { - print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ThirdParties")); + print img_picto('', 'tick.png').' '.$langs->trans("YouHaveXObjectAndSearchOptimOn", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'COMPANY_DONOTSEARCH_ANYWHERE', $conf->global->COMPANY_DONOTSEARCH_ANYWHERE); } } else { print img_picto('', 'tick.png').' '.$langs->trans("NbOfObjectIsLowerThanNoPb", $nb, $langs->transnoentitiesnoconv("ThirdParties")); diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php index c9a652cd4e4..3e01a99cb61 100644 --- a/htdocs/admin/system/security.php +++ b/htdocs/admin/system/security.php @@ -40,6 +40,8 @@ if (GETPOST('action', 'aZ09') == 'donothing') { exit; } +$execmethod = empty($conf->global->MAIN_EXEC_USE_POPEN) ? 1 : $conf->global->MAIN_EXEC_USE_POPEN; + /* * View @@ -63,18 +65,43 @@ if (function_exists('php_ini_loaded_file')) { } print "
    \n"; -// Get versionof web server -print "
    Web server - ".$langs->trans("Version").": ".$_SERVER["SERVER_SOFTWARE"]."
    \n"; +// Get version of web server +print "
    Web server - ".$langs->trans("Version").": ".$_SERVER["SERVER_SOFTWARE"]."
    \n"; +print ''.$langs->trans("DataRootServer").": ".DOL_DATA_ROOT."
    \n"; +// Web user group by default +$labeluser = dol_getwebuser('user'); +$labelgroup = dol_getwebuser('group'); +if ($labeluser && $labelgroup) { + print ''.$langs->trans("WebUserGroup")." (env vars) : ".$labeluser.':'.$labelgroup; + if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) { + $arrayofinfoofuser = posix_getpwuid(posix_geteuid()); + print ' (POSIX '.$arrayofinfoofuser['name'].':'.$arrayofinfoofuser['gecos'].':'.$arrayofinfoofuser['dir'].':'.$arrayofinfoofuser['shell'].')
    '."\n"; + } +} +// Web user group real (detected by 'id' external command) +if (function_exists('exec')) { + $arrayout = array(); $varout = 0; + exec('id', $arrayout, $varout); + if (empty($varout)) { // Test command is ok. Work only on Linux OS. + print ''.$langs->trans("WebUserGroup")." (real, 'id' command) : ".join(',', $arrayout)."
    \n"; + } +} print '
    '; print "PHP safe_mode = ".(ini_get('safe_mode') ? ini_get('safe_mode') : yn(0)).'   '.$langs->trans("Deprecated")." (removed in PHP 5.4)
    \n"; -print "PHP open_basedir = ".(ini_get('open_basedir') ? ini_get('open_basedir') : yn(0).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("ARestrictedPath")).')')."
    \n"; +print "PHP open_basedir = ".(ini_get('open_basedir') ? ini_get('open_basedir') : yn(0).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("ARestrictedPath").', '.$langs->transnoentitiesnoconv("Example").' '.$_SERVER["DOCUMENT_ROOT"]).')')."
    \n"; print "PHP allow_url_fopen = ".(ini_get('allow_url_fopen') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_fopen') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")
    \n"; print "PHP allow_url_include = ".(ini_get('allow_url_include') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_include') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")
    \n"; print "PHP disable_functions = "; $arrayoffunctionsdisabled = explode(',', ini_get('disable_functions')); $arrayoffunctionstodisable = explode(',', 'pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals'); -$arrayoffunctionstodisable2 = explode(',', 'exec,passthru,shell_exec,system,proc_open,popen'); +if ($execmethod == 1) { + $arrayoffunctionstodisable2 = explode(',', 'passthru,shell_exec,system,proc_open,popen'); + $functiontokeep = 'exec'; +} else { + $arrayoffunctionstodisable2 = explode(',', 'exec,passthru,shell_exec,system,proc_open'); + $functiontokeep = 'popen'; +} $i = 0; foreach ($arrayoffunctionsdisabled as $functionkey) { if ($i > 0) { @@ -115,6 +142,13 @@ if ($todisabletext) { print '
    '; } +print $langs->trans("PHPFunctionsRequiredForCLI").': '; +if (in_array($functiontokeep, $arrayoffunctionsdisabled)) { + print img_picto($langs->trans("PHPFunctionsRequiredForCLI"), 'warning'); +} +print ''.$functiontokeep.''; +print '
    '; + print '
    '; // XDebug @@ -128,39 +162,20 @@ if ($test) { } print '
    '; -print '
    '; -print '
    '; -print load_fiche_titre($langs->trans("ConfigurationFile").' ('.$conffile.')', '', 'folder'); -print ''.$langs->trans("dolibarr_main_prod").': '.$dolibarr_main_prod; -if (empty($dolibarr_main_prod)) { - print '   '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 1); -} -print '
    '; - -print ''.$langs->trans("dolibarr_nocsrfcheck").': '.$dolibarr_nocsrfcheck; -if (!empty($dolibarr_nocsrfcheck)) { - print img_picto('', 'warning').'   '.$langs->trans("IfYouAreOnAProductionSetThis", 0); -} -print '
    '; - -print ''.$langs->trans("dolibarr_main_restrict_ip").': '.$dolibarr_main_restrict_ip; -/*if (empty($dolibarr_main_restrict_ip)) { - print '   '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 1); -}*/ -print '
    '; +// OS Permissions print '
    '; print '
    '; print '
    '; -print load_fiche_titre($langs->trans("PermissionsOnFiles"), '', 'folder'); +print load_fiche_titre($langs->trans("OSSetup").' - '.$langs->trans("PermissionsOnFiles"), '', 'folder'); print ''.$langs->trans("PermissionsOnFilesInWebRoot").': '; $arrayoffilesinroot = dol_dir_list(DOL_DOCUMENT_ROOT, 'all', 1, '', array('\/custom'), 'name', SORT_ASC, 4, 1, '', 1); $fileswithwritepermission = array(); foreach ($arrayoffilesinroot as $fileinroot) { - // Test permission on file - if ($fileinroot['perm'] & 0222) { + // Test if there is at least one write permission file. If yes, add the entry into array $fileswithwritepermission + if (isset($fileinroot['perm']) && ($fileinroot['perm'] & 0222)) { $fileswithwritepermission[] = $fileinroot['relativename']; } } @@ -205,48 +220,65 @@ if ($perms) { } print '
    '; -print '
    '; + +// File conf.php print '
    '; print '
    '; -print load_fiche_titre($langs->trans("Modules"), '', 'folder'); +print '
    '; +print load_fiche_titre($langs->trans("ConfigurationFile").' ('.$conffile.')', '', 'folder'); -// Module log -print ''.$langs->trans("Syslog").': '; -$test = empty($conf->syslog->enabled); -if ($test) { - print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); -} else { - if ($conf->global->SYSLOG_LEVEL > LOG_NOTICE) { - print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedMayExposeInformation", $langs->transnoentities("Syslog")); +print '$dolibarr_main_prod: '.($dolibarr_main_prod ? $dolibarr_main_prod : '0'); +if (empty($dolibarr_main_prod)) { + print '   '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 1); +} +print '
    '; + +print '$dolibarr_nocsrfcheck: '.$dolibarr_nocsrfcheck; +if (!empty($dolibarr_nocsrfcheck)) { + print '   '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 0); +} +print '
    '; + +print '$dolibarr_main_restrict_ip: '; +if (empty($dolibarr_main_restrict_ip)) { + print ''.$langs->trans("None").''; + //print ' ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')'; +} + +print '
    '; + +if (empty($conf->global->SECURITY_DISABLE_TEST_ON_OBFUSCATED_CONF)) { + print '$dolibarr_main_db_pass: '; + if (!empty($dolibarr_main_db_pass) && empty($dolibarr_main_db_encrypted_pass)) { + print img_picto('', 'warning').' '.$langs->trans("DatabasePasswordNotObfuscated").'   ('.$langs->trans("Recommanded").': '.$langs->trans("SetOptionTo", $langs->transnoentitiesnoconv("MainDbPasswordFileConfEncrypted"), yn(1)).')'; + //print ' ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')'; } else { - print img_picto('', 'tick.png').' '.$langs->trans("ModuleSyslogActivatedButLevelNotTooVerbose", $langs->transnoentities("Syslog"), $conf->global->SYSLOG_LEVEL); + print img_picto('', 'tick').' '.$langs->trans("DatabasePasswordObfuscated"); } - //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; -} -print '
    '; -// Module debugbar -print ''.$langs->trans("DebugBar").': '; -$test = empty($conf->debugbar->enabled); -if ($test) { - print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); -} else { - print img_picto('', 'error').' '.$langs->trans("ModuleActivatedDoNotUseInProduction", $langs->transnoentities("DebugBar")); - //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; + print '
    '; } -print '
    '; + + + +// Menu security print '
    '; print '
    '; print '
    '; -print load_fiche_titre($langs->trans("Menu").' '.$langs->trans("SecuritySetup"), '', 'folder'); +print load_fiche_titre($langs->trans("Menu").' '.$langs->trans("SecuritySetup").' + '.$langs->trans("OtherSetup"), '', 'folder'); //print ''.$langs->trans("PasswordEncryption").': '; -print 'MAIN_SECURITY_HASH_ALGO = '.(empty($conf->global->MAIN_SECURITY_HASH_ALGO) ? $langs->trans("Undefined") : '')."   "; -print '     If unset: \'md5\'
    '; +print 'MAIN_SECURITY_HASH_ALGO = '.(empty($conf->global->MAIN_SECURITY_HASH_ALGO) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_HASH_ALGO)."   "; +if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) { + print '     If unset: \'md5\''; +} if ($conf->global->MAIN_SECURITY_HASH_ALGO != 'password_hash') { - print 'MAIN_SECURITY_SALT = '.(empty($conf->global->MAIN_SECURITY_SALT) ? $langs->trans("Undefined") : $conf->global->MAIN_SECURITY_SALT).'
    '; + print '
    MAIN_SECURITY_SALT = '.(empty($conf->global->MAIN_SECURITY_SALT) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_SALT).'
    '; +} else { + print '('.$langs->trans("Recommanded").': password_hash)'; + print '
    '; } if ($conf->global->MAIN_SECURITY_HASH_ALGO != 'password_hash') { print '
    The recommanded value for MAIN_SECURITY_HASH_ALGO is now \'password_hash\' but setting it now will make ALL existing passwords of all users not valid, so update is not possible.
    '; @@ -258,9 +290,32 @@ if ($conf->global->MAIN_SECURITY_HASH_ALGO != 'password_hash') { } print '
    '; + +print 'MAIN_SECURITY_ANTI_SSRF_SERVER_IP = '.(empty($conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP) ? ''.$langs->trans("Undefined").'   ('.$langs->trans("Example").': static-ips-of-server - '.$langs->trans("Note").': common loopback ip like 127.*.*.*, [::1] are already added)' : $conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP)."
    "; +print '
    '; + +print 'MAIN_ALLOW_SVG_FILES_AS_IMAGES = '.(empty($conf->global->MAIN_ALLOW_SVG_FILES_AS_IMAGES) ? '0   ('.$langs->trans("Recommanded").': 0)' : $conf->global->MAIN_ALLOW_SVG_FILES_AS_IMAGES)."
    "; +print '
    '; + +print 'MAIN_EXEC_USE_POPEN = '; +if (empty($conf->global->MAIN_EXEC_USE_POPEN)) { + print ''.$langs->trans("Undefined").''; +} else { + print $conf->global->MAIN_EXEC_USE_POPEN; +} +if ($execmethod == 1) { + print '   ("exec" PHP method will be used for shell commands)'; +} +if ($execmethod == 2) { + print '   ("popen" PHP method will be used for shell commands)'; +} +print "
    "; +print '
    '; + + print ''.$langs->trans("AntivirusEnabledOnUpload").': '; print empty($conf->global->MAIN_ANTIVIRUS_COMMAND) ? '' : img_picto('', 'tick').' '; -print yn($conf->global->MAIN_ANTIVIRUS_COMMAND ? 1 : 0); +print yn(empty($conf->global->MAIN_ANTIVIRUS_COMMAND) ? 0 : 1); if (!empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { print '   - '.$conf->global->MAIN_ANTIVIRUS_COMMAND; if (defined('MAIN_ANTIVIRUS_COMMAND')) { @@ -268,7 +323,6 @@ if (!empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { } } print '
    '; - print '
    '; $securityevent = new Events($db); @@ -291,11 +345,69 @@ if (!empty($eventstolog) && is_array($eventstolog)) { } } } + print '
    '; } else { - print img_warning().' '.$langs->trans("NoSecurityEventsAreAduited", $langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Audit")); + print img_warning().' '.$langs->trans("NoSecurityEventsAreAduited", $langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Audit")).'
    '; } +// Modules/Applications + +print '
    '; +print '
    '; +print '
    '; +print load_fiche_titre($langs->trans("Modules"), '', 'folder'); + +// Module log +print ''.$langs->trans("Syslog").': '; +$test = empty($conf->syslog->enabled); +if ($test) { + print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); +} else { + if ($conf->global->SYSLOG_LEVEL > LOG_NOTICE) { + print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedWithTooHighLogLevel", $langs->transnoentities("Syslog")); + } else { + print img_picto('', 'tick.png').' '.$langs->trans("ModuleSyslogActivatedButLevelNotTooVerbose", $langs->transnoentities("Syslog"), $conf->global->SYSLOG_LEVEL); + } + //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; +} +print '
    '; + +// Module debugbar +print ''.$langs->trans("DebugBar").': '; +$test = empty($conf->debugbar->enabled); +if ($test) { + print img_picto('', 'tick.png').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); +} else { + print img_picto('', 'error').' '.$langs->trans("ModuleActivatedDoNotUseInProduction", $langs->transnoentities("DebugBar")); + //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; +} +print '
    '; + + +// APIs + +print '
    '; +print '
    '; +print '
    '; +print load_fiche_titre($langs->trans("API"), '', 'folder'); + +if (empty($conf->api->enabled) && empty($conf->webservices->enabled)) { + print $langs->trans("APIsAreNotEnabled"); +} else { + if (!empty($conf->webservices->enabled)) { + print $langs->trans('YouEnableDeprecatedWSAPIsUseRESTAPIsInstead')."
    \n"; + print '
    '; + } + if (!empty($conf->api->enabled)) { + print 'API_ENDPOINT_RULES = '.(empty($conf->global->API_ENDPOINT_RULES) ? ''.$langs->trans("Undefined").'' : $conf->global->API_ENDPOINT_RULES)."
    \n"; + print '
    '; + } +} + + +print '

    '; + // End of page llxFooter(); $db->close(); diff --git a/htdocs/admin/taxes.php b/htdocs/admin/taxes.php index 0b553c8a8aa..a3b3a7f1d91 100644 --- a/htdocs/admin/taxes.php +++ b/htdocs/admin/taxes.php @@ -260,7 +260,7 @@ print "
    \n"; print '
    '; print ''; -print '

    '; +print '

    '; print '
    '; print ''; diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 108fe6a8e70..428c80676a2 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -157,7 +157,7 @@ $title = $langs->trans("BackupDumpWizard"); print load_fiche_titre($title); -print '
    '.$langs->trans("Version").''.$langs->trans("Value").'
    '.$langs->trans("VersionLastInstall").''.$conf->global->MAIN_VERSION_LAST_INSTALL.'
    '.$langs->trans("VersionLastUpgrade").''.$conf->global->MAIN_VERSION_LAST_UPGRADE.'
    '.$langs->trans("VersionLastInstall").''.getDolGlobalString('MAIN_VERSION_LAST_INSTALL').'
    '.$langs->trans("VersionLastUpgrade").''.getDolGlobalString('MAIN_VERSION_LAST_UPGRADE').'
    '.$langs->trans("VersionProgram").''.DOL_VERSION; // If current version differs from last upgrade if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE)) { @@ -110,7 +110,7 @@ print ''; print $langs->trans("MakeIntegrityAnalysisFrom").':
    '; print ''."\n"; if (dol_is_file($xmlfile)) { - print ' '.$langs->trans("LocalSignature").' = '; + print ' = '; print ''; print '
    '; } else { @@ -121,10 +121,10 @@ if (dol_is_file($xmlfile)) { } print ''."\n"; if ($enableremotecheck) { - print ' '.$langs->trans("RemoteSignature").' = '; - print '
    '; + print ' = '; + print '
    '; } else { - print ' '.$langs->trans("RemoteSignature").' = '.$xmlremote; + print ' '.$langs->trans("RemoteSignature").' = '.dol_escape_htmltag($xmlremote); if (!GETPOST('xmlremote')) { print ' ('.$langs->trans("FeatureAvailableOnlyOnStable").')'; } @@ -156,7 +156,7 @@ if (GETPOST('target') == 'local') { } } if (GETPOST('target') == 'remote') { - $xmlarray = getURLContent($xmlremote, 'GET', '', 1, array(), array('http', 'https'), 0); // Accept http or https links on external remote server only + $xmlarray = getURLContent($xmlremote, 'GET', '', 1, array(), array('http', 'https'), 0); // Accept http or https links on external remote server only. Same is used into api_setup.class.php. // Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...) if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '400' && $xmlarray['http_code'] != '404') { @@ -164,14 +164,14 @@ if (GETPOST('target') == 'remote') { //print "xmlfilestart".$xmlfile."xmlfileend"; $xml = simplexml_load_string($xmlfile); } else { - $errormsg = $langs->trans('XmlNotFound').': '.$xmlremote.' - '.$xmlarray['http_code'].' '.$xmlarray['curl_error_no'].' '.$xmlarray['curl_error_msg']; + $errormsg = $langs->trans('XmlNotFound').': '.$xmlremote.' - '.$xmlarray['http_code'].(($xmlarray['http_code'] == 400 && $xmlarray['content']) ? ' '.$xmlarray['content'] : '').' '.$xmlarray['curl_error_no'].' '.$xmlarray['curl_error_msg']; setEventMessages($errormsg, null, 'errors'); $error++; } } -if (!$error && $xml) { +if (empty($error) && !empty($xml)) { $checksumconcat = array(); $file_list = array(); $out = ''; @@ -226,9 +226,9 @@ if (!$error && $xml) { //var_dump($xml->dolibarr_htdocs_dir[0]['includecustom']);exit; $includecustom = (empty($xml->dolibarr_htdocs_dir[0]['includecustom']) ? 0 : $xml->dolibarr_htdocs_dir[0]['includecustom']); - // Defined qualified files (must be same than into generate_filelist_xml.php) - $regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$'; - $regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|conf|install|public\/test|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs + // Define qualified files (must be same than into generate_filelist_xml.php and in api_setup.class.php) + $regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$'; + $regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs $scanfiles = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude); // Fill file_list with files in signature, new files, modified files diff --git a/htdocs/admin/system/modules.php b/htdocs/admin/system/modules.php index 51f3b4577cf..150ca10a359 100644 --- a/htdocs/admin/system/modules.php +++ b/htdocs/admin/system/modules.php @@ -25,7 +25,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; -if (!$user->admin) { +if (empty($user->admin)) { accessforbidden(); } @@ -65,6 +65,7 @@ $arrayfields = array( ); $arrayfields = dol_sort_array($arrayfields, 'position'); +$param = ''; /* @@ -134,7 +135,7 @@ foreach ($modules as $key => $module) { $newModule->name = $module->getName(); $newModule->version = $module->getVersion(); $newModule->id = $key; - $newModule->module_position = $module->module_position; + $newModule->module_position = $module->getModulePosition(); $alt = $module->name.' - '.$modules_files[$key]; @@ -164,17 +165,17 @@ foreach ($modules as $key => $module) { $newModule->permission = $permission; // pre-filter list - if ($search_name && !stristr($newModule->name, $search_name)) { + if (!empty($search_name) && !stristr($newModule->name, $search_name)) { continue; } - if ($search_version && !stristr($newModule->version, $search_version)) { + if (!empty($search_version) && !stristr($newModule->version, $search_version)) { continue; } - if ($search_id && !stristr($newModule->id, $search_id)) { + if (!empty($search_id) && !stristr($newModule->id, $search_id)) { continue; } - if ($search_permission) { + if (!empty($search_permission)) { $found = false; foreach ($newModule->permission as $permission) { @@ -211,7 +212,7 @@ print ''; print ''; print ''; -print_barre_liste($langs->trans("AvailableModules"), $page, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $massactionbutton, -1, '', 'title_setup', 0, '', '', 0, 1, 1); +print_barre_liste($langs->trans("AvailableModules"), empty($page) ? 0 : $page, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', -1, '', 'title_setup', 0, '', '', 0, 1, 1); print ''.$langs->trans("ToActivateModule").''; print '
    '; @@ -324,7 +325,7 @@ foreach ($moduleList as $module) { } if ($arrayfields['version']['checked']) { - print '
    '.$module->version.''.$module->version.'
    '; +print '
    '; print ''; print ''; @@ -558,6 +559,12 @@ function show_stats_for_company($product, $socid) print ''; print ''; } + $parameters = array('socid'=>$socid); + $reshook = $hookmanager->executeHooks('addMoreProductStat', $parameters, $product, $nblines); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + print $hookmanager->resPrint; + return $nblines++; } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 0315e848e94..9c33744ceb0 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -2693,8 +2693,9 @@ function getTaskProgressView($task, $label = true, $progressNumber = true, $hide // define progress color according to time spend vs workload $progressBarClass = 'progress-bar-info'; + $progressCalculated = 0; if ($task->planned_workload) { - $progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2); + $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2); // this conf is actually hidden, by default we use 10% for "be carefull or warning" $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10; @@ -2702,12 +2703,12 @@ function getTaskProgressView($task, $label = true, $progressNumber = true, $hide $diffTitle = '
    '.$langs->trans('ProgressDeclared').' : '.$task->progress.($task->progress ? '%' : ''); $diffTitle .= '
    '.$langs->trans('ProgressCalculated').' : '.$progressCalculated.($progressCalculated ? '%' : ''); - //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.doubleval($task->progress * $warningRatio)); - if (doubleval($progressCalculated) > doubleval($task->progress * $warningRatio)) { + //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.floatval($task->progress * $warningRatio)); + if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) { $progressBarClass = 'progress-bar-danger'; $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point")); $diff = ' '.($task->progress - $progressCalculated).'%'; - } elseif (doubleval($progressCalculated) > doubleval($task->progress)) { // warning if close at 10% + } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10% $progressBarClass = 'progress-bar-warning'; $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point")); $diff = ' '.($task->progress - $progressCalculated).'%'; @@ -2771,18 +2772,18 @@ function getTaskProgressView($task, $label = true, $progressNumber = true, $hide $out .= ''; $out .= '
    '; - $diffval = doubleval($task->progress) - doubleval($progressCalculated); + $diffval = floatval($task->progress) - floatval($progressCalculated); if ($diffval >= 0) { // good - $out .= '
    '; + $out .= '
    '; if (!empty($task->progress)) { - $out .= '
    '; + $out .= '
    '; } $out .= '
    '; } else { // bad - $out .= '
    '; - $out .= '
    '; + $out .= '
    '; + $out .= '
    '; $out .= '
    '; } $out .= '
    '; @@ -2811,17 +2812,17 @@ function getTaskProgressBadge($task, $label = '', $tooltip = '') // define color according to time spend vs workload $badgeClass = 'badge '; if ($task->planned_workload) { - $progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2); + $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2); // this conf is actually hidden, by default we use 10% for "be carefull or warning" $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10; - if (doubleval($progressCalculated) > doubleval($task->progress * $warningRatio)) { + if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) { $badgeClass .= 'badge-danger'; if (empty($tooltip)) { $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } - } elseif (doubleval($progressCalculated) > doubleval($task->progress)) { // warning if close at 10% + } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10% $badgeClass .= 'badge-warning'; if (empty($tooltip)) { $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; diff --git a/htdocs/core/lib/propal.lib.php b/htdocs/core/lib/propal.lib.php index 3ddd3ab1b2b..38589c9e610 100644 --- a/htdocs/core/lib/propal.lib.php +++ b/htdocs/core/lib/propal.lib.php @@ -152,3 +152,141 @@ function propal_admin_prepare_head() return $head; } + + + +/** + * Return a HTML table that contains a pie chart of customer proposals + * + * @param int $socid (Optional) Show only results from the customer with this id + * @return string A HTML table that contains a pie chart of customer invoices + */ +function getCustomerProposalPieChart($socid = 0) +{ + global $conf, $db, $langs, $user; + + $result= ''; + + if (empty($conf->propal->enabled) || empty($user->rights->propal->lire)) { + return ''; + } + + $listofstatus = array(Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED); + + $propalstatic = new Propal($db); + + $sql = "SELECT count(p.rowid) as nb, p.fk_statut as status"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; + $sql .= ", ".MAIN_DB_PREFIX."propal as p"; + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= " WHERE p.entity IN (".getEntity($propalstatic->element).")"; + $sql .= " AND p.fk_soc = s.rowid"; + if ($user->socid) { + $sql .= ' AND p.fk_soc = '.$user->socid; + } + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; + } + $sql .= " AND p.fk_statut IN (".$db->sanitize(implode(" ,", $listofstatus)).")"; + $sql .= " GROUP BY p.fk_statut"; + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + $total = 0; + $totalinprocess = 0; + $dataseries = array(); + $colorseries = array(); + $vals = array(); + + while ($i < $num) { + $obj = $db->fetch_object($resql); + if ($obj) { + $vals[$obj->status] = $obj->nb; + $totalinprocess += $obj->nb; + + $total += $obj->nb; + } + $i++; + } + $db->free($resql); + + include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; + + $result = '
    '; + $result .= '
    '; print $langs->trans("DatabaseName").' : '.$dolibarr_main_db_name.'
    '; @@ -239,7 +239,7 @@ if (in_array($type, array('mysql', 'mysqli'))) { print ''; - print '
    '; + print '
    '; print ''; if ($obj->statut == 0) { // Not sent yet - if ($user->rights->mailing->creer && $allowaddtarget) { + if (!empty($user->rights->mailing->creer) && $allowaddtarget) { print ''.img_delete($langs->trans("RemoveRecipient")).''; } } diff --git a/htdocs/comm/mailing/class/advtargetemailing.class.php b/htdocs/comm/mailing/class/advtargetemailing.class.php index 0e7f2abe76d..9051ebfa921 100644 --- a/htdocs/comm/mailing/class/advtargetemailing.class.php +++ b/htdocs/comm/mailing/class/advtargetemailing.class.php @@ -616,6 +616,10 @@ class AdvanceTargetingMailing extends CommonObject if ($arrayquery['options_'.$key] != '') { $sqlwhere[] = " (te.".$key." = ".((int) $arrayquery['options_'.$key]).")"; } + } elseif ($extrafields->attributes[$elementtype]['type'][$key] == 'link') { + if ($arrayquery['options_'.$key] > 0) { + $sqlwhere[]= " (te.".$key." = ".((int) $arrayquery['options_'.$key]).")"; + } } else { if (is_array($arrayquery['options_'.$key])) { $sqlwhere[] = " (te.".$key." IN (".$this->db->sanitize("'".implode("','", $arrayquery['options_'.$key])."'", 1)."))"; @@ -642,7 +646,6 @@ class AdvanceTargetingMailing extends CommonObject if ($num) { while ($i < $num) { $obj = $this->db->fetch_object($resql); - $this->thirdparty_lines[$i] = $obj->rowid; $i++; diff --git a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php index 2c47edd4289..12684e5f873 100644 --- a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php +++ b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php @@ -355,7 +355,7 @@ class FormAdvTargetEmailing extends Form $sql = "SELECT c.rowid, c.name, c.fk_element"; $sql .= " FROM ".MAIN_DB_PREFIX."advtargetemailing as c"; - $sql .= " WHERE type_element='$type_element'"; + $sql .= " WHERE type_element = '".$this->db->escape($type_element)."'"; $sql .= " ORDER BY c.name"; dol_syslog(__METHOD__, LOG_DEBUG); diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index ebca0177868..8b5f757ad0e 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -302,9 +302,26 @@ if (empty($reshook)) { } } elseif ($action == 'setecheance' && $usercancreate) { $result = $object->set_echeance($user, dol_mktime(12, 0, 0, $_POST['echmonth'], $_POST['echday'], $_POST['echyear'])); - $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); - if ($result < 0) { - dol_print_error($db, $object->error); + if ($result >= 0) { + 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->model_pdf; + $ret = $object->fetch($id); // Reload to get new records + if ($ret > 0) { + $object->fetch_thirdparty(); + } + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } else { + setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setdate_livraison' && $usercancreate) { $result = $object->setDeliveryDate($user, dol_mktime(12, 0, 0, $_POST['date_livraisonmonth'], $_POST['date_livraisonday'], $_POST['date_livraisonyear'])); @@ -330,7 +347,7 @@ if (empty($reshook)) { $duration = GETPOST('duree_validite', 'int'); if (empty($datep)) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePropal")), null, 'errors'); $action = 'create'; $error++; } @@ -1248,7 +1265,7 @@ if (empty($reshook)) { if (empty($user->rights->margins->creer)) { foreach ($object->lines as &$line) { - if ($line->id == GETPOST('lineid')) { + if ($line->id == GETPOST('lineid', 'int')) { $fournprice = $line->fk_fournprice; $buyingprice = $line->pa_ht; break; @@ -1419,17 +1436,16 @@ if (empty($reshook)) { */ $form = new Form($db); -$formother = new FormOther($db); $formfile = new FormFile($db); $formpropal = new FormPropal($db); $formmargin = new FormMargin($db); -$companystatic = new Societe($db); if (!empty($conf->projet->enabled)) { $formproject = new FormProjets($db); } +$title = $langs->trans('Proposal')." - ".$langs->trans('Card'); $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos|DE:Modul_Angebote'; -llxHeader('', $langs->trans('Proposal'), $help_url); +llxHeader('', $title, $help_url); $now = dol_now(); @@ -1564,7 +1580,7 @@ if ($action == 'create') { //$warehouse_id = $soc->warehouse_id; } else { print '
    '; - print img_picto('', 'company').$form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500'); + print img_picto('', 'company').$form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx'); // reload page to retrieve customer informations if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { print ''; $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter); - $out .= ' '; + $out .= ' '; $out .= '
    '; } @@ -2494,18 +2497,18 @@ class Form } if ($finished == 0) { - $sql .= " AND p.finished = ".$finished; + $sql .= " AND p.finished = ".((int) $finished); } elseif ($finished == 1) { - $sql .= " AND p.finished = ".$finished; + $sql .= " AND p.finished = ".((int) $finished); if ($status >= 0) { - $sql .= " AND p.tosell = ".$status; + $sql .= " AND p.tosell = ".((int) $status); } } elseif ($status >= 0) { - $sql .= " AND p.tosell = ".$status; + $sql .= " AND p.tosell = ".((int) $status); } // Filter by product type if (strval($filtertype) != '') { - $sql .= " AND p.fk_product_type = ".$filtertype; + $sql .= " AND p.fk_product_type = ".((int) $filtertype); } elseif (empty($conf->product->enabled)) { // when product module is disabled, show services only $sql .= " AND p.fk_product_type = 1"; } elseif (empty($conf->service->enabled)) { // when service module is disabled, show products only @@ -3022,6 +3025,10 @@ class Form global $langs, $conf; global $price_level, $status, $finished; + if (!isset($status)) { + $status = 1; + } + $selected_input_value = ''; if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { if ($selected > 0) { @@ -3037,7 +3044,7 @@ class Form print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions); print ($hidelabel ? '' : $langs->trans("RefOrLabel").' : ').''; } else { - print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', -1, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder); + print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder); } } @@ -3051,7 +3058,7 @@ class Form * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param string $filtre Pour filtre sql * @param string $filterkey Filtre des produits - * @param int $statut -1=Return all products, 0=Products not on sell, 1=Products on sell (not used here, a filter on tobuy is already hard coded in request) + * @param int $statut -1=Return all products, 0=Products not on buy, 1=Products on buy * @param int $outputmode 0=HTML select string, 1=Array * @param int $limit Limit of line number * @param int $alsoproductwithnosupplierprice 1=Add also product without supplier prices @@ -3104,7 +3111,9 @@ class Form $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units u ON u.rowid = p.fk_unit"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; - $sql .= " AND p.tobuy = 1"; + if ($statut != -1) { + $sql .= " AND p.tobuy = ".((int) $statut); + } if (strval($filtertype) != '') { $sql .= " AND p.fk_product_type=".$this->db->escape($filtertype); } @@ -3667,13 +3676,14 @@ class Form /** * Retourne la liste des types de delais de livraison possibles * - * @param int $selected Id du type de delais pre-selectionne - * @param string $htmlname Nom de la zone select - * @param string $filtertype To add a filter + * @param int $selected Id du type de delais pre-selectionne + * @param string $htmlname Nom de la zone select + * @param string $filtertype To add a filter * @param int $addempty Add empty entry + * @param string $morecss More CSS * @return void */ - public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0) + public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '') { global $langs, $user; @@ -3681,7 +3691,7 @@ class Form dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG); - print ''; if ($addempty) { print ''; } @@ -3691,7 +3701,7 @@ class Form } else { print ''; } print ''; @@ -3818,7 +3828,6 @@ class Form $sql = "SELECT id, code, libelle as label, type, active"; $sql .= " FROM ".MAIN_DB_PREFIX."c_paiement"; $sql .= " WHERE entity IN (".getEntity('c_paiement').")"; - //if ($active >= 0) $sql.= " AND active = ".$active; $resql = $this->db->query($sql); if ($resql) { @@ -4051,7 +4060,6 @@ class Form $sql = "SELECT rowid, code, label, active"; $sql .= " FROM ".MAIN_DB_PREFIX."c_transport_mode"; $sql .= " WHERE entity IN (".getEntity('c_transport_mode').")"; - //if ($active >= 0) $sql.= " AND active = ".$active; $resql = $this->db->query($sql); if ($resql) { @@ -4151,15 +4159,16 @@ class Form /** * Return a HTML select list of shipping mode * - * @param string $selected Id shipping mode pre-selected - * @param string $htmlname Name of select zone - * @param string $filtre To filter list. This parameter must not come from input of users - * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. - * @param string $moreattrib To add more attribute on select + * @param string $selected Id shipping mode pre-selected + * @param string $htmlname Name of select zone + * @param string $filtre To filter list. This parameter must not come from input of users + * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. + * @param string $moreattrib To add more attribute on select * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info + * @param string $morecss More CSS * @return void */ - public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0) + public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '') { global $langs, $conf, $user; @@ -4180,7 +4189,7 @@ class Form $num = $this->db->num_rows($result); $i = 0; if ($num) { - print ''; if ($useempty == 1 || ($useempty == 2 && $num > 1)) { print ''; } @@ -4884,7 +4893,7 @@ class Form var more = ""; var inputvalue; if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") { - inputvalue = $("input[name=\'" + inputname + "\']").val(); + inputvalue = $("input[name=\'" + inputname + "\']:checked").val(); } else { if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; } inputvalue = $("#" + inputname + more).val(); @@ -4943,16 +4952,18 @@ class Form $formconfirm .= ''."\n"; // Line title - $formconfirm .= ''."\n"; + $formconfirm .= ''."\n"; // Line text if (is_array($formquestion) && !empty($formquestion['text'])) { - $formconfirm .= ''."\n"; + $formconfirm .= ''."\n"; } // Line form fields if ($more) { - $formconfirm .= ''."\n"; } @@ -4960,10 +4971,10 @@ class Form // Line with question $formconfirm .= ''; $formconfirm .= ''; - $formconfirm .= ''; - $formconfirm .= ''; $formconfirm .= ''."\n"; $formconfirm .= '
    '.img_picto('', 'recent').' '.$title.'
    '; + $formconfirm .= img_picto('', 'recent').' '.$title; + $formconfirm .= '
    '.$formquestion['text'].'
    '.$formquestion['text'].'
    '."\n"; + $formconfirm .= '
    '."\n"; $formconfirm .= $more; $formconfirm .= '
    '.$question.''; - $formconfirm .= $this->selectyesno("confirm", $newselectedchoice); + $formconfirm .= ''; + $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly'); + $formconfirm .= ''; $formconfirm .= '
    '."\n"; @@ -5171,7 +5182,7 @@ class Form $ret .= '
    '; $ret .= ''; $ret .= ''; - $ret .= ''; + $ret .= '
    '; $ret .= ''; @@ -5276,9 +5287,9 @@ class Form global $langs; if ($htmlname != "none") { print ''; - print ''; + print ''; print ''; - $this->selectTransportMode($selected, $htmlname, 2, $addempty, 0, 0, $active); + $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active); print ''; print ''; } else { @@ -5475,7 +5486,7 @@ class Form print ''; print ''; print ''; - print '
    '; $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form'.$htmlname, 1, 0); $ret .= '
    '; + print '
    '; print ''; // Date - print ''; @@ -435,7 +436,8 @@ function getPurchaseInvoicePieChart($socid = 0) $dolgraph->setShowLegend(2); $dolgraph->setShowPercent(1); $dolgraph->SetType(['pie']); - $dolgraph->setHeight('200'); + $dolgraph->setHeight('150'); + $dolgraph->setWidth('300'); $dolgraph->draw('idgraphpurchaseinvoices'); $result .= ''; @@ -454,6 +456,118 @@ function getPurchaseInvoicePieChart($socid = 0) return $result; } +/** + * Return an HTML table that contains a pie chart of the number of customers or supplier invoices + * + * @param string $mode Can be 'customers' or 'suppliers' + * @return string A HTML table that contains a pie chart of customers or supplier invoices + */ +function getNumberInvoicesPieChart($mode) +{ + global $conf, $db, $langs, $user; + if (!empty($conf->facture->enabled) && !empty($user->rights->facture->lire)) { + include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; + + $now = date_create(date('Y-m-d', dol_now())); + $datenowsub30 = date_create(date('Y-m-d', dol_now())); + $datenowsub15 = date_create(date('Y-m-d', dol_now())); + $datenowadd30 = date_create(date('Y-m-d', dol_now())); + $datenowadd15 = date_create(date('Y-m-d', dol_now())); + $interval30days = date_interval_create_from_date_string('30 days'); + $interval15days = date_interval_create_from_date_string('15 days'); + date_sub($datenowsub30, $interval30days); + date_sub($datenowsub15, $interval15days); + date_add($datenowadd30, $interval30days); + date_add($datenowadd15, $interval15days); + + $sql = "SELECT sum(".$db->ifsql("f.date_lim_reglement < '".date_format($datenowsub30, 'Y-m-d')."'", 1, 0).") as nblate30"; + $sql .= ", sum(".$db->ifsql("f.date_lim_reglement < '".date_format($datenowsub15, 'Y-m-d')."'", 1, 0).") as nblate15"; + $sql .= ", sum(".$db->ifsql("f.date_lim_reglement < '".date_format($now, 'Y-m-d')."'", 1, 0).") as nblatenow"; + $sql .= ", sum(".$db->ifsql("f.date_lim_reglement >= '".date_format($now, 'Y-m-d')."'", 1, 0).") as nbnotlatenow"; + $sql .= ", sum(".$db->ifsql("f.date_lim_reglement > '".date_format($datenowadd15, 'Y-m-d')."'", 1, 0).") as nbnotlate15"; + $sql .= ", sum(".$db->ifsql("f.date_lim_reglement > '".date_format($datenowadd30, 'Y-m-d')."'", 1, 0).") as nbnotlate30"; + if ($mode == 'customers') { + $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; + } elseif ($mode == 'fourn' || $mode == 'suppliers') { + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + } else { + return ''; + } + $sql .= " WHERE f.type <> 2"; + $sql .= " AND f.fk_statut = 1"; + if (isset($user->socid) && $user->socid > 0) { + $sql .= " AND f.fk_soc = ".((int) $user->socid); + } + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + $total = 0; + $dataseries = array(); + + while ($i < $num) { + $obj = $db->fetch_object($resql); + $dataseries = array(array($langs->trans('InvoiceLate30Days'),$obj->nblate30) + ,array($langs->trans('InvoiceLate15Days'),$obj->nblate15-$obj->nblate30) + ,array($langs->trans('InvoiceLateMinus15Days'),$obj->nblatenow-$obj->nblate15) + ,array($langs->trans('InvoiceNotLate'),$obj->nbnotlatenow-$obj->nbnotlate15) + ,array($langs->trans('InvoiceNotLate15Days'),$obj->nbnotlate15-$obj->nbnotlate30) + ,array($langs->trans('InvoiceNotLate30Days'),$obj->nbnotlate30)); + $i++; + } + foreach ($dataseries as $key=>$value) { + $total+=$value[1]; + } + + $colorseries = array($badgeStatus8, $badgeStatus1, $badgeStatus3, $badgeStatus4, $badgeStatus11, '-'.$badgeStatus11); + + $result = '
    '; + $result .= '
    '; print $this->selectcontacts($societe->id, $selected, $htmlname); $num = $this->num; @@ -6791,7 +6802,7 @@ class Form { throw new RestException(503, 'Error when validating parameter sqlfilters '.$objecttmp->filter); }*/ - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'Form::forgeCriteriaCallback', $objecttmp->filter).")"; } } @@ -6827,9 +6838,12 @@ class Form $obj = $this->db->fetch_object($resql); $label = ''; $tmparray = explode(',', $fieldstoshow); + $oldvalueforshowoncombobox = 0; foreach ($tmparray as $key => $val) { $val = preg_replace('/t\./', '', $val); - $label .= (($label && $obj->$val) ? ' - ' : '').$obj->$val; + $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : ''); + $label .= $obj->$val; + $oldvalueforshowoncombobox = $objecttmp->fields[$val]['showoncombobox']; } if (empty($outputmode)) { if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) { @@ -6917,7 +6931,7 @@ class Form if ($addjscombo && $jsbeautify) { // Enhance with select2 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; - $out .= ajax_combobox($htmlname); + $out .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', $show_empty < 0 ? (string) $show_empty : '-1'); } $out .= ''."\n"; + $resultyesno = ''.$label.''.dol_print_date($actioncomm->datep, 'dayhour', 'tzuserrel'); + print ''.dol_print_date($actioncomm->datep, 'dayhour', 'tzuserrel'); if ($actioncomm->datef) { $tmpa = dol_getdate($actioncomm->datep); $tmpb = dol_getdate($actioncomm->datef); diff --git a/htdocs/core/class/html.formbarcode.class.php b/htdocs/core/class/html.formbarcode.class.php index 8f3dc86c760..34bcbd86cfa 100644 --- a/htdocs/core/class/html.formbarcode.class.php +++ b/htdocs/core/class/html.formbarcode.class.php @@ -209,7 +209,7 @@ class FormBarCode $out .= ''; $out .= ''; $out .= ''; - $out .= ''; + $out .= '
    '; $out .= ''; diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 6677f7f8dce..4fa2f87f636 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -312,9 +312,9 @@ class FormCompany extends Form $out .= ''; } else { if (!$country || $country != $obj->country) { - // Affiche la rupture si on est en mode liste multipays + // Show break if we are in list with multiple countries if (!$country_codeid && $obj->country_code) { - $out .= '\n"; + $out .= '\n"; $country = $obj->country; } } @@ -1007,6 +1007,9 @@ class FormCompany extends Form { global $conf, $langs; + if (!empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && !empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) && empty($conf->fournisseur->enabled)) { + return '' ; + } $out = ''; + $out .= ''; // Show file date $date = (!empty($file['date']) ? $file['date'] : dol_filemtime($filedir."/".$file["name"])); @@ -1774,11 +1774,16 @@ class FormFile continue; // We do not show orphelins files } - print ''."\n"; + print ''."\n"; print ''; print ''; print ''; print ''; + print ''; } // TITLE if ($this->withemail) { print ''; } @@ -255,7 +259,7 @@ class FormTicket $doleditor->Create(); print ''; - if (!empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) { + if ($public && !empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print '\n"; @@ -453,6 +457,8 @@ class FormTicket } print ''; + print ''."\n"; + print "\n"; print "\n"; } @@ -563,90 +569,194 @@ class FormTicket * @param int $noadmininfo 0=Add admin info, 1=Disable admin info * @param int $maxlength Max length of label * @param string $morecss More CSS + * @param int $use_multilevel if != 0 create a multilevel select ( Do not use any of the other params) * @return void */ - public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '') + public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0) { global $langs, $user; - $ticketstat = new Ticket($this->db); + if ($use_multilevel == 0) { + $ticketstat = new Ticket($this->db); - dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG); + dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG); - $ticketstat->loadCacheCategoriesTickets(); + $ticketstat->loadCacheCategoriesTickets(); - print ''; + if ($empty) { + print ''; + } - if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) { - foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) { - // Exclude some record - if ($filtertype == 'public=1') { - if (empty($arraycategories['public'])) { + if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) { + foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) { + // Exclude some record + if ($filtertype == 'public=1') { + if (empty($arraycategories['public'])) { + continue; + } + } + + // We discard empty line if showempty is on because an empty line has already been output. + if ($empty && empty($arraycategories['code'])) { continue; } + + if ($format == 0) { + print ''; } - - // We discard empty line if showempty is on because an empty line has already been output. - if ($empty && empty($arraycategories['code'])) { - continue; - } - - if ($format == 0) { - print ''; } - } - print ''; - if ($user->admin && !$noadmininfo) { - print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); - } + print ''; + if ($user->admin && !$noadmininfo) { + print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + } - print ajax_combobox('select'.$htmlname); + print ajax_combobox('select'.$htmlname); + } else { + $groupticket=GETPOST('groupticket', 'aZ09'); + $groupticketchild=GETPOST('groupticket_child', 'aZ09'); + $arraycodenotparent[] = ""; + $stringtoprint = ''.$langs->trans("GroupOfTicket").' '; + $stringtoprint .= ''; + } + $stringtoprint .= ' '; + + $stringtoprint .= ''; + + $stringtoprint .=''; + return $stringtoprint; + } } /** @@ -989,6 +1099,8 @@ class FormTicket print ''; } + $uselocalbrowser = false; + // Intro // External users can't send message email if ($user->rights->ticket->write && !$user->socid) { @@ -999,15 +1111,15 @@ class FormTicket print ''; } // MESSAGE + $defaultmessage = ""; if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) { $defaultmessage = $arraydefaultmessage->content; @@ -1037,7 +1149,7 @@ class FormTicket //$toolbarname = 'dolibarr_details'; $toolbarname = 'dolibarr_notes'; include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_5, 70); + $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_5, 70); $doleditor->Create(); print ''; @@ -1049,7 +1161,7 @@ class FormTicket print $form->textwithpicto('', $langs->trans("TicketMessageMailSignatureHelp"), 1, 'help'); print ''; } @@ -1083,7 +1195,7 @@ class FormTicket if ($this->withfile == 2) { // Can add other files $out .= ''; $out .= ' '; - $out .= ''; + $out .= ''; } $out .= "\n"; @@ -1100,6 +1212,8 @@ class FormTicket } print "\n"; + print ''."\n"; + print "\n"; print "\n"; } diff --git a/htdocs/core/class/infobox.class.php b/htdocs/core/class/infobox.class.php index 076dace54f0..fb59e2b7c42 100644 --- a/htdocs/core/class/infobox.class.php +++ b/htdocs/core/class/infobox.class.php @@ -85,7 +85,7 @@ class InfoBox * * @param DoliDB $db Database handler * @param string $mode 'available' or 'activated' - * @param string $zone Name or area (-1 for all, 0 for Homepage, 1 for Accountancy, 2 for xxx, ...) + * @param int $zone Name or area (-1 for all, 0 for Homepage, 1 for Accountancy, 2 for xxx, ...) * @param User|null $user Object user to filter * @param array $excludelist Array of box id (box.box_id = boxes_def.rowid) to exclude * @param int $includehidden Include also hidden boxes @@ -97,7 +97,6 @@ class InfoBox $boxes = array(); - $confuserzone = 'MAIN_BOXES_'.$zone; if ($mode == 'activated') { // activated $sql = "SELECT b.rowid, b.position, b.box_order, b.fk_user,"; $sql .= " d.rowid as box_id, d.file, d.note, d.tms"; @@ -105,7 +104,7 @@ class InfoBox $sql .= " WHERE b.box_id = d.rowid"; $sql .= " AND b.entity IN (0,".$conf->entity.")"; if ($zone >= 0) { - $sql .= " AND b.position = ".$zone; + $sql .= " AND b.position = ".((int) $zone); } if (is_object($user)) { $sql .= " AND b.fk_user IN (0,".$user->id.")"; @@ -116,7 +115,7 @@ class InfoBox } else { // available $sql = "SELECT d.rowid as box_id, d.file, d.note, d.tms"; $sql .= " FROM ".MAIN_DB_PREFIX."boxes_def as d"; - $sql .= " WHERE d.entity IN (0,".$conf->entity.")"; + $sql .= " WHERE d.entity IN (0, ".$conf->entity.")"; } dol_syslog(get_class()."::listBoxes get default box list for mode=".$mode." userid=".(is_object($user) ? $user->id : '')."", LOG_DEBUG); @@ -217,7 +216,7 @@ class InfoBox * Save order of boxes for area and user * * @param DoliDB $db Database handler - * @param string $zone Name of area (0 for Homepage, ...) + * @param int $zone Name of area (0 for Homepage, ...) * @param string $boxorder List of boxes with correct order 'A:123,456,...-B:789,321...' * @param int $userid Id of user * @return int <0 if KO, 0=Nothing done, > 0 if OK @@ -254,8 +253,8 @@ class InfoBox // Delete all lines $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes"; $sql .= " WHERE entity = ".$conf->entity; - $sql .= " AND fk_user = ".$userid; - $sql .= " AND position = ".$zone; + $sql .= " AND fk_user = ".((int) $userid); + $sql .= " AND position = ".((int) $zone); dol_syslog(get_class()."::saveboxorder", LOG_DEBUG); $result = $db->query($sql); @@ -278,14 +277,13 @@ class InfoBox $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes"; $sql .= "(box_id, position, box_order, fk_user, entity)"; $sql .= " values ("; - $sql .= " ".$id.","; - $sql .= " ".$zone.","; + $sql .= " ".((int) $id).","; + $sql .= " ".((int) $zone).","; $sql .= " '".$db->escape($colonne.$ii)."',"; - $sql .= " ".$userid.","; - $sql .= " ".$conf->entity; + $sql .= " ".((int) $userid).","; + $sql .= " ".((int) $conf->entity); $sql .= ")"; - dol_syslog(get_class()."::saveboxorder", LOG_DEBUG); $result = $db->query($sql); if ($result < 0) { $error++; diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 0f97ed878cf..a578f08f3c1 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -932,7 +932,7 @@ class Ldap * Returns an array containing a details or list of LDAP record(s) * ldapsearch -LLLx -hlocalhost -Dcn=admin,dc=parinux,dc=org -w password -b "ou=adherents,ou=people,dc=parinux,dc=org" userPassword * - * @param string $search Value of fiel to search, '*' for all. Not used if $activefilter is set. + * @param string $search Value of field to search, '*' for all. Not used if $activefilter is set. * @param string $userDn DN (Ex: ou=adherents,ou=people,dc=parinux,dc=org) * @param string $useridentifier Name of key field (Ex: uid) * @param array $attributeArray Array of fields required. Note this array must also contains field $useridentifier (Ex: sn,userPassword) diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index 65fdaff9645..6f024c91b0b 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -352,10 +352,10 @@ class Menubase $sql .= " type='".$this->db->escape($this->type)."',"; $sql .= " mainmenu='".$this->db->escape($this->mainmenu)."',"; $sql .= " leftmenu='".$this->db->escape($this->leftmenu)."',"; - $sql .= " fk_menu=".$this->fk_menu.","; + $sql .= " fk_menu=".((int) $this->fk_menu).","; $sql .= " fk_mainmenu=".($this->fk_mainmenu ? "'".$this->db->escape($this->fk_mainmenu)."'" : "null").","; $sql .= " fk_leftmenu=".($this->fk_leftmenu ? "'".$this->db->escape($this->fk_leftmenu)."'" : "null").","; - $sql .= " position=".($this->position > 0 ? $this->position : 0).","; + $sql .= " position=".($this->position > 0 ? ((int) $this->position) : 0).","; $sql .= " url='".$this->db->escape($this->url)."',"; $sql .= " target='".$this->db->escape($this->target)."',"; $sql .= " titre='".$this->db->escape($this->title)."',"; diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 345ec5b38e3..6b32799bc89 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -176,7 +176,7 @@ class Notify $sqlnotifcode = ''; if ($notifcode) { if (is_numeric($notifcode)) { - $sqlnotifcode = " AND n.fk_action = ".$notifcode; // Old usage + $sqlnotifcode = " AND n.fk_action = ".((int) $notifcode); // Old usage } else { $sqlnotifcode = " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage } @@ -195,7 +195,7 @@ class Notify $sql .= $sqlnotifcode; $sql .= " AND s.entity IN (".getEntity('societe').")"; if ($socid > 0) { - $sql .= " AND s.rowid = ".$socid; + $sql .= " AND s.rowid = ".((int) $socid); } dol_syslog(__METHOD__." ".$notifcode.", ".$socid."", LOG_DEBUG); @@ -233,7 +233,7 @@ class Notify $sql .= $sqlnotifcode; $sql .= " AND c.entity IN (".getEntity('user').")"; if ($userid > 0) { - $sql .= " AND c.rowid = ".$userid; + $sql .= " AND c.rowid = ".((int) $userid); } dol_syslog(__METHOD__." ".$notifcode.", ".$socid."", LOG_DEBUG); @@ -380,11 +380,11 @@ class Notify $sql .= " AND n.fk_soc = s.rowid"; $sql .= " AND c.statut = 1"; if (is_numeric($notifcode)) { - $sql .= " AND n.fk_action = ".$notifcode; // Old usage + $sql .= " AND n.fk_action = ".((int) $notifcode); // Old usage } else { $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage } - $sql .= " AND s.rowid = ".$object->socid; + $sql .= " AND s.rowid = ".((int) $object->socid); $sql .= "\nUNION\n"; } diff --git a/htdocs/core/class/rssparser.class.php b/htdocs/core/class/rssparser.class.php index c11bdd5563d..6a8a91dbb05 100644 --- a/htdocs/core/class/rssparser.class.php +++ b/htdocs/core/class/rssparser.class.php @@ -1,19 +1,19 @@ * -* 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 . -*/ + * 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/core/class/rssparser.class.php @@ -538,22 +538,18 @@ class RssParser if ($el == 'channel') { $this->inchannel = true; - } elseif ($el == 'item' or $el == 'entry') { + } elseif ($el == 'item' || $el == 'entry') { $this->initem = true; if (isset($attrs['rdf:about'])) { $this->current_item['about'] = $attrs['rdf:about']; } - } elseif ($this->_format == 'rss' and - $this->current_namespace == '' and - $el == 'textinput') { + } elseif ($this->_format == 'rss' && $this->current_namespace == '' && $el == 'textinput') { // if we're in the default namespace of an RSS feed, // record textinput or image fields $this->intextinput = true; - } elseif ($this->_format == 'rss' and - $this->current_namespace == '' and - $el == 'image') { + } elseif ($this->_format == 'rss' && $this->current_namespace == '' && $el == 'image') { $this->inimage = true; - } elseif ($this->_format == 'atom' and in_array($el, $this->_CONTENT_CONSTRUCTS)) { + } elseif ($this->_format == 'atom' && in_array($el, $this->_CONTENT_CONSTRUCTS)) { // handle atom content constructs // avoid clashing w/ RSS mod_content if ($el == 'content') { @@ -561,7 +557,7 @@ class RssParser } $this->incontent = $el; - } elseif ($this->_format == 'atom' and $this->incontent) { + } elseif ($this->_format == 'atom' && $this->incontent) { // if inside an Atom content construct (e.g. content or summary) field treat tags as text // if tags are inlined, then flatten $attrs_str = join(' ', array_map('map_attrs', array_keys($attrs), array_values($attrs))); @@ -569,7 +565,7 @@ class RssParser $this->append_content("<$element $attrs_str>"); array_unshift($this->stack, $el); - } elseif ($this->_format == 'atom' and $el == 'link') { + } elseif ($this->_format == 'atom' && $el == 'link') { // Atom support many links per containging element. // Magpie treats link elements of type rel='alternate' // as being equivalent to RSS's simple link element. diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index 9534970a856..bdd6cc2b83a 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -319,9 +319,9 @@ class Utils } if ($dolibarr_main_db_character_set == 'utf8mb4') { // We save output into utf8mb4 charset - $param .= " --default-character-set=utf8mb4"; + $param .= " --default-character-set=utf8mb4 --no-tablespaces"; } else { - $param .= " --default-character-set=utf8"; // We always save output into utf8 charset + $param .= " --default-character-set=utf8 --no-tablespaces"; // We always save output into utf8 charset } $paramcrypted = $param; $paramclear = $param; @@ -354,7 +354,7 @@ class Utils $execmethod = 1; } - dol_syslog("Utils::dumpDatabase execmethod=".$execmethod." command:".$fullcommandcrypted, LOG_DEBUG); + dol_syslog("Utils::dumpDatabase execmethod=".$execmethod." command:".$fullcommandcrypted, LOG_INFO); // TODO Replace with executeCLI function if ($execmethod == 1) { @@ -594,7 +594,7 @@ class Utils * Execute a CLI command. * * @param string $command Command line to execute. - * @param string $outputfile Output file (used only when method is 2). For exemple $conf->admin->dir_temp.'/out.tmp'; + * @param string $outputfile A path for an output file (used only when method is 2). For example: $conf->admin->dir_temp.'/out.tmp'; * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method * @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK. */ diff --git a/htdocs/core/extrafieldsinexport.inc.php b/htdocs/core/extrafieldsinexport.inc.php index 0d29c0d1323..a868c99a66f 100644 --- a/htdocs/core/extrafieldsinexport.inc.php +++ b/htdocs/core/extrafieldsinexport.inc.php @@ -1,5 +1,9 @@ = 0) { - $sql .= " AND entity = ".$entity; + $sql .= " AND entity = ".((int) $entity); } dol_syslog("admin.lib::dolibarr_del_const", LOG_DEBUG); @@ -906,7 +906,7 @@ function listOfSessions() if (preg_match('/dol_login/i', $sessValues) && // limit to dolibarr session (preg_match('/dol_entity\|i:'.$conf->entity.';/i', $sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i', $sessValues)) && // limit to current entity - preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i', $sessValues)) { // limit to company name + preg_match('/dol_company\|s:([0-9]+):"('.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').')"/i', $sessValues)) { // limit to company name $tmp = explode('_', $file); $idsess = $tmp[1]; $regs = array(); @@ -1189,10 +1189,10 @@ function unActivateModule($value, $requiredby = 1) * @param array $tabrowid Tabrowid * @param array $tabcond Tabcond * @param array $tabhelp Tabhelp - * @param array $tabfieldcheck Tabfieldcheck + * @param array $tabcomplete Tab complete (will replace all other in future). Key is table name. * @return int 1 */ -function complete_dictionary_with_modules(&$taborder, &$tabname, &$tablib, &$tabsql, &$tabsqlsort, &$tabfield, &$tabfieldvalue, &$tabfieldinsert, &$tabrowid, &$tabcond, &$tabhelp, &$tabfieldcheck) +function complete_dictionary_with_modules(&$taborder, &$tabname, &$tablib, &$tabsql, &$tabsqlsort, &$tabfield, &$tabfieldvalue, &$tabfieldinsert, &$tabrowid, &$tabcond, &$tabhelp, &$tabcomplete) { global $db, $modules, $conf, $langs; @@ -1255,53 +1255,76 @@ function complete_dictionary_with_modules(&$taborder, &$tabname, &$tablib, &$tab if (!empty($objMod->dictionaries)) { //var_dump($objMod->dictionaries['tabname']); $nbtabname = $nbtablib = $nbtabsql = $nbtabsqlsort = $nbtabfield = $nbtabfieldvalue = $nbtabfieldinsert = $nbtabrowid = $nbtabcond = $nbtabfieldcheck = $nbtabhelp = 0; - foreach ($objMod->dictionaries['tabname'] as $val) { + $tabnamerelwithkey = array(); + foreach ($objMod->dictionaries['tabname'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $val); $nbtabname++; $taborder[] = max($taborder) + 1; $tabname[] = $val; + $tabnamerelwithkey[$key] = $val; + $tabcomplete[$tmptablename]['picto'] = $objMod->picto; } // Position - foreach ($objMod->dictionaries['tablib'] as $val) { + foreach ($objMod->dictionaries['tablib'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtablib++; $tablib[] = $val; + $tabcomplete[$tmptablename]['lib'] = $val; } - foreach ($objMod->dictionaries['tabsql'] as $val) { + foreach ($objMod->dictionaries['tabsql'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabsql++; $tabsql[] = $val; + $tabcomplete[$tmptablename]['sql'] = $val; } - foreach ($objMod->dictionaries['tabsqlsort'] as $val) { + foreach ($objMod->dictionaries['tabsqlsort'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabsqlsort++; $tabsqlsort[] = $val; + $tabcomplete[$tmptablename]['sqlsort'] = $val; } - foreach ($objMod->dictionaries['tabfield'] as $val) { + foreach ($objMod->dictionaries['tabfield'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabfield++; $tabfield[] = $val; + $tabcomplete[$tmptablename]['field'] = $val; } - foreach ($objMod->dictionaries['tabfieldvalue'] as $val) { + foreach ($objMod->dictionaries['tabfieldvalue'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabfieldvalue++; $tabfieldvalue[] = $val; + $tabcomplete[$tmptablename]['value'] = $val; } - foreach ($objMod->dictionaries['tabfieldinsert'] as $val) { + foreach ($objMod->dictionaries['tabfieldinsert'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabfieldinsert++; $tabfieldinsert[] = $val; + $tabcomplete[$tmptablename]['fieldinsert'] = $val; } - foreach ($objMod->dictionaries['tabrowid'] as $val) { + foreach ($objMod->dictionaries['tabrowid'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabrowid++; $tabrowid[] = $val; + $tabcomplete[$tmptablename]['rowid'] = $val; } - foreach ($objMod->dictionaries['tabcond'] as $val) { + foreach ($objMod->dictionaries['tabcond'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabcond++; $tabcond[] = $val; + $tabcomplete[$tmptablename]['rowid'] = $val; } if (!empty($objMod->dictionaries['tabhelp'])) { - foreach ($objMod->dictionaries['tabhelp'] as $val) { + foreach ($objMod->dictionaries['tabhelp'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabhelp++; $tabhelp[] = $val; + $tabcomplete[$tmptablename]['help'] = $val; } } if (!empty($objMod->dictionaries['tabfieldcheck'])) { - foreach ($objMod->dictionaries['tabfieldcheck'] as $val) { + foreach ($objMod->dictionaries['tabfieldcheck'] as $key => $val) { + $tmptablename = preg_replace('/'.MAIN_DB_PREFIX.'/', '', $tabnamerelwithkey[$key]); $nbtabfieldcheck++; - $tabfieldcheck[] = $val; + $tabcomplete[$tmptablename]['fieldcheck'] = $val; } } @@ -1522,9 +1545,10 @@ function form_constantes($tableau, $strictw3c = 0, $helptext = '') print ''; } + print '
    '; print '
    '; $out .= $this->selectBarcodeType($selected, $htmlname, 1); $out .= ''.dol_print_size($size, 1, 1).''.dol_print_size($size, 1, 1).'
    '; if ($found > 0 && is_object($this->cache_objects[$modulepart.'_'.$id.'_'.$ref])) { - print $this->cache_objects[$modulepart.'_'.$id.'_'.$ref]->getNomUrl(1, 'document'); + $tmpobject = $this->cache_objects[$modulepart.'_'.$id.'_'.$ref]; + //if (! in_array($tmpobject->element, array('expensereport'))) { + print $tmpobject->getNomUrl(1, 'document'); + //} else { + // print $tmpobject->getNomUrl(1); + //} } else { print $langs->trans("ObjectDeleted", ($id ? $id : $ref)); } @@ -2029,7 +2034,7 @@ class FormFile print ''.dol_print_date($link->datea, "dayhour", "tzuser").''; - print ''.img_edit().''; // id= is included into $param + print ''.img_edit().''; // id= is included into $param if ($permissiontodelete) { print '   '.img_delete().''; // id= is included into $param } else { diff --git a/htdocs/core/class/html.formintervention.class.php b/htdocs/core/class/html.formintervention.class.php index aa0259ba288..7058e80b1d7 100644 --- a/htdocs/core/class/html.formintervention.class.php +++ b/htdocs/core/class/html.formintervention.class.php @@ -77,14 +77,14 @@ class FormIntervention if ($socid == '0') { $sql .= " AND (f.fk_soc = 0 OR f.fk_soc IS NULL)"; } else { - $sql .= " AND f.fk_soc = ".$socid; + $sql .= " AND f.fk_soc = ".((int) $socid); } } dol_syslog(get_class($this)."::select_intervention", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { - $out .= ''; if ($showempty) { $out .= ''; } diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index f56b9f6070e..06b6a18b870 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -4,7 +4,7 @@ * Copyright (C) 2010-2011 Juanjo Menent * Copyright (C) 2015-2017 Marcos García * Copyright (C) 2015-2017 Nicolas ZABOURI - * Copyright (C) 2018-2019 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -584,7 +584,10 @@ class FormMail extends Form $liste['company'] = $conf->global->MAIN_INFO_SOCIETE_NOM.' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>'; // Add also email aliases if there is some - $listaliases = array('user_aliases'=>$user->email_aliases, 'global_aliases'=>$conf->global->MAIN_INFO_SOCIETE_MAIL_ALIASES); + $listaliases = array( + 'user_aliases' => (empty($user->email_aliases) ? '' : $user->email_aliases), + 'global_aliases' => getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES'), + ); // Also add robot email if (!empty($this->fromalsorobot)) { @@ -1275,10 +1278,10 @@ class FormMail extends Form $sql .= " AND entity IN (".getEntity('c_email_templates').")"; $sql .= " AND (private = 0 OR fk_user = ".$user->id.")"; // Get all public or private owned if ($active >= 0) { - $sql .= " AND active = ".$active; + $sql .= " AND active = ".((int) $active); } if ($label) { - $sql .= " AND label ='".$db->escape($label)."'"; + $sql .= " AND label = '".$db->escape($label)."'"; } if (!($id > 0) && $languagetosearch) { $sql .= " AND (lang = '".$db->escape($languagetosearch)."'".($languagetosearchmain ? " OR lang = '".$db->escape($languagetosearchmain)."'" : "")." OR lang IS NULL OR lang = '')"; @@ -1434,7 +1437,7 @@ class FormMail extends Form $sql .= " AND entity IN (".getEntity('c_email_templates').")"; $sql .= " AND (private = 0 OR fk_user = ".$user->id.")"; // See all public templates or templates I own. if ($active >= 0) { - $sql .= " AND active = ".$active; + $sql .= " AND active = ".((int) $active); } //if (is_object($outputlangs)) $sql.= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')"; // Return all languages $sql .= $this->db->order("position,lang,label", "ASC"); @@ -1594,6 +1597,9 @@ class FormMail extends Form if ($conf->adherent->enabled) { $tmparray['__SECUREKEYPAYMENT_MEMBER__'] = 'SecureKeyPAYMENTUniquePerMember'; } + if ($conf->donation->enabled) { + $tmparray['__SECUREKEYPAYMENT_DONATION__'] = 'SecureKeyPAYMENTUniquePerDonation'; + } if ($conf->facture->enabled) { $tmparray['__SECUREKEYPAYMENT_INVOICE__'] = 'SecureKeyPAYMENTUniquePerInvoice'; } @@ -1603,6 +1609,23 @@ class FormMail extends Form if ($conf->contrat->enabled) { $tmparray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'SecureKeyPAYMENTUniquePerContractLine'; } + + //Online payement link + if ($conf->adherent->enabled) { + $tmparray['__ONLINEPAYMENTLINK_MEMBER__'] = 'OnlinePaymentLinkUniquePerMember'; + } + if ($conf->donation->enabled) { + $tmparray['__ONLINEPAYMENTLINK_DONATION__'] = 'OnlinePaymentLinkUniquePerDonation'; + } + if ($conf->facture->enabled) { + $tmparray['__ONLINEPAYMENTLINK_INVOICE__'] = 'OnlinePaymentLinkUniquePerInvoice'; + } + if ($conf->commande->enabled) { + $tmparray['__ONLINEPAYMENTLINK_ORDER__'] = 'OnlinePaymentLinkUniquePerOrder'; + } + if ($conf->contrat->enabled) { + $tmparray['__ONLINEPAYMENTLINK_CONTRACTLINE__'] = 'OnlinePaymentLinkUniquePerContractLine'; + } } } else { /* No need to show into tooltip help, option is not enabled @@ -1613,6 +1636,9 @@ class FormMail extends Form $vars['__SECUREKEYPAYMENT_CONTRACTLINE__']=''; */ } + if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { + $substitutionarray['__PUBLICLINK_NEWMEMBERFORM__'] = 'BlankSubscriptionForm'; + } } foreach ($tmparray as $key => $val) { diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 18f3fd0f3ce..46858191c7b 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -56,6 +56,51 @@ class FormOther $this->db = $db; } + /** + * Return HTML code for scanner tool. + * This must be called into an existing + * + * @param string $jstoexecuteonadd Name of javascript function to call + * @return string HTML component + */ + public function getHTMLScannerForm($jstoexecuteonadd = 'barcodscannerjs') + { + global $langs; + + $out = ''; + + $out .= ''."\n"; + $out .= '
    '; + $out .= '
    Barcode scanner tool...

    '; + + $out .= ' Autodetect if we scan a product barcode or a lot/serial barcode
    '; + $out .= ' Scan a product barcode
    '; + $out .= ' Scan a product lot or serial number
    '; + + $out .= $langs->trans("QtyToAddAfterBarcodeScan").'
    '; + $out .= ''; + + /*print '
    '.$langs->trans("or").'
    '; + + print '
    '; + + print '     Qty
    '; + */ + $out .= '
    '; + $out .= '
    '; + $out .= ''; + $out .= ''; + $out .= '
    '; + + $out .= ''.$langs->trans("FeatureNotYetAvailable").''; + + // TODO Add call of javascript $jstoexecuteonadd so each scan will add qty into the inventory page + an ajax save. + + $out .= '
    '; + $out .= '
    '; + + return $out; + } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** @@ -1174,14 +1219,15 @@ class FormOther jQuery("#boxcombo").change(function() { var boxid=jQuery("#boxcombo").val(); if (boxid > 0) { + console.log("A box widget has been selected for addition, we call ajax page to add it.") var left_list = cleanSerialize(jQuery("#boxhalfleft").sortable("serialize")); var right_list = cleanSerialize(jQuery("#boxhalfright").sortable("serialize")); var boxorder = \'A:\' + left_list + \'-B:\' + right_list; jQuery.ajax({ - url: \''.DOL_URL_ROOT.'/core/ajax/box.php?boxorder=\'+boxorder+\'&boxid=\'+boxid+\'&zone='.$areacode.'&userid='.$user->id.'\', - async: false - }); - window.location.search=\'mainmenu='.GETPOST("mainmenu", "aZ09").'&leftmenu='.GETPOST('leftmenu', "aZ09").'&action=addbox&boxid=\'+boxid; + url: \''.DOL_URL_ROOT.'/core/ajax/box.php?boxorder=\'+boxorder+\'&boxid=\'+boxid+\'&zone='.$areacode.'&userid='.$user->id.'\' + }).done(function() { + window.location.search=\'mainmenu='.GETPOST("mainmenu", "aZ09").'&leftmenu='.GETPOST('leftmenu', "aZ09").'\'; + }); } });'; if (!count($arrayboxtoactivatelabel)) { diff --git a/htdocs/core/class/html.formsocialcontrib.class.php b/htdocs/core/class/html.formsocialcontrib.class.php index 8a40eed9da8..3455b572888 100644 --- a/htdocs/core/class/html.formsocialcontrib.class.php +++ b/htdocs/core/class/html.formsocialcontrib.class.php @@ -76,7 +76,7 @@ class FormSocialContrib $sql = "SELECT c.id, c.libelle as type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_chargesociales as c"; $sql .= " WHERE c.active = 1"; - $sql .= " AND c.fk_pays = ".$mysoc->country_id; + $sql .= " AND c.fk_pays = ".((int) $mysoc->country_id); $sql .= " ORDER BY c.libelle ASC"; } else { $sql = "SELECT c.id, c.libelle as type"; diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index c5c3b38b29b..f4e076640c4 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -103,11 +103,13 @@ class FormTicket */ public function __construct($db) { + global $conf; + $this->db = $db; $this->action = 'add'; - $this->withcompany = 1; + $this->withcompany = $conf->societe->enabled ? 1 : 0; $this->withfromsocid = 0; $this->withfromcontactid = 0; //$this->withthreadid=0; @@ -169,13 +171,15 @@ class FormTicket if ($this->withref) { // Ref $defaultref = $ticketstat->getDefaultRef(); - print '
    '.$langs->trans("Ref").'
    '.$langs->trans("Ref").''; + print ''; + print '
    '; - print ''; + print ''; print '
    '; print ''; @@ -313,7 +317,7 @@ class FormTicket if ($this->withfile == 2) { // Can add other files $out .= ''; $out .= ' '; - $out .= ''; + $out .= ''; } $out .= "
    '; include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $uselocalbrowser = true; - $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70); + $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70); $doleditor->Create(); print '
    '; include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 150, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70); + $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 150, 'dolibarr_details', '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70); $doleditor->Create(); print '
    '; print ''; - print ''; + print ''; print ''; } + // Submit if (empty($strictw3c)) { print '"; } + print "\n"; if (empty($strictw3c)) { @@ -1688,6 +1716,7 @@ function form_constantes($tableau, $strictw3c = 0, $helptext = '') } } print '
    '.$langs->trans("Description").''.$langs->trans("Description").''; $text = $langs->trans("Value"); print $form->textwithpicto($text, $helptext, 1, 'help', '', 0, 2, 'idhelptext'); @@ -1669,17 +1693,21 @@ function form_constantes($tableau, $strictw3c = 0, $helptext = '') //var_dump($arraydefaultmessage); //var_dump($arrayofmessagename); print $form->selectarray('constvalue'.(empty($strictw3c) ? '' : ($strictw3c == 3 ? '_'.$const : '[]')), $arrayofmessagename, $obj->value.':'.$tmp[1], 'None', 0, 0, '', 0, 0, 0, '', '', 1); + } elseif (preg_match('/MAIL_FROM$/i', $const)) { + print img_picto('', 'email', 'class="pictofixedwidth"').''; } else { // type = 'string' ou 'chaine' print ''; } print ''; print ''; print "
    '; + print ''; if (!empty($strictw3c) && $strictw3c == 1) { print '
    '; diff --git a/htdocs/core/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index 939e6514c13..ef635b259ff 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -168,7 +168,7 @@ function show_array_actions_to_do($max = 5) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if ($socid) { - $sql .= " AND s.rowid = ".$socid; + $sql .= " AND s.rowid = ".((int) $socid); } $sql .= " ORDER BY a.datep DESC, a.id DESC"; $sql .= $db->plimit($max, 0); @@ -284,7 +284,7 @@ function show_array_last_actions_done($max = 5) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if ($socid) { - $sql .= " AND s.rowid = ".$socid; + $sql .= " AND s.rowid = ".((int) $socid); } $sql .= " ORDER BY a.datep2 DESC"; $sql .= $db->plimit($max, 0); diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 4108724236d..99cf4e4f8d1 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -411,10 +411,11 @@ function ajax_dialog($title, $message, $w = 350, $h = 150) * @param int $minLengthToAutocomplete Minimum length of input string to start autocomplete * @param int $forcefocus Force focus on field * @param string $widthTypeOfAutocomplete 'resolve' or 'off' + * @param string $idforemptyvalue '-1' * @return string Return html string to convert a select field into a combo, or '' if feature has been disabled for some reason. * @see selectArrayAjax() of html.form.class */ -function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete = 'resolve') +function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete = 'resolve', $idforemptyvalue = '-1') { global $conf; @@ -454,13 +455,15 @@ function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = templateResult: function (data, container) { /* Format visible output into combo list */ /* Code to add class of origin OPTION propagated to the new select2
  • tag */ if (data.element) { $(container).addClass($(data.element).attr("class")); } - //console.log(data.html); - if (data.id == -1) return \' \'; + //console.log($(data.element).attr("data-html")); + if (data.id == '.((int) $idforemptyvalue).' && $(data.element).attr("data-html") == undefined) { + return \' \'; + } if ($(data.element).attr("data-html") != undefined) return htmlEntityDecodeJs($(data.element).attr("data-html")); // If property html set, we decode html entities and use this return data.text; }, templateSelection: function (selection) { /* Format visible output of selected value */ - if (selection.id == -1) return \'\'+selection.text+\'\'; + if (selection.id == '.((int) $idforemptyvalue).') return \'\'+selection.text+\'\'; return selection.text; }, escapeMarkup: function(markup) { diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index fb97d2e5361..5abc6bfc2ac 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -227,7 +227,7 @@ function societe_prepare_head(Societe $object) if (empty($conf->stripe->enabled)) { $sql .= " AND n.stripe_card_ref IS NULL"; } else { - $sql .= " AND (n.stripe_card_ref IS NULL OR (n.stripe_card_ref IS NOT NULL AND n.status = ".$servicestatus."))"; + $sql .= " AND (n.stripe_card_ref IS NULL OR (n.stripe_card_ref IS NOT NULL AND n.status = ".((int) $servicestatus)."))"; } $resql = $db->query($sql); @@ -504,11 +504,11 @@ function getCountry($searchkey, $withcode = '', $dbtouse = 0, $outputlangs = '', $sql = "SELECT rowid, code, label FROM ".MAIN_DB_PREFIX."c_country"; if (is_numeric($searchkey)) { - $sql .= " WHERE rowid=".$searchkey; + $sql .= " WHERE rowid = ".((int) $searchkey); } elseif (!empty($searchkey)) { - $sql .= " WHERE code='".$db->escape($searchkey)."'"; + $sql .= " WHERE code = '".$db->escape($searchkey)."'"; } else { - $sql .= " WHERE label='".$db->escape($searchlabel)."'"; + $sql .= " WHERE label = '".$db->escape($searchlabel)."'"; } $resql = $dbtouse->query($sql); @@ -571,7 +571,7 @@ function getState($id, $withcode = '', $dbtouse = 0, $withregion = 0, $outputlan $sql = "SELECT d.rowid as id, d.code_departement as code, d.nom as name, d.active, c.label as country, c.code as country_code, r.code_region as region_code, r.nom as region_name FROM"; $sql .= " ".MAIN_DB_PREFIX."c_departements as d, ".MAIN_DB_PREFIX."c_regions as r,".MAIN_DB_PREFIX."c_country as c"; - $sql .= " WHERE d.fk_region=r.code_region and r.fk_pays=c.rowid and d.rowid=".$id; + $sql .= " WHERE d.fk_region=r.code_region and r.fk_pays=c.rowid and d.rowid=".((int) $id); $sql .= " AND d.active = 1 AND r.active = 1 AND c.active = 1"; $sql .= " ORDER BY c.code, d.code_departement"; @@ -754,7 +754,7 @@ function isInEEC($object) return false; } - $country_code_in_EEC = getCountriesInEEC(); + $country_code_in_EEC = getCountriesInEEC(); // This make a database call but there is a cache done into $conf->cache['country_code_in_EEC'] //print "dd".$object->country_code; return in_array($object->country_code, $country_code_in_EEC); @@ -939,11 +939,11 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') 't.email', ); //Social media - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - $searchAddressPhoneDBFields['t.'.$key] = "t.socialnetworks->'$.".$key."'"; - } - } + // foreach ($socialnetworks as $key => $value) { + // if ($value['active']) { + // $searchAddressPhoneDBFields['t.'.$key] = "t.socialnetworks->'$.".$key."'"; + // } + // } if (!$sortorder) { $sortorder = "ASC"; @@ -963,9 +963,9 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') $contactstatic->fields = array( 'name' =>array('type'=>'varchar(128)', 'label'=>'Name', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1), - 'poste' =>array('type'=>'varchar(128)', 'label'=>'PostOrFunction', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>20), - 'address' =>array('type'=>'varchar(128)', 'label'=>'Address', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>30), - 'role' =>array('type'=>'checkbox', 'label'=>'Role', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>40), + 'poste' =>array('type'=>'varchar(128)', 'label'=>'PostOrFunction', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>2, 'index'=>1, 'position'=>20), + 'address' =>array('type'=>'varchar(128)', 'label'=>'Address', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>3, 'index'=>1, 'position'=>30), + 'role' =>array('type'=>'checkbox', 'label'=>'Role', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>4, 'index'=>1, 'position'=>40), 'statut' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'default'=>0, 'index'=>1, 'position'=>50, 'arrayofkeyval'=>array(0=>$contactstatic->LibStatut(0, 1), 1=>$contactstatic->LibStatut(1, 1))), ); @@ -1448,7 +1448,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin if (is_object($objcon) && $objcon->id > 0) { $force_filter_contact = true; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as r ON a.id = r.fk_actioncomm"; - $sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".$objcon->id; + $sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".((int) $objcon->id); } if (is_object($filterobj) && in_array(get_class($filterobj), array('Societe', 'Client', 'Fournisseur'))) { @@ -1457,7 +1457,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin $sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_resources as er"; $sql .= " ON er.resource_type = 'dolresource'"; $sql .= " AND er.element_id = a.id"; - $sql .= " AND er.resource_id = ".$filterobj->id; + $sql .= " AND er.resource_id = ".((int) $filterobj->id); } elseif (is_object($filterobj) && get_class($filterobj) == 'Project') { /* Nothing */ } elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { @@ -1940,7 +1940,7 @@ function show_subsidiaries($conf, $langs, $db, $object) $sql = "SELECT s.rowid, s.client, s.fournisseur, s.nom as name, s.name_alias, s.email, s.address, s.zip, s.town, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur, s.canvas"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; - $sql .= " WHERE s.parent = ".$object->id; + $sql .= " WHERE s.parent = ".((int) $object->id); $sql .= " AND s.entity IN (".getEntity('societe').")"; $sql .= " ORDER BY s.nom"; diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index a615c04ca8e..0dde3a93159 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -547,12 +547,12 @@ function dol_get_last_day($year, $month = 12, $gm = false) * * @param int $date Date GMT * @param mixed $gm False or 0 or 'tzserver' = Return date to compare with server TZ, - * True or 1 or 'gmt' to compare with GMT date. + * 'gmt' to compare with GMT date. * @return int Date for last hour of a given date */ function dol_get_last_hour($date, $gm = 'tzserver') { - $tmparray = dol_getdate($date); + $tmparray = dol_getdate($date, false, ($gm == 'gmt' ? 'gmt' : '')); return dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year'], $gm); } @@ -561,12 +561,12 @@ function dol_get_last_hour($date, $gm = 'tzserver') * * @param int $date Date GMT * @param mixed $gm False or 0 or 'tzserver' = Return date to compare with server TZ, - * True or 1 or 'gmt' to compare with GMT date. + * 'gmt' to compare with GMT date. * @return int Date for last hour of a given date */ function dol_get_first_hour($date, $gm = 'tzserver') { - $tmparray = dol_getdate($date); + $tmparray = dol_getdate($date, false, ($gm == 'gmt' ? 'gmt' : '')); return dol_mktime(0, 0, 0, $tmparray['mon'], $tmparray['mday'], $tmparray['year'], $gm); } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 755cd8674df..7e34eec5ecd 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -62,8 +62,10 @@ function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excl global $db, $hookmanager; global $object; - dol_syslog("files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter)); - //print 'xxx'."files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter); + if ($recursive <= 1) { // Avoid too verbose log + dol_syslog("files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter)); + //print 'xxx'."files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter); + } $loaddate = ($mode == 1 || $mode == 2) ?true:false; $loadsize = ($mode == 1 || $mode == 3) ?true:false; @@ -133,7 +135,7 @@ function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excl if ($qualified) { $isdir = is_dir(dol_osencode($path."/".$file)); // Check whether this is a file or directory and whether we're interested in that type - if ($isdir && (($types == "directories") || ($types == "all") || $recursive)) { + if ($isdir && (($types == "directories") || ($types == "all") || $recursive > 0)) { // Add entry into file_list array if (($types == "directories") || ($types == "all")) { if ($loaddate || $sortcriteria == 'date') { @@ -165,10 +167,10 @@ function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excl } // if we're in a directory and we want recursive behavior, call this function again - if ($recursive) { + if ($recursive > 0) { if (empty($donotfollowsymlinks) || !is_link($path."/".$file)) { //var_dump('eee '. $path."/".$file. ' '.is_dir($path."/".$file).' '.is_link($path."/".$file)); - $file_list = array_merge($file_list, dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook, ($relativename != '' ? $relativename.'/' : '').$file, $donotfollowsymlinks)); + $file_list = array_merge($file_list, dol_dir_list($path."/".$file, $types, $recursive + 1, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook, ($relativename != '' ? $relativename.'/' : '').$file, $donotfollowsymlinks)); } } } elseif (!$isdir && (($types == "files") || ($types == "all"))) { @@ -2230,7 +2232,8 @@ function dol_most_recent_file($dir, $regexfilter = '', $excludefilter = array('( } /** - * Security check when accessing to a document (used by document.php, viewimage.php and webservices) + * Security check when accessing to a document (used by document.php, viewimage.php and webservices to get documents). + * TODO Replace code that set $accesallowed by a call to restrictedArea() * * @param string $modulepart Module of document ('module', 'module_user_temp', 'module_user' or 'module_temp') * @param string $original_file Relative path with filename, relative to modulepart. @@ -2444,6 +2447,16 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, // Wrapping for events if ($fuser->rights->agenda->myactions->{$read}) { $accessallowed = 1; + // If we known $id of project, call checkUserAccessToObject to check permission on the given agenda event on properties and assigned users + if ($refname && !preg_match('/^specimen/i', $original_file)) { + include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $tmpobject = new ActionComm($db); + $tmpobject->fetch((int) $refname); + $accessallowed = checkUserAccessToObject($user, array('agenda'), $tmpobject->id, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id', ''); + if ($user->socid && $tmpobject->socid) { + $accessallowed = checkUserAccessToObject($user, array('societe'), $tmpobject->socid); + } + } } $original_file = $conf->agenda->dir_output.'/'.$original_file; } elseif ($modulepart == 'category' && !empty($conf->categorie->multidir_output[$entity])) { @@ -2610,12 +2623,26 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, // Wrapping pour les projets if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; + // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project + if ($refname && !preg_match('/^specimen/i', $original_file)) { + include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + $tmpproject = new Project($db); + $tmpproject->fetch('', $refname); + $accessallowed = checkUserAccessToObject($user, array('projet'), $tmpproject->id, 'projet&project', '', '', 'rowid', ''); + } } $original_file = $conf->projet->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")"; } elseif ($modulepart == 'project_task' && !empty($conf->projet->dir_output)) { if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; + // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project + if ($refname && !preg_match('/^specimen/i', $original_file)) { + include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $tmptask = new Task($db); + $tmptask->fetch('', $refname); + $accessallowed = checkUserAccessToObject($user, array('projet_task'), $tmptask->id, 'projet&project', '', '', 'rowid', ''); + } } $original_file = $conf->projet->dir_output.'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")"; diff --git a/htdocs/core/lib/fourn.lib.php b/htdocs/core/lib/fourn.lib.php index 68910357269..efc9f60147c 100644 --- a/htdocs/core/lib/fourn.lib.php +++ b/htdocs/core/lib/fourn.lib.php @@ -59,7 +59,7 @@ function facturefourn_prepare_head($object) $nbStandingOrders = 0; $sql = "SELECT COUNT(pfd.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; - $sql .= " WHERE pfd.fk_facture_fourn = ".$object->id; + $sql .= " WHERE pfd.fk_facture_fourn = ".((int) $object->id); $sql .= " AND pfd.ext_payment_id IS NULL"; $resql = $db->query($sql); if ($resql) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ce3b89d7805..6856cbab458 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -294,7 +294,7 @@ function dol_shutdown() } /** - * Return true if we are in a context of submitting the parameter $paramname + * Return true if we are in a context of submitting the parameter $paramname from a POST of a form. * * @param string $paramname Name or parameter to test * @return boolean True if we have just submit a POST or GET request with the parameter provided (even if param is empty) @@ -634,17 +634,17 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null $out = checkVal($out, $check, $filter, $options); } - // Sanitizing for special parameters. There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. + // Sanitizing for special parameters. + // Note: There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. if ($paramname == 'backtopage' || $paramname == 'backtolist' || $paramname == 'backtourl') { - $out = str_replace('\\', '/', $out); - $out = str_replace(array(':', ';', '@'), '', $out); - + $out = str_replace('\\', '/', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. + $out = str_replace(array(':', ';', '@'), '', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. do { $oldstringtoclean = $out; $out = str_ireplace(array('javascript', 'vbscript', '&colon', '&#'), '', $out); } while ($oldstringtoclean != $out); - $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); + $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); // We remove schema*// to remove external URL } // Code for search criteria persistence. @@ -684,13 +684,13 @@ function GETPOSTINT($paramname, $method = 0, $filter = null, $options = null, $n } /** - * Return a value after checking on a rule. + * Return a value after checking on a rule. A sanitization may also have been done. * - * @param string $out Value to get/check - * @param string $check Type of check + * @param string $out Value to check/clear. + * @param string $check Type of check/sanitizing * @param int $filter Filter to apply when $check is set to 'custom'. (See http://php.net/manual/en/filter.filters.php for détails) * @param mixed $options Options to pass to filter_var when $check is set to 'custom' - * @return string|array Value found (string or array), or '' if check fails + * @return string|array Value sanitized (string or array). It may be '' if format check fails. */ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = null) { @@ -777,6 +777,11 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = case 'restricthtml': // Recommended for most html textarea do { $oldstringtoclean = $out; + + // We replace chars encoded with numeric HTML entities with real char (to avoid to have numeric entities used for obfuscation of injections) + $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+);/i', 'realCharForNumericEntities', $out); + $out = preg_replace('/&#x?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'. + $out = dol_string_onlythesehtmltags($out, 0, 1, 1); // We should also exclude non expected attributes @@ -797,7 +802,6 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = } - if (!function_exists('dol_getprefix')) { /** * Return a prefix to use for this Dolibarr instance, for session/cookie names or email id. @@ -1386,7 +1390,9 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = return; } - $message = preg_replace('/password=\'[^\']*\'/', 'password=\'hidden\'', $message); // protection to avoid to have value of password in log + if (empty($conf->global->MAIN_SHOW_PASSWORD_INTO_LOG)) { + $message = preg_replace('/password=\'[^\']*\'/', 'password=\'hidden\'', $message); // protection to avoid to have value of password in log + } // If adding log inside HTML page is required if ((!empty($_REQUEST['logtohtml']) && !empty($conf->global->MAIN_ENABLE_LOG_TO_HTML)) @@ -1656,7 +1662,7 @@ function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab $tabsname = str_replace("@", "", $picto); } $out .= '
    '; - $out .= ''.$langs->trans("More").'... ('.$nbintab.')'; // Do not use "reposition" class in the "More". + $out .= ''.$langs->trans("More").'... ('.$nbintab.')'; // Do not use "reposition" class in the "More". $out .= '
    '; $out .= $outmore; $out .= '
    '; @@ -1917,7 +1923,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi } if ($showbarcode) { - $morehtmlleft .= '
    '.$form->showbarcode($object).'
    '; + $morehtmlleft .= '
    '.$form->showbarcode($object, 100, 'photoref').'
    '; } if ($object->element == 'societe') { @@ -2197,8 +2203,8 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = if ($tzoutput == 'tzserver') { $to_gmt = false; $offsettzstring = @date_default_timezone_get(); // Example 'Europe/Berlin' or 'Indian/Reunion' - $offsettz = 0; - $offsetdst = 0; + $offsettz = 0; // Timezone offset with server timezone, so 0 + $offsetdst = 0; // Dst offset with server timezone, so 0 } elseif ($tzoutput == 'tzuser' || $tzoutput == 'tzuserrel') { $to_gmt = true; $offsettzstring = (empty($_SESSION['dol_tz_string']) ? 'UTC' : $_SESSION['dol_tz_string']); // Example 'Europe/Berlin' or 'Indian/Reunion' @@ -2290,7 +2296,7 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = dol_print_error("Functions.lib::dol_print_date function called with a bad value from page ".$_SERVER["PHP_SELF"]); return ''; } elseif (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+) ?([0-9]+)?:?([0-9]+)?:?([0-9]+)?/i', $time, $reg)) { // Still available to solve problems in extrafields of type date - // This part of code should not be used. + // This part of code should not be used anymore. dol_syslog("Functions.lib::dol_print_date function called with a bad value from page ".$_SERVER["PHP_SELF"], LOG_WARNING); //if (function_exists('debug_print_backtrace')) debug_print_backtrace(); // Date has format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' @@ -2308,7 +2314,7 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = if ($time < 100000000000) { // Protection against bad date values $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. - $ret = adodb_strftime($format, $timetouse, $to_gmt); + $ret = adodb_strftime($format, $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server } else { $ret = 'Bad value '.$time.' for date'; } @@ -2318,7 +2324,7 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. // Here ret is string in PHP setup language (strftime was used). Now we convert to $outputlangs. - $month = adodb_strftime('%m', $timetouse); + $month = adodb_strftime('%m', $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server $month = sprintf("%02d", $month); // $month may be return with format '06' on some installation and '6' on other, so we force it to '06'. if ($encodetooutput) { $monthtext = $outputlangs->transnoentities('Month'.$month); @@ -2334,9 +2340,10 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = //return $ret; } if (preg_match('/__a__/i', $format)) { + //print "time=$time offsettz=$offsettz offsetdst=$offsetdst offsettzstring=$offsettzstring"; $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. - $w = adodb_strftime('%w', $timetouse); // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. + $w = adodb_strftime('%w', $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server $dayweek = $outputlangs->transnoentitiesnoconv('Day'.$w); $ret = str_replace('__A__', $dayweek, $ret); $ret = str_replace('__a__', dol_substr($dayweek, 0, 3), $ret); @@ -2353,7 +2360,7 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = * * @param int $timestamp Timestamp * @param boolean $fast Fast mode. deprecated. - * @param string $forcetimezone '' to use the PHP server timezone. Or use a form like 'Europe/Paris' or '+0200' to force timezone. + * @param string $forcetimezone '' to use the PHP server timezone. Or use a form like 'gmt', 'Europe/Paris' or '+0200' to force timezone. * @return array Array of informations * 'seconds' => $secs, * 'minutes' => $min, @@ -2368,42 +2375,23 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = */ function dol_getdate($timestamp, $fast = false, $forcetimezone = '') { - global $conf; - - if (empty($conf->global->MAIN_USE_OLD_FUNCTIONS_FOR_GETDATE)) { - //$datetimeobj = new DateTime('@'.$timestamp); - $datetimeobj = new DateTime(); - $datetimeobj->setTimestamp($timestamp); // Use local PHP server timezone - if ($forcetimezone) { - $datetimeobj->setTimezone(new DateTimeZone($forcetimezone)); // (add timezone relative to the date entered) - } - $arrayinfo = array( - 'year'=>((int) date_format($datetimeobj, 'Y')), - 'mon'=>((int) date_format($datetimeobj, 'm')), - 'mday'=>((int) date_format($datetimeobj, 'd')), - 'wday'=>((int) date_format($datetimeobj, 'w')), - 'yday'=>((int) date_format($datetimeobj, 'z')), - 'hours'=>((int) date_format($datetimeobj, 'H')), - 'minutes'=>((int) date_format($datetimeobj, 'i')), - 'seconds'=>((int) date_format($datetimeobj, 's')), - '0'=>$timestamp - ); - } else { - // PHP getdate is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows - $usealternatemethod = false; - if ($timestamp <= 0) { - $usealternatemethod = true; // <= 1970 - } - if ($timestamp >= 2145913200) { - $usealternatemethod = true; // >= 2038 - } - - if ($usealternatemethod) { - $arrayinfo = adodb_getdate($timestamp, $fast); - } else { - $arrayinfo = getdate($timestamp); - } + //$datetimeobj = new DateTime('@'.$timestamp); + $datetimeobj = new DateTime(); + $datetimeobj->setTimestamp($timestamp); // Use local PHP server timezone + if ($forcetimezone) { + $datetimeobj->setTimezone(new DateTimeZone($forcetimezone == 'gmt' ? 'UTC' : $forcetimezone)); // (add timezone relative to the date entered) } + $arrayinfo = array( + 'year'=>((int) date_format($datetimeobj, 'Y')), + 'mon'=>((int) date_format($datetimeobj, 'm')), + 'mday'=>((int) date_format($datetimeobj, 'd')), + 'wday'=>((int) date_format($datetimeobj, 'w')), + 'yday'=>((int) date_format($datetimeobj, 'z')), + 'hours'=>((int) date_format($datetimeobj, 'H')), + 'minutes'=>((int) date_format($datetimeobj, 'i')), + 'seconds'=>((int) date_format($datetimeobj, 's')), + '0'=>$timestamp + ); return $arrayinfo; } @@ -3505,48 +3493,38 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } } else { $pictowithouttext = preg_replace('/(\.png|\.gif|\.svg)$/', '', $picto); + $pictowithouttext = str_replace('object_', '', $pictowithouttext); if (empty($srconly) && in_array($pictowithouttext, array( '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected', 'accountancy', 'account', 'accountline', 'action', 'add', 'address', 'angle-double-down', 'angle-double-up', 'asset', - 'bank_account', 'barcode', 'bank', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'building', - 'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'cron', 'cubes', - 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'edit', 'ellipsis-h', 'email', 'eraser', 'establishment', 'external-link-alt', 'external-link-square-alt', + 'bank_account', 'barcode', 'bank', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'bug', 'building', + 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', + 'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'conversation', 'cron', 'cubes', + 'multicurrency', + 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'dynamicprice', + 'edit', 'ellipsis-h', 'email', 'eraser', 'establishment', 'expensereport', 'external-link-alt', 'external-link-square-alt', 'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'autofill', 'folder', 'folder-open', 'folder-plus', - 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', + 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', 'help', 'holiday', - 'images', 'info', 'intervention', 'inventory', 'intracommreport', - 'label', 'language', 'link', 'list', 'listlight', 'loan', 'lot', 'long-arrow-alt-right', + 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'knowledgemanagement', + 'label', 'language', 'link', 'list', 'list-alt', 'listlight', 'loan', 'lot', 'long-arrow-alt-right', 'margin', 'map-marker-alt', 'member', 'meeting', 'money-bill-alt', 'movement', 'mrp', 'note', 'next', - 'object_accounting', 'object_account', 'object_accountline', 'object_action', 'object_asset', 'object_bank_account', 'object_barcode', 'object_bill', 'object_billr', 'object_billa', 'object_billd', 'object_bom', - 'object_category', 'object_conferenceorbooth', 'object_conversation', 'object_bookmark', 'object_bug', 'object_building', 'object_clock', 'object_collab', 'object_dolly', 'object_dollyrevert', - 'object_folder', 'object_folder-open','object_generic', - 'object_list-alt', 'object_calendar', 'object_calendarweek', 'object_calendarmonth', 'object_calendarday', 'object_calendarperuser', - 'object_cash-register', 'object_company', 'object_contact', 'object_contract', 'object_cron', 'object_donation', 'object_dynamicprice', 'object_establishment', - 'object_globe', 'object_holiday', 'object_hrm', 'object_invoice', 'object_intervention', 'object_inventory', 'object_intracommreport', 'object_label', - 'object_margin', 'object_members', 'object_money-bill-alt', 'object_multicurrency', 'object_order', 'object_payment', - 'object_lot', 'object_mrp', 'object_other', - 'object_payment', 'object_pdf', 'object_product', 'object_propal', - 'object_paragraph', 'object_poll', 'object_printer', 'object_project', 'object_projectpub', 'object_propal', 'object_resource', 'object_rss', 'object_projecttask', - 'object_reception', 'object_recruitmentjobposition', 'object_recruitmentcandidature', - 'object_salary', 'object_shipment', 'object_share-alt', 'object_supplier_invoice', 'object_supplier_invoicea', 'object_supplier_invoiced', 'object_supplier_order', 'object_supplier_proposal', 'object_service', 'object_stock', - 'object_technic', 'object_ticket', 'object_trip', 'object_user', 'object_group', 'object_member', - 'object_phoning', 'object_phoning_mobile', 'object_phoning_fax', 'object_email', 'object_website', 'object_movement', 'object_workstation', 'off', 'on', 'order', - 'paiment', 'play', 'pdf', 'phone', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'stock', 'resize', 'service', 'stats', 'trip', - 'setup', 'share-alt', 'sign-out', 'split', 'stripe', 'stripe-s', 'switch_off', 'switch_on', 'tools', 'unlink', 'uparrow', 'user', 'vcard', 'wrench', + 'paiment', 'paragraph', 'play', 'pdf', 'phone', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'stock', 'resize', 'service', 'stats', 'trip', + 'security', 'setup', 'share-alt', 'sign-out', 'split', 'stripe', 'stripe-s', 'switch_off', 'switch_on', 'tools', 'unlink', 'uparrow', 'user', 'vcard', 'wrench', 'github', 'jabber', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp', 'chevron-left', 'chevron-right', 'chevron-down', 'chevron-top', 'commercial', 'companies', 'generic', 'home', 'hrm', 'members', 'products', 'invoicing', - 'payment', 'pencil-ruler', 'preview', 'project', 'projectpub', 'projecttask', 'refresh', 'salary', 'shipment', 'supplier_invoice', 'technic', 'ticket', + 'partnership', 'payment', 'pencil-ruler', 'preview', 'project', 'projectpub', 'projecttask', 'question', 'refresh', 'salary', 'shipment', + 'supplier_invoice', 'supplier_invoicea', 'supplier_invoicer', 'supplier_invoiced', + 'technic', 'ticket', 'error', 'warning', - 'recruitmentcandidature', 'recruitmentjobposition', 'resource', - 'shapes', 'supplier_proposal', 'supplier_order', 'supplier_invoice', + 'recent', 'reception', 'recruitmentcandidature', 'recruitmentjobposition', 'resource', + 'shapes', 'supplier', 'supplier_proposal', 'supplier_order', 'supplier_invoice', 'timespent', 'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda', - 'user-cog', 'website', 'workstation', + 'uncheck', 'user-cog', 'website', 'workstation', 'conferenceorbooth', 'eventorganization' ))) { - $pictowithouttext = str_replace('object_', '', $pictowithouttext); - $fakey = $pictowithouttext; $facolor = ''; $fasize = ''; @@ -3560,35 +3538,39 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $arrayconvpictotofa = array( 'account'=>'university', 'accountline'=>'receipt', 'accountancy'=>'search-dollar', 'action'=>'calendar-alt', 'add'=>'plus-circle', 'address'=> 'address-book', 'asset'=>'money-check-alt', 'autofill'=>'fill', - 'bank_account'=>'university', 'bill'=>'file-invoice-dollar', 'billa'=>'file-excel', 'billr'=>'file-invoice-dollar', 'supplier_invoicea'=>'file-excel', 'billd'=>'file-medical', 'supplier_invoiced'=>'file-medical', + 'bank_account'=>'university', + 'bill'=>'file-invoice-dollar', 'billa'=>'file-excel', 'billr'=>'file-invoice-dollar', 'billd'=>'file-medical', + 'supplier_invoice'=>'file-invoice-dollar', 'supplier_invoicea'=>'file-excel', 'supplier_invoicer'=>'file-invoice-dollar', 'supplier_invoiced'=>'file-medical', 'bom'=>'shapes', 'chart'=>'chart-line', 'company'=>'building', 'contact'=>'address-book', 'contract'=>'suitcase', 'collab'=>'people-arrows', 'conversation'=>'comments', 'country'=>'globe-americas', 'cron'=>'business-time', 'donation'=>'file-alt', 'dynamicprice'=>'hand-holding-usd', 'setup'=>'cog', 'companies'=>'building', 'products'=>'cube', 'commercial'=>'suitcase', 'invoicing'=>'coins', 'accounting'=>'search-dollar', 'category'=>'tag', 'dollyrevert'=>'dolly', - 'hrm'=>'user-tie', 'margin'=>'calculator', 'members'=>'user-friends', 'ticket'=>'ticket-alt', 'globe'=>'external-link-alt', 'lot'=>'barcode', + 'generate'=>'plus-square', 'hrm'=>'user-tie', 'incoterm'=>'truck-loading', + 'margin'=>'calculator', 'members'=>'user-friends', 'ticket'=>'ticket-alt', 'globe'=>'external-link-alt', 'lot'=>'barcode', 'email'=>'at', 'establishment'=>'building', 'edit'=>'pencil-alt', 'graph'=>'chart-line', 'grip_title'=>'arrows-alt', 'grip'=>'arrows-alt', 'help'=>'question-circle', 'generic'=>'file', 'holiday'=>'umbrella-beach', - 'info'=>'info-circle', 'inventory'=>'boxes', 'intracommreport'=>'globe-europe', 'label'=>'layer-group', 'loan'=>'money-bill-alt', + 'info'=>'info-circle', 'inventory'=>'boxes', 'intracommreport'=>'globe-europe', 'knowledgemanagement'=>'ticket-alt', 'label'=>'layer-group', 'loan'=>'money-bill-alt', 'member'=>'user-alt', 'meeting'=>'chalkboard-teacher', 'mrp'=>'cubes', 'next'=>'arrow-alt-circle-right', - 'trip'=>'wallet', 'group'=>'users', 'movement'=>'people-carry', + 'trip'=>'wallet', 'expensereport'=>'wallet', 'group'=>'users', 'movement'=>'people-carry', 'sign-out'=>'sign-out-alt', 'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', 'check'=>'check', 'bookmark'=>'star', 'bookmark'=>'star', 'bank'=>'university', 'close_title'=>'times', 'delete'=>'trash', 'edit'=>'pencil-alt', 'filter'=>'filter', - 'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarmonth'=>'calendar-alt', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table', + 'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarmonth'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarmonth'=>'calendar-alt', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table', 'intervention'=>'ambulance', 'invoice'=>'file-invoice-dollar', 'multicurrency'=>'dollar-sign', 'order'=>'file-invoice', 'error'=>'exclamation-triangle', 'warning'=>'exclamation-triangle', 'other'=>'square', 'playdisabled'=>'play', 'pdf'=>'file-pdf', 'poll'=>'check-double', 'pos'=>'cash-register', 'preview'=>'binoculars', 'project'=>'project-diagram', 'projectpub'=>'project-diagram', 'projecttask'=>'tasks', 'propal'=>'file-signature', - 'payment'=>'money-check-alt', 'phoning'=>'phone', 'phoning_mobile'=>'mobile-alt', 'phoning_fax'=>'fax', 'previous'=>'arrow-alt-circle-left', 'printer'=>'print', 'product'=>'cube', 'service'=>'concierge-bell', - 'reception'=>'dolly', 'recruitmentjobposition'=>'id-card-alt', 'recruitmentcandidature'=>'id-badge', + 'partnership'=>'handshake', 'payment'=>'money-check-alt', 'phoning'=>'phone', 'phoning_mobile'=>'mobile-alt', 'phoning_fax'=>'fax', 'previous'=>'arrow-alt-circle-left', 'printer'=>'print', 'product'=>'cube', 'service'=>'concierge-bell', + 'recent' => 'question', 'reception'=>'dolly', 'recruitmentjobposition'=>'id-card-alt', 'recruitmentcandidature'=>'id-badge', 'resize'=>'crop', 'supplier_order'=>'dol-order_supplier', 'supplier_proposal'=>'file-signature', 'refresh'=>'redo', 'resource'=>'laptop-house', - 'salary'=>'wallet', 'shipment'=>'dolly', 'stock'=>'box-open', 'stats' => 'chart-bar', 'split'=>'code-branch', 'stripe'=>'stripe-s', 'supplier_invoice'=>'file-invoice-dollar', 'technic'=>'cogs', 'ticket'=>'ticket-alt', + 'security'=>'key', 'salary'=>'wallet', 'shipment'=>'dolly', 'stock'=>'box-open', 'stats' => 'chart-bar', 'split'=>'code-branch', 'stripe'=>'stripe-s', + 'supplier'=>'building', 'supplier_invoice'=>'file-invoice-dollar', 'technic'=>'cogs', 'ticket'=>'ticket-alt', 'timespent'=>'clock', 'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'university', 'title_hrm'=>'umbrella-beach', 'title_agenda'=>'calendar-alt', - 'uparrow'=>'share', 'vcard'=>'address-card', + 'uncheck'=>'times', 'uparrow'=>'share', 'vcard'=>'address-card', 'jabber'=>'comment-o', 'website'=>'globe-americas', 'workstation'=>'pallet', 'conferenceorbooth'=>'chalkboard-teacher', 'eventorganization'=>'project-diagram' @@ -3624,10 +3606,10 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ if (in_array($pictowithouttext, array('dollyrevert', 'member', 'members', 'contract', 'group', 'resource', 'shipment'))) { $morecss = 'em092'; } - if (in_array($pictowithouttext, array('conferenceorbooth', 'collab', 'eventorganization', 'holiday', 'project', 'workstation'))) { + if (in_array($pictowithouttext, array('conferenceorbooth', 'collab', 'eventorganization', 'holiday', 'info', 'project', 'workstation'))) { $morecss = 'em088'; } - if (in_array($pictowithouttext, array('intervention', 'info', 'payment', 'loan', 'stock', 'technic'))) { + if (in_array($pictowithouttext, array('asset', 'intervention', 'payment', 'loan', 'partnership', 'stock', 'technic'))) { $morecss = 'em080'; } @@ -3648,21 +3630,23 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'bill'=>'infobox-commande', 'billa'=>'infobox-commande', 'billr'=>'infobox-commande', 'billd'=>'infobox-commande', 'conferenceorbooth'=>'infobox-project', 'cash-register'=>'infobox-bank_account', 'contract'=>'infobox-contrat', 'check'=>'font-status4', 'collab'=>'infobox-action', 'conversation'=>'infobox-contrat', - 'donation'=>'infobox-commande', 'dollyrevert'=>'flip', 'ecm'=>'infobox-action', + 'donation'=>'infobox-commande', 'dolly'=>'infobox-commande', 'dollyrevert'=>'flip infobox-order_supplier', + 'ecm'=>'infobox-action', 'eventorganization'=>'infobox-project', 'hrm'=>'infobox-adherent', 'group'=>'infobox-adherent', 'intervention'=>'infobox-contrat', + 'incoterm'=>'infobox-supplier_proposal', 'multicurrency'=>'infobox-bank_account', 'members'=>'infobox-adherent', 'member'=>'infobox-adherent', 'money-bill-alt'=>'infobox-bank_account', 'order'=>'infobox-commande', 'user'=>'infobox-adherent', 'users'=>'infobox-adherent', 'error'=>'pictoerror', 'warning'=>'pictowarning', 'switch_on'=>'font-status4', - 'holiday'=>'infobox-holiday', 'info'=>'opacityhigh', 'invoice'=>'infobox-commande', 'loan'=>'infobox-bank_account', - 'eventorganization'=>'infobox-project', + 'holiday'=>'infobox-holiday', 'info'=>'opacityhigh', 'invoice'=>'infobox-commande', + 'knowledgemanagement'=>'infobox-contrat rotate90', 'loan'=>'infobox-bank_account', 'payment'=>'infobox-bank_account', 'poll'=>'infobox-adherent', 'pos'=>'infobox-bank_account', 'project'=>'infobox-project', 'projecttask'=>'infobox-project', 'propal'=>'infobox-propal', 'reception'=>'flip', 'recruitmentjobposition'=>'infobox-adherent', 'recruitmentcandidature'=>'infobox-adherent', 'resource'=>'infobox-action', - 'salary'=>'infobox-bank_account', 'supplier_invoice'=>'infobox-order_supplier', 'supplier_invoicea'=>'infobox-order_supplier', 'supplier_invoiced'=>'infobox-order_supplier', - 'supplier_order'=>'infobox-order_supplier', 'supplier_proposal'=>'infobox-supplier_proposal', - 'ticket'=>'infobox-contrat', 'title_accountancy'=>'infobox-bank_account', 'title_hrm'=>'infobox-holiday', 'trip'=>'infobox-expensereport', 'title_agenda'=>'infobox-action', + 'salary'=>'infobox-bank_account', 'shipment'=>'infobox-commande', 'supplier_invoice'=>'infobox-order_supplier', 'supplier_invoicea'=>'infobox-order_supplier', 'supplier_invoiced'=>'infobox-order_supplier', + 'supplier'=>'infobox-order_supplier', 'supplier_order'=>'infobox-order_supplier', 'supplier_proposal'=>'infobox-supplier_proposal', + 'ticket'=>'infobox-contrat', 'title_accountancy'=>'infobox-bank_account', 'title_hrm'=>'infobox-holiday', 'expensereport'=>'infobox-expensereport', 'trip'=>'infobox-expensereport', 'title_agenda'=>'infobox-action', //'title_setup'=>'infobox-action', 'tools'=>'infobox-action', 'list-alt'=>'imgforviewmode', 'calendar'=>'imgforviewmode', 'calendarweek'=>'imgforviewmode', 'calendarmonth'=>'imgforviewmode', 'calendarday'=>'imgforviewmode', 'calendarperuser'=>'imgforviewmode' ); @@ -3676,11 +3660,14 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'cog'=>'#999', 'companies'=>'#6c6aa8', 'company'=>'#6c6aa8', 'contact'=>'#6c6aa8', 'cron'=>'#555', 'dynamicprice'=>'#a69944', 'edit'=>'#444', 'note'=>'#999', 'error'=>'', 'help'=>'#bbb', 'listlight'=>'#999', 'language'=>'#555', - 'dolly'=>'#a69944', 'dollyrevert'=>'#a69944', 'lot'=>'#a69944', + //'dolly'=>'#a69944', 'dollyrevert'=>'#a69944', + 'lot'=>'#a69944', 'map-marker-alt'=>'#aaa', 'mrp'=>'#a69944', 'product'=>'#a69944', 'service'=>'#a69944', 'inventory'=>'#a69944', 'stock'=>'#a69944', 'movement'=>'#a69944', 'other'=>'#ddd', - 'playdisabled'=>'#ccc', 'printer'=>'#444', 'projectpub'=>'#986c6a', 'reception'=>'#a69944', 'resize'=>'#444', 'rss'=>'#cba', - 'shipment'=>'#a69944', 'stats'=>'#444', 'switch_off'=>'#999', 'technic'=>'#999', 'timespent'=>'#555', 'uparrow'=>'#555', 'user-cog'=>'#999', 'country'=>'#aaa', 'globe-americas'=>'#aaa', + 'partnership'=>'#6c6aa8', 'playdisabled'=>'#ccc', 'printer'=>'#444', 'projectpub'=>'#986c6a', 'reception'=>'#a69944', 'resize'=>'#444', 'rss'=>'#cba', + //'shipment'=>'#a69944', + 'security'=>'#999', 'stats'=>'#444', 'switch_off'=>'#999', 'technic'=>'#999', 'timespent'=>'#555', + 'uncheck'=>'#800', 'uparrow'=>'#555', 'user-cog'=>'#999', 'country'=>'#aaa', 'globe-americas'=>'#aaa', 'website'=>'#304', 'workstation'=>'#a69944' ); if (isset($arrayconvpictotocolor[$pictowithouttext])) { @@ -4522,7 +4509,7 @@ function dol_print_error($db = '', $error = '', $errors = null) } $langs->loadLangs(array("main", "errors")); // Reload main because language may have been set only on previous line so we have to reload files we need. // This should not happen, except if there is a bug somewhere. Enabled and check log in such case. - print 'This website or feature is currently temporarly not available or failed after a technical error.

    This may be due to a maintenance operation. Current status of operation are on next line...

    '."\n"; + print 'This website or feature is currently temporarly not available or failed after a technical error.

    This may be due to a maintenance operation. Current status of operation ('.dol_print_date(dol_now(), 'dayhourrfc').') are on next line...

    '."\n"; print $langs->trans("DolibarrHasDetectedError").'. '; print $langs->trans("YouCanSetOptionDolibarrMainProdToZero"); define("MAIN_CORE_ERROR", 1); @@ -6671,6 +6658,8 @@ function dol_textishtml($msg, $option = 0) return true; } elseif (preg_match('/<\/textarea/i', $msg)) { return true; + } elseif (preg_match('/<(b|em|i|u)>/i', $msg)) { + return true; } elseif (preg_match('/
    /i', $msg)) { return true; - } elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i', $msg)) { - return true; - } elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/>/i', $msg)) { + } elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/?>/i', $msg)) { return true; } elseif (preg_match('/]*src[^<>]*>/i', $msg)) { return true; // must accept @@ -6835,6 +6822,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__MEMBER_CIVILITY__'] = '__MEMBER_CIVILITY__'; $substitutionarray['__MEMBER_FIRSTNAME__'] = '__MEMBER_FIRSTNAME__'; $substitutionarray['__MEMBER_LASTNAME__'] = '__MEMBER_LASTNAME__'; + $substitutionarray['__MEMBER_USER_LOGIN_INFORMATION__'] = 'Login and pass of the external user account'; /*$substitutionarray['__MEMBER_NOTE_PUBLIC__'] = '__MEMBER_NOTE_PUBLIC__'; $substitutionarray['__MEMBER_NOTE_PRIVATE__'] = '__MEMBER_NOTE_PRIVATE__';*/ } @@ -6896,8 +6884,6 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, // For backward compatibility $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null)); $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null); - $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null)); - $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null); $substitutionarray['__SUPPLIER_ORDER_DATE_DELIVERY__'] = (isset($object->date_livraison) ? dol_print_date($object->date_livraison, 'day', 0, $outputlangs) : ''); $substitutionarray['__SUPPLIER_ORDER_DELAY_DELIVERY__'] = (isset($object->availability_code) ? ($outputlangs->transnoentities("AvailabilityType".$object->availability_code) != ('AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset(isset($object->availability) ? $object->availability : '')) : ''); @@ -6910,6 +6896,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } $substitutionarray['__MEMBER_FIRSTNAME__'] = (isset($object->firstname) ? $object->firstname : ''); $substitutionarray['__MEMBER_LASTNAME__'] = (isset($object->lastname) ? $object->lastname : ''); + $substitutionarray['__MEMBER_USER_LOGIN_INFORMATION__'] = ''; if (method_exists($object, 'getFullName')) { $substitutionarray['__MEMBER_FULLNAME__'] = $object->getFullName($outputlangs); } @@ -7102,6 +7089,11 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } else { $substitutionarray['__DIRECTDOWNLOAD_URL_CONTRACT__'] = ''; } + if (!empty($conf->global->SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'supplier_proposal') { + $substitutionarray['__DIRECTDOWNLOAD_URL_SUPPLIER_PROPOSAL__'] = $object->getLastMainDocLink($object->element); + } else { + $substitutionarray['__DIRECTDOWNLOAD_URL_SUPPLIER_PROPOSAL__'] = ''; + } if (is_object($object) && $object->element == 'propal') { $substitutionarray['__URL_PROPOSAL__'] = DOL_MAIN_URL_ROOT."/comm/propal/card.php?id=".$object->id; @@ -7115,6 +7107,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if (is_object($object) && $object->element == 'contrat') { $substitutionarray['__URL_CONTRACT__'] = DOL_MAIN_URL_ROOT."/contrat/card.php?id=".$object->id; } + if (is_object($object) && $object->element == 'supplier_proposal') { + $substitutionarray['__URL_SUPPLIER_PROPOSAL__'] = DOL_MAIN_URL_ROOT."/supplier_proposal/card.php?id=".$object->id; + } } if (is_object($object) && $object->element == 'action') { @@ -7144,14 +7139,14 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__AMOUNT_TAX3__'] = is_object($object) ? $object->total_localtax2 : ''; } - $substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : ''; - $substitutionarray['__AMOUNT_EXCL_TAX_FORMATED__'] = is_object($object) ? ($object->total_ht ? price($object->total_ht, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : ''; - $substitutionarray['__AMOUNT_VAT_FORMATED__'] = is_object($object) ? (isset($object->total_vat) ? price($object->total_vat, 0, $outputlangs, 0, 0, -1, $conf->currency) : ($object->total_tva ? price($object->total_tva, 0, $outputlangs, 0, 0, -1, $conf->currency) : null)) : ''; + $substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : ''; + $substitutionarray['__AMOUNT_EXCL_TAX_FORMATED__'] = is_object($object) ? ($object->total_ht ? price($object->total_ht, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : ''; + $substitutionarray['__AMOUNT_VAT_FORMATED__'] = is_object($object) ? (isset($object->total_vat) ? price($object->total_vat, 0, $outputlangs, 0, -1, -1, $conf->currency) : ($object->total_tva ? price($object->total_tva, 0, $outputlangs, 0, -1, -1, $conf->currency) : null)) : ''; if ($onlykey != 2 || $mysoc->useLocalTax(1)) { - $substitutionarray['__AMOUNT_TAX2_FORMATED__'] = is_object($object) ? ($object->total_localtax1 ? price($object->total_localtax1, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : ''; + $substitutionarray['__AMOUNT_TAX2_FORMATED__'] = is_object($object) ? ($object->total_localtax1 ? price($object->total_localtax1, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : ''; } if ($onlykey != 2 || $mysoc->useLocalTax(2)) { - $substitutionarray['__AMOUNT_TAX3_FORMATED__'] = is_object($object) ? ($object->total_localtax2 ? price($object->total_localtax2, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : ''; + $substitutionarray['__AMOUNT_TAX3_FORMATED__'] = is_object($object) ? ($object->total_localtax2 ? price($object->total_localtax2, 0, $outputlangs, 0, -1, -1, $conf->currency) : null) : ''; } $substitutionarray['__AMOUNT_MULTICURRENCY__'] = (is_object($object) && isset($object->multicurrency_total_ttc)) ? $object->multicurrency_total_ttc : ''; @@ -7219,13 +7214,15 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, * complete_substitutions_array($substitutionarray, $langs, $thirdparty); * $mesg = make_substitutions($mesg, $substitutionarray, $langs); * - * @param string $text Source string in which we must do substitution - * @param array $substitutionarray Array with key->val to substitute. Example: array('__MYKEY__' => 'MyVal', ...) - * @param Translate $outputlangs Output language - * @return string Output string after substitutions + * @param string $text Source string in which we must do substitution + * @param array $substitutionarray Array with key->val to substitute. Example: array('__MYKEY__' => 'MyVal', ...) + * @param Translate $outputlangs Output language + * @param int $converttextinhtmlifnecessary 0=Convert only value into HTML if text is already in HTML + * 1=Will also convert initial $text into HTML if we try to insert one value that is HTML + * @return string Output string after substitutions * @see complete_substitutions_array(), getCommonSubstitutionArray() */ -function make_substitutions($text, $substitutionarray, $outputlangs = null) +function make_substitutions($text, $substitutionarray, $outputlangs = null, $converttextinhtmlifnecessary = 0) { global $conf, $langs; @@ -7237,22 +7234,41 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null) $outputlangs = $langs; } + // Is initial text HTML or simple text ? + $msgishtml = 0; + if (dol_textishtml($text, 1)) { + $msgishtml = 1; + } + // Make substitution for language keys: __(AnyTranslationKey)__ or __(AnyTranslationKey|langfile)__ if (is_object($outputlangs)) { $reg = array(); while (preg_match('/__\(([^\)]+)\)__/', $text, $reg)) { - $msgishtml = 0; - if (dol_textishtml($text, 1)) { - $msgishtml = 1; - } - // If key is __(TranslationKey|langfile)__, then force load of langfile.lang $tmp = explode('|', $reg[1]); if (!empty($tmp[1])) { $outputlangs->load($tmp[1]); } - $text = preg_replace('/__\('.preg_quote($reg[1], '/').'\)__/', $msgishtml ?dol_htmlentitiesbr($outputlangs->transnoentitiesnoconv($reg[1])) : $outputlangs->transnoentitiesnoconv($reg[1]), $text); + $value = $outputlangs->transnoentitiesnoconv($reg[1]); + + if (empty($converttextinhtmlifnecessary)) { + // convert $newval into HTML is necessary + $text = preg_replace('/__\('.preg_quote($reg[1], '/').'\)__/', $msgishtml ? dol_htmlentitiesbr($value) : $value, $text); + } else { + if (! $msgishtml) { + $valueishtml = dol_textishtml($value, 1); + + if ($valueishtml) { + $text = dol_htmlentitiesbr($text); + $msgishtml = 1; + } + } else { + $value = dol_nl2br("$value"); + } + + $text = preg_replace('/__\('.preg_quote($reg[1], '/').'\)__/', $value, $text); + } } } @@ -7260,18 +7276,30 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null) // Must be after the substitution of translation, so if the text of translation contains a string __[xxx]__, it is also converted. $reg = array(); while (preg_match('/__\[([^\]]+)\]__/', $text, $reg)) { - $msgishtml = 0; - if (dol_textishtml($text, 1)) { - $msgishtml = 1; - } - $keyfound = $reg[1]; if (isASecretKey($keyfound)) { - $newval = '*****forbidden*****'; + $value = '*****forbidden*****'; } else { - $newval = empty($conf->global->$keyfound) ? '' : $conf->global->$keyfound; + $value = empty($conf->global->$keyfound) ? '' : $conf->global->$keyfound; + } + + if (empty($converttextinhtmlifnecessary)) { + // convert $newval into HTML is necessary + $text = preg_replace('/__\['.preg_quote($keyfound, '/').'\]__/', $msgishtml ? dol_htmlentitiesbr($value) : $value, $text); + } else { + if (! $msgishtml) { + $valueishtml = dol_textishtml($value, 1); + + if ($valueishtml) { + $text = dol_htmlentitiesbr($text); + $msgishtml = 1; + } + } else { + $value = dol_nl2br("$value"); + } + + $text = preg_replace('/__\['.preg_quote($keyfound, '/').'\]__/', $value, $text); } - $text = preg_replace('/__\['.preg_quote($keyfound, '/').'\]__/', $msgishtml ?dol_htmlentitiesbr($newval) : $newval, $text); } // Make substitition for array $substitutionarray @@ -7284,7 +7312,21 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null) $value = ''; // Protection } - $text = str_replace("$key", "$value", $text); // We must keep the " to work when value is 123.5 for example + if (empty($converttextinhtmlifnecessary)) { + $text = str_replace("$key", "$value", $text); // We must keep the " to work when value is 123.5 for example + } else { + if (! $msgishtml) { + $valueishtml = dol_textishtml($value, 1); + + if ($valueishtml) { + $text = dol_htmlentitiesbr($text); + $msgishtml = 1; + } + } else { + $value = dol_nl2br("$value"); + } + $text = str_replace("$key", "$value", $text); // We must keep the " to work when value is 123.5 for example + } } return $text; @@ -7308,18 +7350,7 @@ function complete_substitutions_array(&$substitutionarray, $outputlangs, $object require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - // Add a substitution key for each extrafields, using key __EXTRA_XXX__ - // TODO Remove this. Already available into the getCommonSubstitutionArray used to build the substitution array. - /*if (is_object($object) && is_array($object->array_options)) - { - foreach($object->array_options as $key => $val) - { - $keyshort=preg_replace('/^(options|extra)_/','',$key); - $substitutionarray['__EXTRAFIELD_'.$keyshort.'__']=$val; - // For backward compatibiliy - $substitutionarray['%EXTRA_'.$keyshort.'%']=$val; - } - }*/ + // Note: substitution key for each extrafields, using key __EXTRA_XXX__ is already available into the getCommonSubstitutionArray used to build the substitution array. // Check if there is external substitution to do, requested by plugins $dirsubstitutions = array_merge(array(), (array) $conf->modules_parts['substitutions']); @@ -7968,6 +7999,29 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1) global $obj; // To get $obj used into list when dol_eval is used for computed fields and $obj is not yet $object global $soc; // For backward compatibility + // Replace dangerous char (used for RCE), we allow only PHP variable testing. + if (strpos($s, '`') !== false) { + return 'Bad string syntax to evaluate: '.$s; + } + + // We block using of php exec or php file functions + $forbiddenphpstrings = array("exec(", "passthru(", "shell_exec(", "system(", "proc_open(", "popen(", "eval(", "dol_eval(", "executeCLI("); + $forbiddenphpstrings = array_merge($forbiddenphpstrings, array("fopen(", "file_put_contents(", "fputs(", "fputscsv(", "fwrite(", "fpassthru(", "unlink(", "mkdir(", "rmdir(", "symlink(", "touch(", "umask(")); + $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('function(', '$$', 'call_user_func(')); + $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST')); + $forbiddenphpregex = 'global\s+\$'; + do { + $oldstringtoclean = $s; + $s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s); + $s = preg_replace('/'.$forbiddenphpregex.'/', '__forbiddenstring__', $s); + //$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod( + } while ($oldstringtoclean != $s); + + if (strpos($s, '__forbiddenstring__') !== false) { + dol_syslog('Bad string syntax to evaluate: '.$s, LOG_WARNING); + return 'Bad string syntax to evaluate: '.$s; + } + //print $s."
    \n"; if ($returnvalue) { if ($hideerrors) { @@ -8042,7 +8096,7 @@ function picto_from_langcode($codelang, $moreatt = '') * Return default language from country code. * Return null if not found. * - * @param string $countrycode Country code like 'US', 'FR', 'CA', ... + * @param string $countrycode Country code like 'US', 'FR', 'CA', 'ES', 'MX', ... * @return string Value of locale like 'en_US', 'fr_FR', ... */ function getLanguageCodeFromCountryCode($countrycode) @@ -8066,6 +8120,9 @@ function getLanguageCodeFromCountryCode($countrycode) if ($mysoc->country_code == 'DE') { return 'de_CH'; } + if ($mysoc->country_code == 'IT') { + return 'it_CH'; + } } // Locale list taken from: @@ -8206,6 +8263,7 @@ function getLanguageCodeFromCountryCode($countrycode) 'pt-BR', 'pt-PT', 'rm-CH', + 'ro-MD', 'ro-RO', 'ru-RU', 'rw-RW', @@ -8364,12 +8422,12 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, // No need to make a return $head. Var is modified as a reference if (!empty($hookmanager)) { - $parameters = array('object' => $object, 'mode' => $mode, 'head' => $head); + $parameters = array('object' => $object, 'mode' => $mode, 'head' => &$head); $reshook = $hookmanager->executeHooks('completeTabsHead', $parameters); if ($reshook > 0) { $head = $hookmanager->resArray; - $h = count($head); } + $h = count($head); } } @@ -9365,7 +9423,8 @@ function getDictvalue($tablename, $field, $id, $checkentity = false, $rowidfield if (!isset($dictvalues[$tablename])) { $dictvalues[$tablename] = array(); - $sql = 'SELECT * FROM '.$tablename.' WHERE 1'; // Here select * is allowed as it is generic code and we don't have list of fields + + $sql = 'SELECT * FROM '.$tablename.' WHERE 1 = 1'; // Here select * is allowed as it is generic code and we don't have list of fields if ($checkentity) { $sql .= ' AND entity IN (0,'.getEntity($tablename).')'; } @@ -9640,7 +9699,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st /** * Function dolGetButtonAction * - * @param string $label label of button no html : use in alt attribute for accessibility $html is not empty + * @param string $label label of button without HTML : use in alt attribute for accessibility $html is not empty * @param string $html optional : content with html * @param string $actionType default, delete, danger * @param string $url the url for link @@ -9654,11 +9713,13 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = $class = 'butAction'; if ($actionType == 'danger' || $actionType == 'delete') { $class = 'butActionDelete'; + if (strpos($url, 'token=') === false) $url .= '&token='.newToken(); } $attr = array( - 'class' => $class - ,'href' => empty($url) ? '' : $url + 'class' => $class, + 'href' => empty($url) ? '' : $url, + 'title' => $label ); if (empty($html)) { @@ -9707,7 +9768,18 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = $tag = !empty($attr['href']) ? 'a' : 'span'; - return '
    <'.$tag.' '.$compiledAttributes.'>'.$html.'
    '; + return '<'.$tag.' '.$compiledAttributes.'>'.$html.''; +} + +/** + * Add space between dolGetButtonTitle + * + * @param string $moreClass more css class label + * @return string html of title separator + */ +function dolGetButtonTitleSeparator($moreClass = "") +{ + return ''; } /** @@ -9718,7 +9790,7 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = * @param string $iconClass class for icon element (Example: 'fa fa-file') * @param string $url the url for link * @param string $id attribute id of button - * @param int $status 0 no user rights, 1 active, -1 Feature Disabled, -2 disable Other reason use helpText as tooltip + * @param int $status 0 no user rights, 1 active, 2 current action or selected, -1 Feature Disabled, -2 disable Other reason use helpText as tooltip * @param array $params various params for future : recommended rather than adding more function arguments * @return string html button */ @@ -9753,7 +9825,9 @@ function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $u $useclassfortooltip = 0; } - if ($status <= 0) { + if ($status == 2) { + $attr['class'] .= ' btnTitleSelected'; + } elseif ($status <= 0) { $attr['class'] .= ' refused'; $attr['href'] = ''; @@ -10193,14 +10267,27 @@ function readfileLowMemory($fullpath_original_file_osencoded, $method = -1) } /** - * Create a button to copy $valuetoprint in the clipboard + * Create a button to copy $valuetocopy in the clipboard. + * Code that handle the click is inside lib_foot.jsp.php * - * @param string $valuetoprint The value to print - * @param int $showonlyonhover Show the copypaste button only on hover + * @param string $valuetocopy The value to print + * @param int $showonlyonhover Show the copy-paste button only on hover + * @param string $texttoshow Replace the value to show with this text * @return string The string to print for the button */ -function showValueWithClipboardCPButton($valuetoprint, $showonlyonhover = 1) +function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $texttoshow = '') { - $result = ''.$valuetoprint.''; + global $conf; + + /*if (!empty($conf->dol_no_mouse_hover)) { + $showonlyonhover = 0; + }*/ + + if ($texttoshow) { + $result = ''.$valuetocopy.''.$texttoshow.''; + } else { + $result = ''.$valuetocopy.''; + } + return $result; } diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index e279ced2a3d..6f5d2ccb891 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -1043,7 +1043,7 @@ function get_next_value($db, $mask, $table, $field, $where = '', $objsoc = '', $ $regType = array(); if (preg_match('/\{(t+)\}/i', $mask, $regType)) { $masktype = $regType[1]; - $masktype_value = substr(preg_replace('/^TE_/', '', $objsoc->typent_code), 0, dol_strlen($regType[1])); // get n first characters of thirdpaty typent_code (where n is length in mask) + $masktype_value = substr(preg_replace('/^TE_/', '', $objsoc->typent_code), 0, dol_strlen($regType[1])); // get n first characters of thirdparty typent_code (where n is length in mask) $masktype_value = str_pad($masktype_value, dol_strlen($regType[1]), "#", STR_PAD_RIGHT); // we fill on right with # to have same number of char than into mask } else { $masktype = ''; @@ -2679,57 +2679,6 @@ if (!function_exists('dolEscapeXML')) { } -/** - * Return automatic or manual in current language - * - * @param string $automaticmanual Value to test (1, 'automatic', 'true' or 0, 'manual', 'false') - * @param integer $case 1=Yes/No, 0=yes/no, 2=Disabled checkbox, 3=Disabled checkbox + Automatic/Manual - * @param int $color 0=texte only, 1=Text is formated with a color font style ('ok' or 'error'), 2=Text is formated with 'ok' color. - * @return string HTML string - */ -function autoOrManual($automaticmanual, $case = 1, $color = 0) -{ - global $langs; - $result = 'unknown'; - $classname = ''; - if ($automaticmanual == 1 || strtolower($automaticmanual) == 'automatic' || strtolower($automaticmanual) == 'true') { // A mettre avant test sur no a cause du == 0 - $result = $langs->trans('automatic'); - if ($case == 1 || $case == 3) { - $result = $langs->trans("Automatic"); - } - if ($case == 2) { - $result = ''; - } - if ($case == 3) { - $result = ' '.$result; - } - - $classname = 'ok'; - } elseif ($automaticmanual == 0 || strtolower($automaticmanual) == 'manual' || strtolower($automaticmanual) == 'false') { - $result = $langs->trans("manual"); - if ($case == 1 || $case == 3) { - $result = $langs->trans("Manual"); - } - if ($case == 2) { - $result = ''; - } - if ($case == 3) { - $result = ' '.$result; - } - - if ($color == 2) { - $classname = 'ok'; - } else { - $classname = 'error'; - } - } - if ($color) { - return ''.$result.''; - } - return $result; -} - - /** * Convert links to local wrapper to medias files into a string into a public external URL readable on internet * diff --git a/htdocs/core/lib/geturl.lib.php b/htdocs/core/lib/geturl.lib.php index 531e366de77..f87e7b7b4cd 100644 --- a/htdocs/core/lib/geturl.lib.php +++ b/htdocs/core/lib/geturl.lib.php @@ -24,7 +24,9 @@ /** * Function to get a content from an URL (use proxy if proxy defined). * Support Dolibarr setup for timeout and proxy. - * Enhancement of CURL to add an anti SSRF protection. + * Enhancement of CURL to add an anti SSRF protection: + * - you can set MAIN_SECURITY_ANTI_SSRF_SERVER_IP to set static ip of server + * - common local lookup ips like 127.*.*.* are automatically added * * @param string $url URL to call. * @param string $postorget 'POST', 'GET', 'HEAD', 'PUT', 'PUTALREADYFORMATED', 'POSTALREADYFORMATED', 'DELETE' @@ -155,7 +157,7 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = // Deny some reserved host names if (in_array($hosttocheck, array('metadata.google.internal'))) { $info['http_code'] = 400; - $info['content'] = 'Error bad hostname (Used by Google metadata). This value for hostname is not allowed.'; + $info['content'] = 'Error bad hostname '.$hosttocheck.' (Used by Google metadata). This value for hostname is not allowed.'; break; } @@ -165,11 +167,17 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = } elseif (in_array($hosttocheck, array('ip6-localhost', 'ip6-loopback'))) { $iptocheck = '::1'; } else { - // TODO Resolve $hosttocheck to get the IP $iptocheck and set CURLOPT_CONNECT_TO to use this ip - $iptocheck = $hosttocheck; + // Resolve $hosttocheck to get the IP $iptocheck and set CURLOPT_CONNECT_TO to use this ip so curl will not try another resolution that may give a different result + if (function_exists('gethostbyname')) { + $iptocheck = gethostbyname($hosttocheck); + } else { + $iptocheck = $hosttocheck; + } + // TODO Resolve ip v6 } - if (!filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { // This is not an IP + // Check $iptocheck is an IP (v4 or v6), if not clear value. + if (!filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { // This is not an IP, we clean data $iptocheck = '0'; // } @@ -181,18 +189,44 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = $info['content'] = 'Error bad hostname IP (private or reserved range). Must be an external URL.'; break; } - if (in_array($iptocheck, array('100.100.100.200'))) { + if (!empty($_SERVER["SERVER_ADDR"]) && $iptocheck == $_SERVER["SERVER_ADDR"]) { $info['http_code'] = 400; - $info['content'] = 'Error bad hostname IP (Used by Alibaba metadata). Must be an external URL.'; + $info['content'] = 'Error bad hostname IP (IP is a local IP). Must be an external URL.'; + break; + } + if (!empty($conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP) && in_array($iptocheck, explode(',', $conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP))) { + $info['http_code'] = 400; + $info['content'] = 'Error bad hostname IP (IP is a local IP defined into MAIN_SECURITY_SERVER_IP). Must be an external URL.'; break; } } if ($localurl == 1) { // Only local url allowed (dangerous, may allow to get metadata on server or make internal port scanning) + // Deny ips NOT like 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8 et 240.0.0.0/4, ::1/128, ::/128, ::ffff:0:0/96, fe80::/10... if (filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) { $info['http_code'] = 400; - $info['content'] = 'Error bad hostname. Must be a local URL.'; + $info['content'] = 'Error bad hostname '.$iptocheck.'. Must be a local URL.'; break; } + if (!empty($conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP) && !in_array($iptocheck, explode(',', $conf->global->MAIN_SECURITY_ANTI_SSRF_SERVER_IP))) { + $info['http_code'] = 400; + $info['content'] = 'Error bad hostname IP (IP is not a local IP defined into list MAIN_SECURITY_SERVER_IP). Must be a local URL in allowed list.'; + break; + } + } + + // Common check (local and external) + if (in_array($iptocheck, array('100.100.100.200'))) { + $info['http_code'] = 400; + $info['content'] = 'Error bad hostname IP (Used by Alibaba metadata). Must be an external URL.'; + break; + } + + // Set CURLOPT_CONNECT_TO so curl will not try another resolution that may give a different result. Possible only on PHP v7+ + if (defined('CURLOPT_CONNECT_TO')) { + $connect_to = array(sprintf("%s:%d:%s:%d", $newUrlArray['host'], $newUrlArray['port'], $iptocheck, $newUrlArray['port'])); + //var_dump($newUrlArray); + //var_dump($connect_to); + curl_setopt($ch, CURLOPT_CONNECT_TO, $connect_to); } } @@ -220,7 +254,7 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = $rep = array(); if (curl_errno($ch)) { - // Ad keys to $rep + // Add keys to $rep $rep['content'] = $response; // moving to display page to display curl errors @@ -231,14 +265,16 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = } else { //$info = curl_getinfo($ch); - // Ad keys to $rep + // Add keys to $rep $rep = $info; //$rep['header_size']=$info['header_size']; //$rep['http_code']=$info['http_code']; dol_syslog("getURLContent http_code=".$rep['http_code']); // Add more keys to $rep - $rep['content'] = $response; + if ($response) { + $rep['content'] = $response; + } $rep['curl_error_no'] = ''; $rep['curl_error_msg'] = ''; } diff --git a/htdocs/core/lib/images.lib.php b/htdocs/core/lib/images.lib.php index 36e8cef6bfe..0a0ebe3ce02 100644 --- a/htdocs/core/lib/images.lib.php +++ b/htdocs/core/lib/images.lib.php @@ -148,10 +148,11 @@ function dol_getImageSize($file, $url = false) * @param int $src_x Position of croping image in source image (not use if mode=0) * @param int $src_y Position of croping image in source image (not use if mode=0) * @param string $filetowrite Path of file to write (overwrite source file if not provided) + * @param int $newquality Value for the new quality of image, for supported format (use 0 for maximum/unchanged). * @return string File name if OK, error message if KO * @see dol_convert_file() */ -function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, $src_y = 0, $filetowrite = '') +function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, $src_y = 0, $filetowrite = '', $newquality = 0) { require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; @@ -181,10 +182,13 @@ function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, $filetoread = realpath(dol_osencode($file)); // Chemin canonique absolu de l'image - $infoImg = getimagesize($filetoread); // Recuperation des infos de l'image + $infoImg = getimagesize($filetoread); // Get data about src image $imgWidth = $infoImg[0]; // Largeur de l'image $imgHeight = $infoImg[1]; // Hauteur de l'image + $imgTargetName = ($filetowrite ? $filetowrite : $file); + $newExt = strtolower(pathinfo($imgTargetName, PATHINFO_EXTENSION)); + if ($mode == 0) { // If resize, we check parameters if (!empty($filetowrite) && $filetowrite != $file && $newWidth <= 0 && $newHeight <= 0) { $newWidth = $imgWidth; @@ -199,6 +203,7 @@ function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, } } + // Test function to read source image exists $imgfonction = ''; switch ($infoImg[2]) { case 1: // IMG_GIF @@ -213,116 +218,140 @@ function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, case 4: // IMG_WBMP $imgfonction = 'imagecreatefromwbmp'; break; - case 17: // IMG_WBMP + case 18: // IMG_WEBP $imgfonction = 'imagecreatefromwebp'; break; } if ($imgfonction) { if (!function_exists($imgfonction)) { // Fonctions de conversion non presente dans ce PHP - return 'Resize not possible. This PHP does not support GD functions '.$imgfonction; + return 'Read of image not possible. This PHP does not support GD functions '.$imgfonction; } } - // Initialisation des variables selon l'extension de l'image + // Test function to write target image exists + if ($filetowrite) { + $imgfonction = ''; + switch ($newExt) { + case 'gif': // IMG_GIF + $imgfonction = 'imagecreatefromgif'; + break; + case 'jpg': // IMG_JPG + $imgfonction = 'imagecreatefromjpeg'; + break; + case 'png': // IMG_PNG + $imgfonction = 'imagecreatefrompng'; + break; + case 'bmp': // IMG_WBMP + $imgfonction = 'imagecreatefromwbmp'; + break; + case 'webp': // IMG_WEBP + $imgfonction = 'imagecreatefromwebp'; + break; + } + if ($imgfonction) { + if (!function_exists($imgfonction)) { + // Fonctions de conversion non presente dans ce PHP + return 'Write of image not possible. This PHP does not support GD functions '.$imgfonction; + } + } + } + + // Read source image file switch ($infoImg[2]) { case 1: // Gif $img = imagecreatefromgif($filetoread); $extImg = '.gif'; // File name extension of image - $newquality = 'NU'; // Quality is not used for this format break; case 2: // Jpg $img = imagecreatefromjpeg($filetoread); $extImg = '.jpg'; - $newquality = 100; // % quality maximum break; case 3: // Png $img = imagecreatefrompng($filetoread); $extImg = '.png'; - $newquality = 0; // No compression (0-9) break; case 4: // Bmp $img = imagecreatefromwbmp($filetoread); $extImg = '.bmp'; - $newquality = 'NU'; // Quality is not used for this format break; case 18: // Webp $img = imagecreatefromwebp($filetoread); $extImg = '.webp'; - $newquality = '100'; // % quality maximum break; } - // Create empty image - if ($infoImg[2] == 1) { - // Compatibilite image GIF - $imgThumb = imagecreate($newWidth, $newHeight); + // Create empty image for target + if ($newExt == 'gif') { + // Compatibility image GIF + $imgTarget = imagecreate($newWidth, $newHeight); } else { - $imgThumb = imagecreatetruecolor($newWidth, $newHeight); + $imgTarget = imagecreatetruecolor($newWidth, $newHeight); } // Activate antialiasing for better quality if (function_exists('imageantialias')) { - imageantialias($imgThumb, true); + imageantialias($imgTarget, true); } // This is to keep transparent alpha channel if exists (PHP >= 4.2) if (function_exists('imagesavealpha')) { - imagesavealpha($imgThumb, true); + imagesavealpha($imgTarget, true); } - // Initialisation des variables selon l'extension de l'image - switch ($infoImg[2]) { - case 1: // Gif - $trans_colour = imagecolorallocate($imgThumb, 255, 255, 255); // On procede autrement pour le format GIF - imagecolortransparent($imgThumb, $trans_colour); + // Set transparent color according to image extension + switch ($newExt) { + case 'gif': // Gif + $trans_colour = imagecolorallocate($imgTarget, 255, 255, 255); // On procede autrement pour le format GIF + imagecolortransparent($imgTarget, $trans_colour); break; - case 2: // Jpg - $trans_colour = imagecolorallocatealpha($imgThumb, 255, 255, 255, 0); + case 'jpg': // Jpg + $trans_colour = imagecolorallocatealpha($imgTarget, 255, 255, 255, 0); break; - case 3: // Png - imagealphablending($imgThumb, false); // Pour compatibilite sur certain systeme - $trans_colour = imagecolorallocatealpha($imgThumb, 255, 255, 255, 127); // Keep transparent channel + case 'png': // Png + imagealphablending($imgTarget, false); // Pour compatibilite sur certain systeme + $trans_colour = imagecolorallocatealpha($imgTarget, 255, 255, 255, 127); // Keep transparent channel break; - case 4: // Bmp - $trans_colour = imagecolorallocatealpha($imgThumb, 255, 255, 255, 0); + case 'bmp': // Bmp + $trans_colour = imagecolorallocatealpha($imgTarget, 255, 255, 255, 0); break; - case 18: // Webp - $trans_colour = imagecolorallocatealpha($imgThumb, 255, 255, 255, 127); + case 'webp': // Webp + $trans_colour = imagecolorallocatealpha($imgTarget, 255, 255, 255, 127); break; } if (function_exists("imagefill")) { - imagefill($imgThumb, 0, 0, $trans_colour); + imagefill($imgTarget, 0, 0, $trans_colour); } - dol_syslog("dol_imageResizeOrCrop: convert image from ($imgWidth x $imgHeight) at position ($src_x x $src_y) to ($newWidth x $newHeight) as $extImg, newquality=$newquality"); - //imagecopyresized($imgThumb, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight); // Insere l'image de base redimensionnee - imagecopyresampled($imgThumb, $img, 0, 0, $src_x, $src_y, $newWidth, $newHeight, ($mode == 0 ? $imgWidth : $newWidth), ($mode == 0 ? $imgHeight : $newHeight)); // Insere l'image de base redimensionnee - - $imgTargetName = ($filetowrite ? $filetowrite : $file); + dol_syslog("dol_imageResizeOrCrop: convert image from ($imgWidth x $imgHeight) at position ($src_x x $src_y) to ($newWidth x $newHeight) as $extImg"); + //imagecopyresized($imgTarget, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight); // Insere l'image de base redimensionnee + imagecopyresampled($imgTarget, $img, 0, 0, $src_x, $src_y, $newWidth, $newHeight, ($mode == 0 ? $imgWidth : $newWidth), ($mode == 0 ? $imgHeight : $newHeight)); // Insere l'image de base redimensionnee // Check if permission are ok //$fp = fopen($imgTargetName, "w"); //fclose($fp); - $newExt = strtolower(pathinfo($imgTargetName, PATHINFO_EXTENSION)); - // Create image on disk (overwrite file if exists) switch ($newExt) { case 'gif': // Gif - imagegif($imgThumb, $imgTargetName); + $newquality = 'NU'; // Quality is not used for this format + imagegif($imgTarget, $imgTargetName); break; case 'jpg': // Jpg - imagejpeg($imgThumb, $imgTargetName, $newquality); + $newquality = ($newquality ? $newquality : '100'); // % quality maximum + imagejpeg($imgTarget, $imgTargetName, $newquality); break; case 'png': // Png - imagepng($imgThumb, $imgTargetName, $newquality); + $newquality = 0; // No compression (0-9) + imagepng($imgTarget, $imgTargetName, $newquality); break; case 'bmp': // Bmp - imagewbmp($imgThumb, $imgTargetName); + $newquality = 'NU'; // Quality is not used for this format + imagewbmp($imgTarget, $imgTargetName); break; case 'webp': // Webp - imagewebp($imgThumb, $imgTargetName, $newquality); + $newquality = ($newquality ? $newquality : '100'); // % quality maximum + imagewebp($imgTarget, $imgTargetName, $newquality); break; } @@ -333,7 +362,7 @@ function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x = 0, // Free memory. This does not delete image. imagedestroy($img); - imagedestroy($imgThumb); + imagedestroy($imgTarget); clearstatcache(); // File was replaced by a modified one, so we clear file caches. diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php index b3a9ed7b453..c328d659b93 100644 --- a/htdocs/core/lib/invoice.lib.php +++ b/htdocs/core/lib/invoice.lib.php @@ -315,7 +315,8 @@ function getCustomerInvoicePieChart($socid = 0) $dolgraph->setShowLegend(2); $dolgraph->setShowPercent(1); $dolgraph->SetType(['pie']); - $dolgraph->setHeight('200'); + $dolgraph->setHeight('150'); + $dolgraph->setWidth('300'); $dolgraph->draw('idgraphcustomerinvoices'); $result .= '
  • '; + $result .= ''; + $result .= ''; + $result .= ''; + + if ($conf->use_javascript_ajax) { + $dolgraph = new DolGraph(); + $dolgraph->SetData($dataseries); + $dolgraph->SetDataColor(array_values($colorseries)); + $dolgraph->setShowLegend(2); + $dolgraph->setShowPercent(1); + $dolgraph->SetType(['pie']); + $dolgraph->setHeight('150'); + $dolgraph->setWidth('300'); + if ($mode == 'customers') { + $dolgraph->draw('idgraphcustomerinvoices'); + } elseif ($mode == 'fourn' || $mode == 'suppliers') { + $dolgraph->draw('idgraphfourninvoices'); + } else { + return ''; + } + $result .= ''; + $result .= ''; + $result .= ''; + } else { + // Print text lines + } + + $result .= '
    '.$langs->trans("Statistics").' - '; + if ($mode == 'customers') { + $result .= $langs->trans("CustomerInvoice"); + } elseif ($mode == 'fourn' || $mode == 'suppliers') { + $result .= $langs->trans("SupplierInvoice"); + } else { + return ''; + } + $result .= '
    '.$dolgraph->show($total ? 0 : $langs->trans("NoOpenInvoice")).'
    '; + $result .= ''; + + return $result; + } else { + dol_print_error($db); + } + } +} /** * Return a HTML table that contains a list with customer invoice drafts * @@ -465,6 +579,8 @@ function getCustomerInvoiceDraftTable($maxCount = 500, $socid = 0) { global $conf, $db, $langs, $user, $hookmanager; + $maxofloop = (empty($conf->global->MAIN_MAXLIST_OVERLOAD) ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD); + $result = ''; $tmpinvoice = new Facture($db); @@ -488,7 +604,7 @@ function getCustomerInvoiceDraftTable($maxCount = 500, $socid = 0) } if ($socid) { - $sql .= " AND f.fk_soc = $socid"; + $sql .= " AND f.fk_soc = ".((int) $socid); } // Add where from hooks $parameters = array(); @@ -511,6 +627,7 @@ function getCustomerInvoiceDraftTable($maxCount = 500, $socid = 0) if ($resql) { $num = $db->num_rows($resql); + $nbofloop = min($num, $maxofloop); $result .= '
    '; $result .= ''; @@ -530,7 +647,7 @@ function getCustomerInvoiceDraftTable($maxCount = 500, $socid = 0) $i = 0; $othernb = 0; $tot_ttc = 0; - while ($i < $num) { + while ($i < $nbofloop) { $obj = $db->fetch_object($resql); if ($i >= $maxCount) { @@ -577,7 +694,7 @@ function getCustomerInvoiceDraftTable($maxCount = 500, $socid = 0) if ($othernb) { $result .= ''; $result .= ''; $result .= "\n"; } @@ -608,6 +725,8 @@ function getDraftSupplierTable($maxCount = 500, $socid = 0) { global $conf, $db, $langs, $user, $hookmanager; + $maxofloop = (empty($conf->global->MAIN_MAXLIST_OVERLOAD) ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD); + $result = ''; $facturesupplierstatic = new FactureFournisseur($db); @@ -627,7 +746,7 @@ function getDraftSupplierTable($maxCount = 500, $socid = 0) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if ($socid) { - $sql .= " AND f.fk_soc = ".$socid; + $sql .= " AND f.fk_soc = ".((int) $socid); } // Add where from hooks $parameters = array(); @@ -637,6 +756,7 @@ function getDraftSupplierTable($maxCount = 500, $socid = 0) if ($resql) { $num = $db->num_rows($resql); + $nbofloop = min($num, $maxofloop); $result .= '
    '; $result .= '
    '; - $result .= ''.$langs->trans("More").'... ('.$othernb.')'; + $result .= ''.$langs->trans("More").'...'.($othernb < $maxofloop ? ' ('.$othernb.')' : '').''; $result .= '
    '; @@ -656,7 +776,7 @@ function getDraftSupplierTable($maxCount = 500, $socid = 0) $i = 0; $othernb = 0; $tot_ttc = 0; - while ($i < $num) { + while ($i < $nbofloop) { $obj = $db->fetch_object($resql); if ($i >= $maxCount) { @@ -702,7 +822,7 @@ function getDraftSupplierTable($maxCount = 500, $socid = 0) if ($othernb) { $result .= ''; $result .= ''; $result .= "\n"; } @@ -734,8 +854,8 @@ function getCustomerInvoiceLatestEditTable($maxCount = 5, $socid = 0) { global $conf, $db, $langs, $user; - $sql = "SELECT f.rowid, f.entity, f.ref, f.fk_statut as status, f.paye, s.nom as socname, s.rowid as socid, s.canvas, s.client,"; - $sql .= " f.datec"; + $sql = "SELECT f.rowid, f.entity, f.ref, f.fk_statut as status, f.paye, f.type, f.total_ht, f.total_tva, f.total_ttc, f.datec,"; + $sql .= " s.nom as socname, s.rowid as socid, s.canvas, s.client"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) { @@ -784,6 +904,10 @@ function getCustomerInvoiceLatestEditTable($maxCount = 5, $socid = 0) $objectstatic->ref = $obj->ref; $objectstatic->paye = $obj->paye; $objectstatic->statut = $obj->status; + $objectstatic->total_ht = $obj->total_ht; + $objectstatic->total_tva = $obj->total_tva; + $objectstatic->total_ttc = $obj->total_ttc; + $objectstatic->type = $obj->type; $companystatic->id = $obj->socid; $companystatic->name = $obj->socname; @@ -832,8 +956,8 @@ function getPurchaseInvoiceLatestEditTable($maxCount = 5, $socid = 0) { global $conf, $db, $langs, $user; - $sql = "SELECT f.rowid, f.entity, f.ref, f.fk_statut as status, f.paye, s.nom as socname, s.rowid as socid, s.canvas, s.client,"; - $sql .= " f.datec"; + $sql = "SELECT f.rowid, f.entity, f.ref, f.fk_statut as status, f.paye, f.total_ht, f.total_tva, f.total_ttc, f.type, f.ref_supplier, f.datec,"; + $sql .= " s.nom as socname, s.rowid as socid, s.canvas, s.client"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$socid) { @@ -842,7 +966,7 @@ function getPurchaseInvoiceLatestEditTable($maxCount = 5, $socid = 0) $sql .= " WHERE f.fk_soc = s.rowid"; $sql .= " AND f.entity IN (".getEntity('facture_fourn').")"; if ($socid) { - $sql .= " AND f.fk_soc = ".$socid; + $sql .= " AND f.fk_soc = ".((int) $socid); } if (!$user->rights->societe->client->voir && !$socid) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; @@ -882,6 +1006,10 @@ function getPurchaseInvoiceLatestEditTable($maxCount = 5, $socid = 0) $objectstatic->ref = $obj->ref; $objectstatic->paye = $obj->paye; $objectstatic->statut = $obj->status; + $objectstatic->total_ht = $obj->total_ht; + $objectstatic->total_tva = $obj->total_tva; + $objectstatic->total_ttc = $obj->total_ttc; + $objectstatic->type = $obj->type; $companystatic->id = $obj->socid; $companystatic->name = $obj->socname; @@ -954,7 +1082,7 @@ function getCustomerInvoiceUnpaidOpenTable($maxCount = 500, $socid = 0) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if ($socid) { - $sql .= " AND f.fk_soc = ".$socid; + $sql .= " AND f.fk_soc = ".((int) $socid); } // Add where from hooks $parameters = array(); @@ -1142,7 +1270,7 @@ function getPurchaseInvoiceUnpaidOpenTable($maxCount = 500, $socid = 0) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if ($socid) { - $sql .= " AND ff.fk_soc = ".$socid; + $sql .= " AND ff.fk_soc = ".((int) $socid); } // Add where from hooks $parameters = array(); diff --git a/htdocs/core/lib/invoice2.lib.php b/htdocs/core/lib/invoice2.lib.php index c5e2aeb0a16..64365f32547 100644 --- a/htdocs/core/lib/invoice2.lib.php +++ b/htdocs/core/lib/invoice2.lib.php @@ -43,7 +43,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; * @param int $regenerate ''=Use existing PDF files, 'nameofpdf'=Regenerate all PDF files using the template * @param string $filesuffix Suffix to add into file name of generated PDF * @param string $paymentbankid Only if payment on this bank account id - * @param array $thirdpartiesid List of thirdparties id when using filter excludethirdpartiesid or onlythirdpartiesid + * @param array $thirdpartiesid List of thirdparties id when using filter=excludethirdpartiesid or filter=onlythirdpartiesid * @param string $fileprefix Prefix to add into filename of generated PDF * @return int Error code */ diff --git a/htdocs/core/lib/member.lib.php b/htdocs/core/lib/member.lib.php index 484f34c265c..fc274e0d624 100644 --- a/htdocs/core/lib/member.lib.php +++ b/htdocs/core/lib/member.lib.php @@ -63,6 +63,33 @@ function member_prepare_head(Adherent $object) $h++; } + $tabtoadd = (!empty(getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR')) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') ? 'member' : 'thirdparty'; + + if ($tabtoadd == 'member') { + if (!empty($user->rights->partnership->read)) { + $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; + $head[$h][0] = DOL_URL_ROOT.'/adherents/partnership.php?rowid='.$object->id; + $head[$h][1] = $langs->trans("Partnership"); + $head[$h][2] = 'partnership'; + if ($nbPartnership > 0) { + $head[$h][1] .= ''.$nbPartnership.''; + } + $h++; + } + } else { + if (!empty($user->rights->partnership->read)) { + $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; + $head[$h][0] = DOL_URL_ROOT.'/societe/partnership.php?socid='.$object->id; + $head[$h][1] = $langs->trans("Partnership"); + $head[$h][2] = 'partnership'; + if ($nbPartnership > 0) { + $head[$h][1] .= ''.$nbPartnership.''; + } + $h++; + } + } + + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab @@ -70,9 +97,6 @@ function member_prepare_head(Adherent $object) complete_head_from_modules($conf, $langs, $object, $head, $h, 'member'); $nbNote = 0; - if (!empty($object->note)) { - $nbNote++; - } if (!empty($object->note_private)) { $nbNote++; } diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index 2bd8707f86b..7e02450160a 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -171,3 +171,135 @@ function order_admin_prepare_head() return $head; } + + + +/** + * Return a HTML table that contains a pie chart of customer orders + * + * @param int $socid (Optional) Show only results from the customer with this id + * @return string A HTML table that contains a pie chart of customer invoices + */ +function getCustomerOrderPieChart($socid = 0) +{ + global $conf, $db, $langs, $user; + + $result = ''; + + if (empty($conf->commande->enabled) || empty($user->rights->commande->lire)) { + return ''; + } + + $commandestatic = new Commande($db); + + /* + * Statistics + */ + + $sql = "SELECT count(c.rowid) as nb, c.fk_statut as status"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; + $sql .= ", ".MAIN_DB_PREFIX."commande as c"; + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= " WHERE c.fk_soc = s.rowid"; + $sql .= " AND c.entity IN (".getEntity('societe').")"; + if ($user->socid) { + $sql .= ' AND c.fk_soc = '.$user->socid; + } + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; + } + $sql .= " GROUP BY c.fk_statut"; + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + + $total = 0; + $totalinprocess = 0; + $dataseries = array(); + $colorseries = array(); + $vals = array(); + // -1=Canceled, 0=Draft, 1=Validated, 2=Accepted/On process, 3=Closed (Sent/Received, billed or not) + while ($i < $num) { + $row = $db->fetch_row($resql); + if ($row) { + //if ($row[1]!=-1 && ($row[1]!=3 || $row[2]!=1)) + { + if (!isset($vals[$row[1]])) { + $vals[$row[1]] = 0; + } + $vals[$row[1]] += $row[0]; + $totalinprocess += $row[0]; + } + $total += $row[0]; + } + $i++; + } + $db->free($resql); + + include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; + + $result = '
    '; + $result .= '
    '; - $result .= ''.$langs->trans("More").'... ('.$othernb.')'; + $result .= ''.$langs->trans("More").'...'.($othernb < $maxofloop ? ' ('.$othernb.')' : '').''; $result .= '
    '; + $result .= ''."\n"; + $listofstatus = array(0, 1, 2, 3, -1); + foreach ($listofstatus as $status) { + $dataseries[] = array($commandestatic->LibStatut($status, 0, 1, 1), (isset($vals[$status]) ? (int) $vals[$status] : 0)); + if ($status == Commande::STATUS_DRAFT) { + $colorseries[$status] = '-'.$badgeStatus0; + } + if ($status == Commande::STATUS_VALIDATED) { + $colorseries[$status] = $badgeStatus1; + } + if ($status == Commande::STATUS_SHIPMENTONPROCESS) { + $colorseries[$status] = $badgeStatus4; + } + if ($status == Commande::STATUS_CLOSED && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { + $colorseries[$status] = $badgeStatus6; + } + if ($status == Commande::STATUS_CLOSED && (!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) { + $colorseries[$status] = $badgeStatus6; + } + if ($status == Commande::STATUS_CANCELED) { + $colorseries[$status] = $badgeStatus9; + } + + if (empty($conf->use_javascript_ajax)) { + $result .= ''; + $result .= ''; + $result .= ''; + $result .= "\n"; + } + } + if ($conf->use_javascript_ajax) { + $result .= ''; + } + + //if ($totalinprocess != $total) + $result .= ''; + $result .= "
    '.$langs->trans("Statistics").' - '.$langs->trans("CustomersOrders").'
    '.$commandestatic->LibStatut($status, 0, 0, 1).''.(isset($vals[$status]) ? $vals[$status] : 0).' '; + $result .= $commandestatic->LibStatut($status, 0, 3, 1); + $result .= '
    '; + + 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('150'); + $dolgraph->setWidth('300'); + $dolgraph->draw('idgraphstatus'); + $result .= $dolgraph->show($total ? 0 : 1); + + $result .= '
    '.$langs->trans("Total").''.$total.'

    "; + } else { + dol_print_error($db); + } + + return $result; +} diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 494a92d33e3..4621e22d122 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -3,6 +3,7 @@ * Copyright (C) 2013 Marcos García * Copyright (C) 2018 Frédéric France * Copyright (C) 2020 Abbes Bahfir + * Copyright (C) 2021 Waël Almoman * * 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 @@ -155,9 +156,9 @@ function getValidOnlinePaymentMethods($paymentmethod = '') } /** - * Return string with full Url + * Return string with full online payment Url * - * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'membersubscription' ...) + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) * @param string $ref Ref of object * @return string Url string */ @@ -178,11 +179,27 @@ function showOnlinePaymentUrl($type, $ref) return $out; } +/** + * Return string with HTML link for online payment + * + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) + * @param string $ref Ref of object + * @param string $label Text or HTML tag to display, if empty it display the URL + * @return string Url string + */ +function getHtmlOnlinePaymentLink($type, $ref, $label = '') +{ + $url = getOnlinePaymentUrl(0, $type, $ref); + $label = $label ? $label : $url; + return''.$label.''; +} + + /** * Return string with full Url * * @param int $mode 0=True url, 1=Url formated with colors - * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'membersubscription' ...) + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) * @param string $ref Ref of object * @param int $amount Amount (required for $type='free' only) * @param string $freetag Free tag @@ -287,7 +304,7 @@ function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag } } elseif ($type == 'member' || $type == 'membersubscription') { $newtype = 'member'; - $out = $urltouse.'/public/payment/newpayment.php?source=membersubscription&ref='.($mode ? '' : ''); + $out = $urltouse.'/public/payment/newpayment.php?source=member&ref='.($mode ? '' : ''); if ($mode == 1) { $out .= 'member_ref'; } diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 529355b94b2..4821bfde2b9 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -12,6 +12,7 @@ * Copyright (C) 2015-2016 Marcos García * Copyright (C) 2019 Lenin Rivas * Copyright (C) 2020 Nicolas ZABOURI + * Copyright (C) 2021 Anthony Berton * * 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 @@ -35,6 +36,42 @@ */ +/** + * Return array head with list of tabs to view object informations. + * + * @return array head array with tabs + */ +function pdf_admin_prepare_head() +{ + global $langs, $conf, $user; + + $h = 0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT.'/admin/pdf.php'; + $head[$h][1] = $langs->trans("Common"); + $head[$h][2] = 'general'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin'); + + if (!empty($conf->propal->enabled)) { + $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php'; + $head[$h][1] = $langs->trans("Other"); + $head[$h][2] = 'other'; + $h++; + } + + complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin', 'remove'); + + return $head; +} + + /** * Return array with format properties of default PDF format * @@ -668,8 +705,8 @@ function pdf_pagehead(&$pdf, $outputlangs, $page_height) { global $conf; - // Add a background image on document - if (!empty($conf->global->MAIN_USE_BACKGROUND_ON_PDF)) { // Warning, this option make TCPDF generation being crazy and some content disappeared behind the image + // Add a background image on document only if good setup of const + if (!empty($conf->global->MAIN_USE_BACKGROUND_ON_PDF) && ($conf->global->MAIN_USE_BACKGROUND_ON_PDF != '-1')) { // Warning, this option make TCPDF generation being crazy and some content disappeared behind the image $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image $pdf->Image($conf->mycompany->dir_output.'/logos/'.$conf->global->MAIN_USE_BACKGROUND_ON_PDF, (isset($conf->global->MAIN_USE_BACKGROUND_ON_PDF_X) ? $conf->global->MAIN_USE_BACKGROUND_ON_PDF_X : 0), (isset($conf->global->MAIN_USE_BACKGROUND_ON_PDF_Y) ? $conf->global->MAIN_USE_BACKGROUND_ON_PDF_Y : 0), 0, $page_height); $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak @@ -1196,7 +1233,7 @@ function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, /** * Output line description into PDF * - * @param TCPDF $pdf PDF object + * @param TCPDF $pdf PDF object * @param Object $object Object * @param int $i Current line number * @param Translate $outputlangs Object lang for output @@ -1288,38 +1325,36 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $translatealsoifmodified = (!empty($conf->global->MAIN_MULTILANG_TRANSLATE_EVEN_IF_MODIFIED)); // By default if value was modified manually, we keep it (no translation because we don't have it) // TODO Instead of making a compare to see if param was modified, check that content contains reference translation. If yes, add the added part to the new translation - // ($textwasmodified is replaced with $textwasmodifiedorcompleted and we add completion). + // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion). // Set label - // If we want another language, and if label is same than default language (we did force it to a specific value), we can use translation. + // If we want another language, and if label is same than default language (we did not force it to a specific value), we can use translation. //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit; - $textwasmodified = ($label == $prodser->label); - if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasmodified || $translatealsoifmodified)) { + $textwasnotmodified = ($label == $prodser->label); + if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) { $label = $prodser->multilangs[$outputlangs->defaultlang]["label"]; } // Set desc // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no - $textwasmodified = false; + $textwasnotmodified = false; if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) { - $textwasmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false); + $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false); } else { - $textwasmodified = ($desc == $prodser->description); + $textwasnotmodified = ($desc == $prodser->description); } - if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && ($textwasmodified || $translatealsoifmodified)) { + if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && ($textwasnotmodified || $translatealsoifmodified)) { $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"]; } // Set note - $textwasmodified = ($note == $prodser->note); - if (!empty($prodser->multilangs[$outputlangs->defaultlang]["note"]) && ($textwasmodified || $translatealsoifmodified)) { - $note = $prodser->multilangs[$outputlangs->defaultlang]["note"]; + $textwasnotmodified = ($note == $prodser->note_public); + if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) { + $note = $prodser->multilangs[$outputlangs->defaultlang]["other"]; } } } elseif ($object->element == 'facture' || $object->element == 'facturefourn') { - if ($object->type == $object::TYPE_DEPOSIT) { - $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc); - } + $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc); } // Description short of product line diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 9825b2dac2c..f3ebef1e49f 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -360,9 +360,10 @@ function product_lot_admin_prepare_head() */ function show_stats_for_company($product, $socid) { - global $conf, $langs, $user, $db; - $form = new Form($db); + global $conf, $langs, $user, $db, $hookmanager; + $form = new Form($db); + $nblines = 0; print '
    '; + + $result .= ''; + $result .= ''; + $result .= ''; + + foreach ($listofstatus as $status) { + $dataseries[] = array($propalstatic->LibStatut($status, 1), (isset($vals[$status]) ? (int) $vals[$status] : 0)); + if ($status == Propal::STATUS_DRAFT) { + $colorseries[$status] = '-'.$badgeStatus0; + } + if ($status == Propal::STATUS_VALIDATED) { + $colorseries[$status] = $badgeStatus1; + } + if ($status == Propal::STATUS_SIGNED) { + $colorseries[$status] = $badgeStatus4; + } + if ($status == Propal::STATUS_NOTSIGNED) { + $colorseries[$status] = $badgeStatus9; + } + if ($status == Propal::STATUS_BILLED) { + $colorseries[$status] = $badgeStatus6; + } + + if (empty($conf->use_javascript_ajax)) { + $result .= ''; + $result .= ''; + $result .= ''; + $result .= "\n"; + } + } + + if ($conf->use_javascript_ajax) { + $result .= ''; + $result .= ''; + $result .= ''; + } + + //if ($totalinprocess != $total) + //{ + // print ''; + // print ''; + // print ''; + // print ''; + //} + + $result .= ''; + $result .= ''; + $result .= ''; + $result .= ''; + + $result .= '
    '.$langs->trans("Statistics").' - '.$langs->trans("Proposals").'
    '.$propalstatic->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('150'); + $dolgraph->setWidth('300'); + $dolgraph->draw('idgraphthirdparties'); + $result .= $dolgraph->show($total ? 0 : 1); + + $result .= '
    '.$langs->trans("Total").' ('.$langs->trans("CustomersOrdersRunning").')'.$totalinprocess.'
    '.$langs->trans("Total").''.$total.'
    '; + $result .= '
    '; + $result .= '
    '; + } else { + dol_print_error($db); + } + + return $result; +} diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index e1df5da4dfb..598802ea574 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -173,17 +173,21 @@ function dol_verifyHash($chain, $hash, $type = '0') * This method check permission on module then call checkUserAccessToObject() for permission on object (according to entity and socid of user). * * @param User $user User to check - * @param string $features Features to check (it must be module $object->element. Examples: 'societe', 'contact', 'produit&service', 'produit|service', ...) + * @param string $features Features to check (it must be module $object->element. Can be a 'or' check with 'levela|levelb'. + * Examples: 'societe', 'contact', 'produit&service', 'produit|service', ...) + * This is used to check permission $user->rights->features->... * @param int $objectid Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional). * @param string $tableandshare 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity for multicompany module. Param not used if objectid is null (optional). * @param string $feature2 Feature to check, second level of permission (optional). Can be a 'or' check with 'sublevela|sublevelb'. + * This is used to check permission $user->rights->features->feature2... * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) * @param int $isdraft 1=The object with id=$objectid is a draft - * @return int Always 1, die process if not allowed + * @param int $mode Mode (0=default, 1=return with not die) + * @return int If mode = 0 (default): Always 1, die process if not allowed. If mode = 1: Return 0 if access not allowed. * @see dol_check_secure_access_document(), checkUserAccessToObject() */ -function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = 'fk_soc', $dbt_select = 'rowid', $isdraft = 0) +function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = 'fk_soc', $dbt_select = 'rowid', $isdraft = 0, $mode = 0) { global $db, $conf; global $hookmanager; @@ -228,7 +232,11 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f if (isset($hookmanager->resArray['result'])) { if ($hookmanager->resArray['result'] == 0) { - accessforbidden(); // Module returns 0, so access forbidden + if ($mode) { + return 0; + } else { + accessforbidden(); // Module returns 0, so access forbidden + } } } if ($reshook > 0) { // No other test done. @@ -343,14 +351,18 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f } if (!$readok) { - accessforbidden(); + if ($mode) { + return 0; + } else { + accessforbidden(); + } } //print "Read access is ok"; // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files) $createok = 1; $nbko = 0; - $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update'); + $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update') || GETPOST('roworder', 'alpha', 2); $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'); if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) { @@ -432,7 +444,11 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f } if ($wemustcheckpermissionforcreate && !$createok) { - accessforbidden(); + if ($mode) { + return 0; + } else { + accessforbidden(); + } } //print "Write access is ok"; } @@ -445,7 +461,11 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f } if (!$createuserok) { - accessforbidden(); + if ($mode) { + return 0; + } else { + accessforbidden(); + } } //print "Create user access is ok"; } @@ -467,6 +487,10 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f if (!$user->rights->fournisseur->commande->supprimer) { $deleteok = 0; } + } elseif ($feature == 'payment_supplier') { + if (!$user->rights->fournisseur->facture->creer) { + $deleteok = 0; + } } elseif ($feature == 'banque') { if (!$user->rights->banque->modifier) { $deleteok = 0; @@ -516,25 +540,34 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f } if (!$deleteok && !($isdraft && $createok)) { - accessforbidden(); + if ($mode) { + return 0; + } else { + accessforbidden(); + } } //print "Delete access is ok"; } - // If we have a particular object to check permissions on, we check this object - // is linked to a company allowed to $user. + // If we have a particular object to check permissions on, we check if $user has permission + // for this given object (link to company, is contact for project, ...) if (!empty($objectid) && $objectid > 0) { $ok = checkUserAccessToObject($user, $featuresarray, $objectid, $tableandshare, $feature2, $dbt_keyfield, $dbt_select, $parentfortableentity); $params = array('objectid' => $objectid, 'features' => join(',', $featuresarray), 'features2' => $feature2); - return $ok ? 1 : accessforbidden('', 1, 1, 0, $params); + //print 'checkUserAccessToObject ok='.$ok; + if ($mode) { + return $ok ? 1 : 0; + } else { + return $ok ? 1 : accessforbidden('', 1, 1, 0, $params); + } } return 1; } /** - * Check access by user to object. - * This function is also called by restrictedArea that check before if module is enabled and permissions of user compared to $action. + * Check access by user to object is ok. + * This function is also called by restrictedArea that check before if module is enabled and if permission of user for $action is ok. * * @param User $user User to check * @param array $featuresarray Features/modules to check. Example: ('user','service','member','project','task',...) @@ -547,7 +580,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f * @return bool True if user has access, False otherwise * @see restrictedArea() */ -function checkUserAccessToObject($user, $featuresarray, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = '', $dbt_select = 'rowid', $parenttableforentity = '') +function checkUserAccessToObject($user, array $featuresarray, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = '', $dbt_select = 'rowid', $parenttableforentity = '') { global $db, $conf; @@ -681,6 +714,7 @@ function checkUserAccessToObject($user, $featuresarray, $objectid = 0, $tableand include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $projectstatic = new Project($db); $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0); + $tmparray = explode(',', $tmps); if (!in_array($objectid, $tmparray)) { return false; diff --git a/htdocs/core/lib/sendings.lib.php b/htdocs/core/lib/sendings.lib.php index 15e7286ab08..0814c0f4825 100644 --- a/htdocs/core/lib/sendings.lib.php +++ b/htdocs/core/lib/sendings.lib.php @@ -246,7 +246,7 @@ function show_list_sending_receive($origin, $origin_id, $filter = '') $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid"; //TODO Add link to expeditiondet_batch $sql .= " WHERE e.entity IN (".getEntity('expedition').")"; - $sql .= " AND obj.fk_".$origin." = ".$origin_id; + $sql .= " AND obj.fk_".$origin." = ".((int) $origin_id); $sql .= " AND obj.rowid = ed.fk_origin_line"; $sql .= " AND ed.fk_expedition = e.rowid"; if ($filter) { @@ -316,8 +316,8 @@ function show_list_sending_receive($origin, $origin_id, $filter = '') $outputlangs = $langs; $newlang = ''; - if (empty($newlang) && !empty($_REQUEST['lang_id'])) { - $newlang = $_REQUEST['lang_id']; + if (empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); } if (empty($newlang)) { $newlang = $object->thirdparty->default_lang; diff --git a/htdocs/core/lib/supplier_proposal.lib.php b/htdocs/core/lib/supplier_proposal.lib.php index a7720bd9ef4..e5c0ed7dbf9 100644 --- a/htdocs/core/lib/supplier_proposal.lib.php +++ b/htdocs/core/lib/supplier_proposal.lib.php @@ -40,7 +40,7 @@ function supplier_proposal_prepare_head($object) $head = array(); $head[$h][0] = DOL_URL_ROOT.'/supplier_proposal/card.php?id='.$object->id; - $head[$h][1] = $langs->trans('SupplierProposalCard'); + $head[$h][1] = $langs->trans('CommRequests'); $head[$h][2] = 'comm'; $h++; diff --git a/htdocs/core/lib/takepos.lib.php b/htdocs/core/lib/takepos.lib.php index db1623387c1..d983f0298ce 100644 --- a/htdocs/core/lib/takepos.lib.php +++ b/htdocs/core/lib/takepos.lib.php @@ -44,7 +44,7 @@ function takepos_admin_prepare_head() $h++; $head[$h][0] = DOL_URL_ROOT.'/takepos/admin/receipt.php'; - $head[$h][1] = $langs->trans("Receipt"); + $head[$h][1] = $langs->trans("Printers").' / '.$langs->trans("Receipt"); $head[$h][2] = 'receipt'; $h++; @@ -62,7 +62,7 @@ function takepos_admin_prepare_head() } $head[$h][0] = DOL_URL_ROOT.'/takepos/admin/other.php'; - $head[$h][1] = $langs->trans("Other"); + $head[$h][1] = $langs->trans("About"); $head[$h][2] = 'other'; $h++; diff --git a/htdocs/core/lib/ticket.lib.php b/htdocs/core/lib/ticket.lib.php index e2e06487de8..0ba7f56c615 100644 --- a/htdocs/core/lib/ticket.lib.php +++ b/htdocs/core/lib/ticket.lib.php @@ -84,7 +84,7 @@ function ticket_prepare_head($object) $head[$h][2] = 'tabTicket'; $h++; - if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && empty($user->socid)) { + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && empty($user->socid) && $conf->societe->enabled) { $nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external')); $head[$h][0] = DOL_URL_ROOT.'/ticket/contact.php?track_id='.$object->track_id; $head[$h][1] = $langs->trans('ContactsAddresses'); @@ -157,7 +157,8 @@ function showDirectPublicLink($object) $out = ''; if (empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) { - $out .= ''.$langs->trans("PublicInterfaceNotEnabled").''; + $langs->load('errors'); + $out .= ''.$langs->trans("ErrorPublicInterfaceNotEnabled").''; } else { $out .= img_picto('', 'object_globe.png').' '.$langs->trans("TicketPublicAccess").'
    '; if ($url) { @@ -335,7 +336,7 @@ function show_ticket_messaging($conf, $langs, $db, $filterobj, $objcon = '', $no if (is_object($objcon) && $objcon->id > 0) { $force_filter_contact = true; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as r ON a.id = r.fk_actioncomm"; - $sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".$objcon->id; + $sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".((int) $objcon->id); } if (is_object($filterobj) && get_class($filterobj) == 'Societe') { diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 93469e9e3c7..cd9ae5ad297 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -110,7 +110,7 @@ function user_prepare_head($object) $nbNote = 0; $sql = "SELECT COUNT(n.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."notify_def as n"; - $sql .= " WHERE fk_user = ".$object->id; + $sql .= " WHERE fk_user = ".((int) $object->id); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); @@ -339,11 +339,11 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) $thumbsbyrow = 6; print '
    '; - print ''; + print '
    '; // Title if ($foruserprofile) { - print ''; + print ''; print ''; print ''; @@ -359,7 +359,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) $dirthemestring .= '"'.$dirtheme.'" '; } - print ''; print ''; } - print ''."\n"; + print ''."\n"; print ""; } } else { - $colspan = 13; + $colspan = 14; if (!empty($conf->multicompany->enabled)) { $colspan++; } diff --git a/htdocs/core/tpl/bloc_comment.tpl.php b/htdocs/core/tpl/bloc_comment.tpl.php index bf148c2124f..f30bb0c5c61 100644 --- a/htdocs/core/tpl/bloc_comment.tpl.php +++ b/htdocs/core/tpl/bloc_comment.tpl.php @@ -80,9 +80,9 @@ if (!empty($object->comments)) { print '
    '; print '
    '; if (!empty($user->photo)) { - print Form::showphoto('userphoto', $userstatic, 80, 0, 0, '', 'small', 0, 1).'
    '; + print Form::showphoto('userphoto', $userstatic, 80, 0, 0, '', 'small', 0, 1).'
    '; } - print $langs->trans('User').' : '.$userstatic->getNomUrl().'
    '; + print $langs->trans('User').' : '.$userstatic->getNomUrl().'
    '; print $langs->trans('Date').' : '.dol_print_date($comment->datec, 'dayhoursec'); print '
    '; // End comment-info diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index de10465a736..c741fb213c2 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -58,8 +58,8 @@ if ($action == 'presend') { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id'])) { - $newlang = $_REQUEST['lang_id']; + 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; @@ -76,7 +76,7 @@ if ($action == 'presend') { if (empty($object->ref_client)) { $topicmail = $outputlangs->trans($defaulttopic, '__REF__'); } elseif (!empty($object->ref_client)) { - $topicmail = $outputlangs->trans($defaulttopic, '__REF__ (__REFCLIENT__)'); + $topicmail = $outputlangs->trans($defaulttopic, '__REF__ (__REF_CLIENT__)'); } // Build document if it not exists @@ -151,6 +151,10 @@ if ($action == 'presend') { $fuser = new User($db); $fuser->fetch($object->fk_user_author); $liste['thirdparty'] = $fuser->getFullName($outputlangs)." <".$fuser->email.">"; + } elseif ($object->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + $fadherent = new Adherent($db); + $fadherent->fetch($object->fk_member); + $liste['member'] = $fadherent->getFullName($outputlangs)." <".$fadherent->email.">"; } elseif ($object->element == 'societe') { foreach ($object->thirdparty_and_contact_email_array(1) as $key => $value) { $liste[$key] = $value; @@ -190,7 +194,7 @@ if ($action == 'presend') { $formmail->withto = $liste; $formmail->withtofree = (GETPOSTISSET('sendto') ? (GETPOST('sendto', 'alphawithlgt') ? GETPOST('sendto', 'alphawithlgt') : '1') : '1'); $formmail->withtocc = $liste; - $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; + $formmail->withtoccc = getDolGlobalString('MAIN_EMAIL_USECCC'); $formmail->withtopic = $topicmail; $formmail->withfile = 2; $formmail->withbody = 1; @@ -204,7 +208,7 @@ if ($action == 'presend') { // Make substitution in email content $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object); - $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; + $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; $substitutionarray['__PERSONALIZED__'] = ''; // deprecated $substitutionarray['__CONTACTCIVNAME__'] = ''; $parameters = array( diff --git a/htdocs/core/tpl/commonfields_add.tpl.php b/htdocs/core/tpl/commonfields_add.tpl.php index 639be537dba..3a43f04c149 100644 --- a/htdocs/core/tpl/commonfields_add.tpl.php +++ b/htdocs/core/tpl/commonfields_add.tpl.php @@ -82,7 +82,7 @@ foreach ($object->fields as $key => $val) { } else { $value = GETPOST($key, 'alphanohtml'); } - if ($val['noteditable']) { + if (!empty($val['noteditable'])) { print $object->showOutputField($val, $key, $value, '', '', '', 0); } else { print $object->showInputField($val, $key, $value, '', '', '', 0); diff --git a/htdocs/core/tpl/commonfields_view.tpl.php b/htdocs/core/tpl/commonfields_view.tpl.php index 4b7821c2dad..f9da77c5894 100644 --- a/htdocs/core/tpl/commonfields_view.tpl.php +++ b/htdocs/core/tpl/commonfields_view.tpl.php @@ -74,7 +74,7 @@ foreach ($object->fields as $key => $val) { if ($val['type'] == 'text') { print ' wordbreak'; } - if ($val['cssview']) { + if (!empty($val['cssview'])) { print ' '.$val['cssview']; } print '">'; diff --git a/htdocs/core/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php index 4a43da6d6cc..45090824248 100644 --- a/htdocs/core/tpl/document_actions_post_headers.tpl.php +++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php @@ -112,7 +112,7 @@ if (!isset($savingdocmask) || !empty($conf->global->MAIN_DISABLE_SUGGEST_REF_AS_ } } -if (!is_object($formfile)) { +if (empty($formfile) || !is_object($formfile)) { $formfile = new FormFile($db); } diff --git a/htdocs/core/tpl/extrafields_add.tpl.php b/htdocs/core/tpl/extrafields_add.tpl.php index f194a177178..2f44bbe9c48 100644 --- a/htdocs/core/tpl/extrafields_add.tpl.php +++ b/htdocs/core/tpl/extrafields_add.tpl.php @@ -47,7 +47,7 @@ if (empty($reshook)) { if (isset($tpl_context)) { $params['tpl_context'] = $tpl_context; } - $params['cols'] = $parameters['colspanvalue']; + $params['cols'] = key_exists('colspanvalue', $parameters) ? $parameters['colspanvalue'] : ''; print $object->showOptionals($extrafields, 'create', $params); } diff --git a/htdocs/core/tpl/extrafields_list_print_fields.tpl.php b/htdocs/core/tpl/extrafields_list_print_fields.tpl.php index 4c56b0223cd..f53f88e3362 100644 --- a/htdocs/core/tpl/extrafields_list_print_fields.tpl.php +++ b/htdocs/core/tpl/extrafields_list_print_fields.tpl.php @@ -11,8 +11,8 @@ if (empty($extrafieldsobjectkey) && is_object($object)) { } // Loop to show all columns of extrafields from $obj, $extrafields and $db -if (!empty($extrafieldsobjectkey)) { // $extrafieldsobject is the $object->table_element like 'societe', 'socpeople', ... - if (is_array($extrafields->attributes[$extrafieldsobjectkey]['label']) && count($extrafields->attributes[$extrafieldsobjectkey]['label'])) { +if (!empty($extrafieldsobjectkey) && !empty($extrafields->attributes[$extrafieldsobjectkey])) { // $extrafieldsobject is the $object->table_element like 'societe', 'socpeople', ... + if (key_exists('label', $extrafields->attributes[$extrafieldsobjectkey]) && is_array($extrafields->attributes[$extrafieldsobjectkey]['label']) && count($extrafields->attributes[$extrafieldsobjectkey]['label'])) { if (empty($extrafieldsobjectprefix)) { $extrafieldsobjectprefix = 'ef.'; } diff --git a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php index 7268da76007..f1b62676887 100644 --- a/htdocs/core/tpl/extrafields_list_search_sql.tpl.php +++ b/htdocs/core/tpl/extrafields_list_search_sql.tpl.php @@ -26,6 +26,10 @@ if (!empty($extrafieldsobjectkey) && !empty($search_array_options) && is_array($ if ($crit != '' && in_array($typ, array('date', 'datetime', 'timestamp'))) { if (is_numeric($crit)) { + if ($typ == 'date') { + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + $crit = dol_get_first_hour($crit); + } $sql .= " AND ".$extrafieldsobjectprefix.$tmpkey." = '".$db->idate($crit)."'"; } elseif (is_array($crit)) { if ($crit['start'] !== '' && $crit['end'] !== '') { diff --git a/htdocs/core/tpl/extrafields_view.tpl.php b/htdocs/core/tpl/extrafields_view.tpl.php index 9c15a71f43c..3b826b2ead5 100644 --- a/htdocs/core/tpl/extrafields_view.tpl.php +++ b/htdocs/core/tpl/extrafields_view.tpl.php @@ -1,6 +1,7 @@ * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,7 +60,7 @@ if ($reshook < 0) { //var_dump($extrafields->attributes[$object->table_element]); -if (empty($reshook) && is_array($extrafields->attributes[$object->table_element]['label'])) { +if (empty($reshook) && isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label'])) { $lastseparatorkeyfound = ''; $extrafields_collapse_num = ''; $extrafields_collapse_num_old = ''; diff --git a/htdocs/core/tpl/filemanager.tpl.php b/htdocs/core/tpl/filemanager.tpl.php index adb38aa9279..d8bbe0c7cc0 100644 --- a/htdocs/core/tpl/filemanager.tpl.php +++ b/htdocs/core/tpl/filemanager.tpl.php @@ -71,27 +71,58 @@ print '
    '; // Toolbar if ($permtoadd) { - $websitekeyandpageid = (!empty($websitekey) ? '&website='.$websitekey : '').(!empty($pageid) ? '&pageid='.$pageid : ''); - print ''; + $websitekeyandpageid = (!empty($websitekey) ? '&website='.urlencode($websitekey) : '').(!empty($pageid) ? '&pageid='.urlencode($pageid) : ''); + print ''; print img_picto('', 'folder-plus', '', false, 0, 0, '', 'size15x marginrightonly'); print ''; } else { - print ''; + print ''; print img_picto('', 'folder-plus', 'disabled', false, 0, 0, '', 'size15x marginrightonly'); print ''; } if ($module == 'ecm') { $tmpurl = ((!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_ECM_DISABLE_JS)) ? '#' : ($_SERVER["PHP_SELF"].'?action=refreshmanual'.($module ? '&module='.$module : '').($section ? '&section='.$section : ''))); - print ''; + print ''; print img_picto('', 'refresh', 'id="refreshbutton"', false, 0, 0, '', 'size15x marginrightonly'); print ''; } if ($permtoadd && GETPOSTISSET('website')) { // If on file manager to manage medias of a web site - print 'ref.'" class="inline-block valignmiddle toolbarbutton paddingtop" title="'.dol_escape_htmltag($langs->trans("GenerateImgWebp")).'">'; + print 'ref.'" class="inline-block valignmiddle toolbarbutton paddingtop" title="'.dol_escape_htmltag($langs->trans("GenerateImgWebp")).'">'; + print img_picto('', 'images', '', false, 0, 0, '', 'size15x flip marginrightonly'); + print ''; +} elseif ($permtoadd && $module == 'ecm') { // If on file manager medias in ecm + print ''; print img_picto('', 'images', '', false, 0, 0, '', 'size15x flip marginrightonly'); print ''; } +print ""; + // Start "Add new file" area $nameforformuserfile = 'formuserfileecm'; @@ -138,33 +169,52 @@ if ($action == 'delete_section') { } // End confirm +// Ask confirmation to build webp images if ($action == 'confirmconvertimgwebp') { - print $form->formconfirm($_SERVER["PHP_SELF"].'?website='.$website->ref, $langs->trans('ConfirmImgWebpCreation'), $langs->trans('ConfirmGenerateImgWebp', $object->ref), 'convertimgwebp', '', "yes", 1); + $langs->load("ecm"); + + $section_dir=GETPOST('section_dir', 'alpha'); + $section=GETPOST('section', 'alpha'); + $form = new Form($db); + $formquestion['section_dir']=array('type'=>'hidden', 'value'=>$section_dir, 'name'=>'section_dir'); + $formquestion['section']=array('type'=>'hidden', 'value'=>$section, 'name'=>'section'); + if ($module == 'medias') { + $formquestion['website']=array('type'=>'hidden', 'value'=>$website->ref, 'name'=>'website'); + } + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans('ConfirmImgWebpCreation'), $langs->trans('ConfirmGenerateImgWebp', $object->ref), 'convertimgwebp', $formquestion, "yes", 1); $action = 'file_manager'; } +// Duplicate images into .webp if ($action == 'convertimgwebp' && $permtoadd) { if ($module == 'medias') { - $imagefolder = $conf->website->dir_output.'/'.$websitekey.'/medias/image/'.$websitekey.'/'; + $imagefolder = $conf->website->dir_output.'/'.$websitekey.'/medias/'.dol_sanitizePathName(GETPOST('section_dir', 'alpha')); } else { - $imagefolder = $conf->ecm->dir_output; + $imagefolder = $conf->ecm->dir_output.'/'.dol_sanitizePathName(GETPOST('section_dir', 'alpha')); } include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; $regeximgext = getListOfPossibleImageExt(); - $filelist = dol_dir_list($imagefolder, "all", 1, $regeximgext); + $filelist = dol_dir_list($imagefolder, "files", 0, $regeximgext); + + $nbconverted = 0; foreach ($filelist as $filename) { $filepath = $filename['fullname']; if (!(substr_compare($filepath, 'webp', -strlen('webp')) === 0)) { if (image_format_supported($filepath) == 1) { - $filepathnoext = preg_replace("/\..*/", "", $filepath); - $result = dol_imageResizeOrCrop($filepath, 0, 0, 0, 0, 0, $filepathnoext.'.webp'); - if (!dol_is_file($result)) { - $error++; - setEventMessages($result, null, 'errors'); + $filepathnoext = preg_replace("/\.[a-z0-9]+$/i", "", $filepath); + + if (! dol_is_file($filepathnoext.'.webp')) { // If file does not exists yet + $result = dol_imageResizeOrCrop($filepath, 0, 0, 0, 0, 0, $filepathnoext.'.webp', 90); + if (!dol_is_file($result)) { + $error++; + setEventMessages($result, null, 'errors'); + } else { + $nbconverted++; + } } } } @@ -186,7 +236,7 @@ if (empty($action) || $action == 'editfile' || $action == 'file_manager' || preg print ''."\n"; print '
    '."\n"; print ''; $showonrightsize = ''; @@ -197,7 +247,7 @@ if (empty($action) || $action == 'editfile' || $action == 'file_manager' || preg if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_ECM_DISABLE_JS)) { // Show the link to "Root" if ($showroot) { - print '"; print ""; print "'; // Output of last run - print ''; foreach ($tab as $key => $val) { print ''; foreach ($tab as $key => $val) { print ''; } diff --git a/htdocs/datapolicy/class/actions_datapolicy.class.php b/htdocs/datapolicy/class/actions_datapolicy.class.php index 8dcfcdadb1c..e54086149fe 100644 --- a/htdocs/datapolicy/class/actions_datapolicy.class.php +++ b/htdocs/datapolicy/class/actions_datapolicy.class.php @@ -117,11 +117,11 @@ class ActionsDatapolicy $object->state_id = ''; $object->skype = ''; $object->country_id = ''; - $object->note_private = $object->note_private.'
    '.$langs->trans('ANONYMISER_AT', dol_print_date(time())); + $object->note_private = $object->note_private.'
    '.$langs->trans('ANONYMISER_AT', dol_print_date(time())); if ($object->update($object->id, $user, 0)) { // On supprime les contacts associé - $sql = "DELETE FROM ".MAIN_DB_PREFIX."socpeople WHERE fk_soc = ".$object->id; + $sql = "DELETE FROM ".MAIN_DB_PREFIX."socpeople WHERE fk_soc = ".((int) $object->id); $this->db->query($sql); setEventMessages($langs->trans('ANONYMISER_SUCCESS'), array()); @@ -196,7 +196,6 @@ class ActionsDatapolicy echo $object->phone_pro.';'; echo $object->phone_perso.';'; echo $object->phone_mobile.';'; - echo $object->jabberid.';'; echo dol_print_date($object->birth).';'; exit; } elseif ($parameters['currentcontext'] == 'contactcard' && $action == 'send_datapolicy') { diff --git a/htdocs/datapolicy/class/datapolicycron.class.php b/htdocs/datapolicy/class/datapolicycron.class.php index 28a713fb733..965d93754f7 100644 --- a/htdocs/datapolicy/class/datapolicycron.class.php +++ b/htdocs/datapolicy/class/datapolicycron.class.php @@ -54,27 +54,26 @@ class DataPolicyCron $errormsg = ''; $nbupdated = $nbdeleted = 0; - // FIXME Removed hardcoded values of id + // FIXME Exclude data from the selection if there is at least 1 invoice. $arrayofparameters = array( 'DATAPOLICIES_TIERS_CLIENT' => array( 'sql' => " SELECT s.rowid FROM ".MAIN_DB_PREFIX."societe as s - WHERE (s.fk_forme_juridique IN (11, 12, 13, 15, 17, 18, 19, 35, 60, 312, 316, 401, 600, 700, 1005) OR s.fk_typent = 8) - AND s.entity = %d + WHERE s.entity = %d AND s.client = 1 AND s.fournisseur = 0 AND s.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND s.rowid NOT IN ( - SELECT DISTINCT a.fk_soc - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_soc IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_soc = s.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Societe", "file" => DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php', 'fields_anonym' => array( - 'name' => $langs->trans('ANONYME'), + 'name' => 'MAKEANONYMOUS', 'name_bis' => '', 'name_alias' => '', 'address' => '', @@ -87,29 +86,28 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), 'DATAPOLICIES_TIERS_PROSPECT' => array( 'sql' => " SELECT s.rowid FROM ".MAIN_DB_PREFIX."societe as s - WHERE (s.fk_forme_juridique IN (11, 12, 13, 15, 17, 18, 19, 35, 60, 312, 316, 401, 600, 700, 1005) OR s.fk_typent = 8) - AND s.entity = %d + WHERE s.entity = %d AND s.client = 2 AND s.fournisseur = 0 AND s.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND s.rowid NOT IN ( - SELECT DISTINCT a.fk_soc - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_soc IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_soc = s.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Societe", "file" => DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php', 'fields_anonym' => array( - 'name' => $langs->trans('ANONYME'), + 'name' => 'MAKEANONYMOUS', 'name_bis' => '', 'name_alias' => '', 'address' => '', @@ -122,29 +120,28 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), 'DATAPOLICIES_TIERS_PROSPECT_CLIENT' => array( 'sql' => " SELECT s.rowid FROM ".MAIN_DB_PREFIX."societe as s - WHERE (s.fk_forme_juridique IN (11, 12, 13, 15, 17, 18, 19, 35, 60, 312, 316, 401, 600, 700, 1005) OR s.fk_typent = 8) - AND s.entity = %d + WHERE s.entity = %d AND s.client = 3 AND s.fournisseur = 0 AND s.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND s.rowid NOT IN ( - SELECT DISTINCT a.fk_soc - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_soc IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_soc = s.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Societe", "file" => DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php', 'fields_anonym' => array( - 'name' => $langs->trans('ANONYME'), + 'name' => 'MAKEANONYMOUS', 'name_bis' => '', 'name_alias' => '', 'address' => '', @@ -157,29 +154,28 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), 'DATAPOLICIES_TIERS_NIPROSPECT_NICLIENT' => array( 'sql' => " SELECT s.rowid FROM ".MAIN_DB_PREFIX."societe as s - WHERE (s.fk_forme_juridique IN (11, 12, 13, 15, 17, 18, 19, 35, 60, 312, 316, 401, 600, 700, 1005) OR s.fk_typent = 8) - AND s.entity = %d + WHERE s.entity = %d AND s.client = 0 AND s.fournisseur = 0 AND s.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND s.rowid NOT IN ( - SELECT DISTINCT a.fk_soc - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_soc IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_soc = s.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Societe", "file" => DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php', 'fields_anonym' => array( - 'name' => $langs->trans('ANONYME'), + 'name' => 'MAKEANONYMOUS', 'name_bis' => '', 'name_alias' => '', 'address' => '', @@ -192,28 +188,27 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), 'DATAPOLICIES_TIERS_FOURNISSEUR' => array( 'sql' => " SELECT s.rowid FROM ".MAIN_DB_PREFIX."societe as s - WHERE (s.fk_forme_juridique IN (11, 12, 13, 15, 17, 18, 19, 35, 60, 312, 316, 401, 600, 700, 1005) OR s.fk_typent = 8) - AND s.entity = %d + WHERE s.entity = %d AND s.fournisseur = 1 AND s.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND s.rowid NOT IN ( - SELECT DISTINCT a.fk_soc - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_soc = s.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Societe", "file" => DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php', 'fields_anonym' => array( - 'name' => $langs->trans('ANONYME'), + 'name' => 'MAKEANONYMOUS', 'name_bis' => '', 'name_alias' => '', 'address' => '', @@ -226,7 +221,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -238,17 +233,17 @@ class DataPolicyCron AND c.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) AND s.client = 1 AND s.fournisseur = 0 - AND c.rowid NOT IN ( - SELECT DISTINCT a.fk_contact - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_contact = c.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Contact", "file" => DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', 'firstname' => '', 'civility_id' => '', 'poste' => '', @@ -264,8 +259,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', - 'jabberid' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -277,17 +271,17 @@ class DataPolicyCron AND c.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) AND s.client = 2 AND s.fournisseur = 0 - AND c.rowid NOT IN ( - SELECT DISTINCT a.fk_contact - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_contact = c.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Contact", "file" => DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', 'firstname' => '', 'civility_id' => '', 'poste' => '', @@ -303,8 +297,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', - 'jabberid' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -316,17 +309,17 @@ class DataPolicyCron AND c.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) AND s.client = 3 AND s.fournisseur = 0 - AND c.rowid NOT IN ( - SELECT DISTINCT a.fk_contact - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_contact = c.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Contact", "file" => DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', 'firstname' => '', 'civility_id' => '', 'poste' => '', @@ -342,8 +335,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', - 'jabberid' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -355,17 +347,17 @@ class DataPolicyCron AND c.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) AND s.client = 0 AND s.fournisseur = 0 - AND c.rowid NOT IN ( - SELECT DISTINCT a.fk_contact - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_contact = c.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Contact", "file" => DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', 'firstname' => '', 'civility_id' => '', 'poste' => '', @@ -381,8 +373,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', - 'jabberid' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -393,17 +384,17 @@ class DataPolicyCron WHERE c.entity = %d AND c.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) AND s.fournisseur = 1 - AND c.rowid NOT IN ( - SELECT DISTINCT a.fk_contact - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.fk_contact IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_contact = c.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) + ) + AND NOT EXISTS ( + SELECT rowid FROM ".MAIN_DB_PREFIX."facture as f WHERE f.fk_soc = s.rowid ) ", "class" => "Contact", "file" => DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', 'firstname' => '', 'civility_id' => '', 'poste' => '', @@ -419,8 +410,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', - 'jabberid' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -429,19 +419,15 @@ class DataPolicyCron SELECT a.rowid FROM ".MAIN_DB_PREFIX."adherent as a WHERE a.entity = %d AND a.tms < DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.rowid NOT IN ( - SELECT DISTINCT a.fk_element - FROM ".MAIN_DB_PREFIX."actioncomm as a - WHERE a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) - AND a.elementtype LIKE 'member' - AND a.fk_element IS NOT NULL + AND NOT EXISTS ( + SELECT id FROM ".MAIN_DB_PREFIX."actioncomm as a WHERE a.fk_element = a.rowid AND a.tms > DATE_SUB(NOW(), INTERVAL %d MONTH) AND a.elementtype LIKE 'member' ) ", "class" => "Adherent", "file" => DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php', 'fields_anonym' => array( - 'lastname' => $langs->trans('ANONYME'), - 'firstname' => $langs->trans('ANONYME'), + 'lastname' => 'MAKEANONYMOUS', + 'firstname' => 'MAKEANONYMOUS', 'civility_id' => '', 'societe' => '', 'address' => '', @@ -456,7 +442,7 @@ class DataPolicyCron 'state' => '', 'country' => '', 'state_id' => '', - 'skype' => '', + 'socialnetworks' => '', 'country_id' => '', ) ), @@ -483,27 +469,27 @@ class DataPolicyCron $object->fetch($obj->rowid); $object->id = $obj->rowid; - if ($object->isObjectUsed($obj->rowid) > 0) { // If object to clean is used - foreach ($params['fields_anonym'] as $fields => $val) { - $object->$fields = $val; - } - $result = $object->update($obj->rowid, $user); - if ($result > 0) { - if ($params['class'] == 'Societe') { - // We delete contacts of thirdparty - $sql = "DELETE FROM ".MAIN_DB_PREFIX."socpeople WHERE fk_soc = ".$obj->rowid; - $result = $this->db->query($sql); - if ($result < 0) { - $errormsg = $this->db->lasterror(); - $error++; + $action = 'anonymize'; // TODO Offer also action "delete" in setup of module + + if ($action == 'anonymize') { + if ($object->isObjectUsed($obj->rowid) == 0) { // If object to clean is used + foreach ($params['fields_anonym'] as $fields => $val) { + if ($val == 'MAKEANONYMOUS') { + $object->$fields = $fields.'-anonymous-'.$obj->rowid; + } else { + $object->$fields = $val; } } - } else { - $errormsg = $object->error; - $error++; + $result = $object->update($obj->rowid, $user); + if ($result > 0) { + $errormsg = $object->error; + $error++; + } + $nbupdated++; } - $nbupdated++; - } else { // If object to clean is not used + } + + if ($action == 'delete') { // If object to clean is not used if ($object->element == 'adherent') { $result = $object->delete($obj->rowid, $user); } else { diff --git a/htdocs/delivery/card.php b/htdocs/delivery/card.php index 69fd5a9bec0..4855c9c1e49 100644 --- a/htdocs/delivery/card.php +++ b/htdocs/delivery/card.php @@ -542,8 +542,8 @@ if ($action == 'create') { // Create. Seems to no be used if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { $outputlangs = $langs; $newlang = ''; - if (empty($newlang) && !empty($_REQUEST['lang_id'])) { - $newlang = $_REQUEST['lang_id']; + if (empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); } if (empty($newlang)) { $newlang = $object->thirdparty->default_lang; @@ -659,7 +659,7 @@ if ($action == 'create') { // Create. Seems to no be used } print "\n"; - print '
    '.$langs->trans("Parameter").''.$langs->trans("DefaultValue").'
    '.$langs->trans("Parameter").''.$langs->trans("DefaultValue").' 
    '; + print '
    '; print $form->textwithpicto($langs->trans("DefaultSkin"), $langs->trans("ThemeDir").' : '.$dirthemestring); print ''; @@ -448,7 +448,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) // Nothing } else { // Show logo - print '
    '.$langs->trans("EnableShowLogo").''; + print '
    '.$langs->trans("EnableShowLogo").''; if ($edit) { print ajax_constantonoff('MAIN_SHOW_LOGO', array(), null, 0, 0, 1); //print $form->selectyesno('MAIN_SHOW_LOGO', $conf->global->MAIN_SHOW_LOGO, 1); diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 4fa0f053236..89fd777cd20 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -502,7 +502,7 @@ function includeContainer($containerref) } $includehtmlcontentopened++; if ($includehtmlcontentopened > $MAXLEVEL) { - print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.$MAXLEVEL.".\n"; + print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.((int) $MAXLEVEL).".\n"; return; } @@ -549,20 +549,20 @@ function getStructuredData($type, $data = array()) "@type": "SoftwareApplication", "name": "'.dol_escape_json($data['name']).'", "operatingSystem": "'.dol_escape_json($data['os']).'", - "applicationCategory": "https://schema.org/'.$data['applicationCategory'].'",'; + "applicationCategory": "https://schema.org/'.dol_escape_json($data['applicationCategory']).'",'; if (!empty($data['ratingcount'])) { $ret .= ' "aggregateRating": { "@type": "AggregateRating", - "ratingValue": "'.$data['ratingvalue'].'", - "ratingCount": "'.$data['ratingcount'].'" + "ratingValue": "'.dol_escape_json($data['ratingvalue']).'", + "ratingCount": "'.dol_escape_json($data['ratingcount']).'" },'; } $ret .= ' "offers": { "@type": "Offer", - "price": "'.$data['price'].'", - "priceCurrency": "'.($data['currency'] ? $data['currency'] : $conf->currency).'" + "price": "'.dol_escape_json($data['price']).'", + "priceCurrency": "'.dol_escape_json($data['currency'] ? $data['currency'] : $conf->currency).'" } }'."\n"; $ret .= ''."\n"; @@ -618,7 +618,7 @@ function getStructuredData($type, $data = array()) $pageurl = str_replace('__WEBSITE_KEY__', $website->ref, $pageurl); $title = str_replace('__WEBSITE_KEY__', $website->ref, $title); - $image = '/medias/'.str_replace('__WEBSITE_KEY__', $website->ref, $image); + $image = '/medias'.(preg_match('/^\//', $image) ? '' : '/').str_replace('__WEBSITE_KEY__', $website->ref, $image); $companyname = str_replace('__WEBSITE_KEY__', $website->ref, $companyname); $description = str_replace('__WEBSITE_KEY__', $website->ref, $description); @@ -666,6 +666,8 @@ function getStructuredData($type, $data = array()) $ret .= '"description": "'.dol_escape_json($description).'"'; $ret .= "\n".'}'."\n"; $ret .= ''."\n"; + } else { + $ret .= ''."\n"; } } elseif ($type == 'product') { $ret = ''."\n"; @@ -691,8 +693,8 @@ function getStructuredData($type, $data = array()) "offers": { "@type": "Offer", "url": "https://example.com/anvil", - "priceCurrency": "'.($data['currency'] ? $data['currency'] : $conf->currency).'", - "price": "'.$data['price'].'", + "priceCurrency": "'.dol_escape_json($data['currency'] ? $data['currency'] : $conf->currency).'", + "price": "'.dol_escape_json($data['price']).'", "itemCondition": "https://schema.org/UsedCondition", "availability": "https://schema.org/InStock", "seller": { diff --git a/htdocs/core/lib/website2.lib.php b/htdocs/core/lib/website2.lib.php index 8824d9cc06d..721b908b9d1 100644 --- a/htdocs/core/lib/website2.lib.php +++ b/htdocs/core/lib/website2.lib.php @@ -283,11 +283,11 @@ function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, /** - * Save content of the index.php and/or wrapper.php page + * Save content of the index.php and/or the wrapper.php page * * @param string $pathofwebsite Path of website root * @param string $fileindex Full path of file index.php - * @param string $filetpl File tpl the index.php page redirect to + * @param string $filetpl File tpl the index.php page redirect to (used only if $fileindex is provided) * @param string $filewrapper Full path of file wrapper.php * @return boolean True if OK */ diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index d9c2cad7c9f..9eb6a43f9b0 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -167,7 +167,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_proposal->enabled', __HANDLER__, 'left', 1653__+MAX_llx_menu__, 'commercial', '', 1650__+MAX_llx_menu__, '/comm/propal/stats/index.php?leftmenu=supplier_proposals&mode=supplier', 'Statistics', 1, 'supplier_proposal', '$user->rights->supplier_proposal->lire', '', 2, 2, __ENTITY__); -- Commercial - Supplier's orders insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled', __HANDLER__, 'left', 5100__+MAX_llx_menu__, 'commercial', 'orders_suppliers', 5__+MAX_llx_menu__, '/fourn/commande/index.php?mainmenu=commercial&leftmenu=orders_suppliers', 'SuppliersOrders', 0, 'orders', '($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire)', '', 2, 6, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled', __HANDLER__, 'left', 5101__+MAX_llx_menu__, 'commercial', '', 5100__+MAX_llx_menu__, '/fourn/commande/card.php?mainmenu=commercial&action=create&leftmenu=orders_suppliers', 'NewOrder', 1, 'orders', '($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer)', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled', __HANDLER__, 'left', 5101__+MAX_llx_menu__, 'commercial', '', 5100__+MAX_llx_menu__, '/fourn/commande/card.php?mainmenu=commercial&action=create&leftmenu=orders_suppliers', 'NewSupplierOrderShort', 1, 'orders', '($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer)', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled', __HANDLER__, 'left', 5102__+MAX_llx_menu__, 'commercial', '', 5100__+MAX_llx_menu__, '/fourn/commande/list.php?mainmenu=commercial&leftmenu=orders_suppliers', 'List', 1, 'orders', '($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire)', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled && $leftmenu=="orders_suppliers"', __HANDLER__, 'left', 5103__+MAX_llx_menu__, 'commercial', '', 5102__+MAX_llx_menu__, '/fourn/commande/list.php?mainmenu=commercial&leftmenu=orders_suppliers&statut=0', 'StatusOrderDraftShort', 1, 'orders', '($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire)', '', 2, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_order->enabled && $leftmenu=="orders_suppliers"', __HANDLER__, 'left', 5104__+MAX_llx_menu__, 'commercial', '', 5102__+MAX_llx_menu__, '/fourn/commande/list.php?mainmenu=commercial&leftmenu=orders_suppliers&statut=1', 'StatusOrderValidated', 1, 'orders', '($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire)', '', 2, 3, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index e35d9d4490c..80ea1d5ea7b 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -227,6 +227,7 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = $tmpentry = array( 'enabled'=>(!empty($conf->propal->enabled) || !empty($conf->commande->enabled) + || !empty($conf->fournisseur->enabled) || !empty($conf->supplier_proposal->enabled) || !empty($conf->supplier_order->enabled) || !empty($conf->contrat->enabled) @@ -235,6 +236,8 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = 'perms'=>(!empty($user->rights->propal->lire) || !empty($user->rights->commande->lire) || !empty($user->rights->supplier_proposal->lire) + || !empty($user->rights->fournisseur->lire) + || !empty($user->rights->fournisseur->commande->lire) || !empty($user->rights->supplier_order->lire) || !empty($user->rights->contrat->lire) || !empty($user->rights->ficheinter->lire) @@ -956,7 +959,7 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM if (!empty($conf->supplier_order->enabled)) { $langs->load("orders"); $newmenu->add("/fourn/commande/index.php?leftmenu=orders_suppliers", $langs->trans("SuppliersOrders"), 0, $user->rights->fournisseur->commande->lire, '', $mainmenu, 'orders_suppliers', 400, '', '', '', img_picto('', 'supplier_order', 'class="paddingright pictofixedwidth"')); - $newmenu->add("/fourn/commande/card.php?action=create&leftmenu=orders_suppliers", $langs->trans("NewOrder"), 1, $user->rights->fournisseur->commande->creer); + $newmenu->add("/fourn/commande/card.php?action=create&leftmenu=orders_suppliers", $langs->trans("NewSupplierOrderShort"), 1, $user->rights->fournisseur->commande->creer); $newmenu->add("/fourn/commande/list.php?leftmenu=orders_suppliers", $langs->trans("List"), 1, $user->rights->fournisseur->commande->lire); if ($usemenuhider || empty($leftmenu) || $leftmenu == "orders_suppliers") { @@ -1370,7 +1373,7 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $modecompta = 'CREANCES-DETTES'; if (!empty($conf->accounting->enabled) && !empty($user->rights->accounting->comptarapport->lire) && $mainmenu == 'accountancy') { - $modecompta = 'BOOKKEEPING'; // Not yet implemented. Should be BOOKKEEPINGCOLLECTED + $modecompta = 'BOOKKEEPING'; // Not yet implemented. } if ($modecompta && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled))) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_report/', $leftmenu)) { @@ -1381,7 +1384,9 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM } $modecompta = 'RECETTES-DEPENSES'; - //if (! empty($conf->accounting->enabled) && ! empty($user->rights->accounting->comptarapport->lire) && $mainmenu == 'accountancy') $modecompta=''; // Not yet implemented. Should be BOOKKEEPINGCOLLECTED + if (!empty($conf->accounting->enabled) && !empty($user->rights->accounting->comptarapport->lire) && $mainmenu == 'accountancy') { + $modecompta = 'BOOKKEEPINGCOLLECTED'; // Not yet implemented. + } if ($modecompta && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled))) { if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_report/', $leftmenu)) { $newmenu->add("/compta/stats/supplier_turnover.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ReportPurchaseTurnoverCollected"), 2, $user->rights->accounting->comptarapport->lire); @@ -1407,7 +1412,6 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $newmenu->add("/compta/resultat/compteres.php?leftmenu=report","Compte de resultat",2,$user->rights->compta->resultat->lire); $newmenu->add("/compta/resultat/bilan.php?leftmenu=report","Bilan",2,$user->rights->compta->resultat->lire); */ - $newmenu->add("/compta/stats/index.php?leftmenu=report", $langs->trans("ReportTurnover"), 1, $user->rights->compta->resultat->lire); /* $newmenu->add("/compta/stats/cumul.php?leftmenu=report","Cumule",2,$user->rights->compta->resultat->lire); @@ -1416,14 +1420,32 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $newmenu->add("/compta/stats/comp.php?leftmenu=report","Transforme",2,$user->rights->compta->resultat->lire); } */ - $newmenu->add("/compta/stats/casoc.php?leftmenu=report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/cabyuser.php?leftmenu=report", $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/cabyprodserv.php?leftmenu=report", $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/byratecountry.php?leftmenu=report", $langs->trans("ByVatRate"), 2, $user->rights->compta->resultat->lire); + + $modecompta = 'CREANCES-DETTES'; + $newmenu->add("/compta/stats/index.php?leftmenu=report&modecompta=".$modecompta, $langs->trans("ReportTurnover"), 1, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/casoc.php?leftmenu=report&modecompta=".$modecompta, $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyuser.php?leftmenu=report&modecompta=".$modecompta, $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyprodserv.php?leftmenu=report&modecompta=".$modecompta, $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/byratecountry.php?leftmenu=report&modecompta=".$modecompta, $langs->trans("ByVatRate"), 2, $user->rights->compta->resultat->lire); + + $modecompta = 'RECETTES-DEPENSES'; + $newmenu->add("/compta/stats/index.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ReportTurnoverCollected"), 1, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/casoc.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyuser.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); + //Achats - $newmenu->add("/compta/stats/supplier_turnover.php?leftmenu=accountancy_report", $langs->trans("ReportPurchaseTurnover"), 1, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/supplier_turnover_by_thirdparty.php?leftmenu=accountancy_report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/supplier_turnover_by_prodserv.php?leftmenu=accountancy_report", $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); + $modecompta = 'CREANCES-DETTES'; + $newmenu->add("/compta/stats/supplier_turnover.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ReportPurchaseTurnover"), 1, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/supplier_turnover_by_thirdparty.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/supplier_turnover_by_prodserv.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); + + /* + $modecompta = 'RECETTES-DEPENSES'; + $newmenu->add("/compta/stats/index.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ReportPurchaseTurnoverCollected"), 1, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/casoc.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyuser.php?leftmenu=accountancy_report&modecompta=".$modecompta, $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); + */ + // Journals $newmenu->add("/compta/journal/sellsjournal.php?leftmenu=report", $langs->trans("SellsJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 50); $newmenu->add("/compta/journal/purchasesjournal.php?leftmenu=report", $langs->trans("PurchasesJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 51); @@ -1595,21 +1617,19 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM } // Inventory - if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - if (!empty($conf->stock->enabled)) { - $langs->load("stocks"); - if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("Inventories"), 0, $user->rights->stock->lire, '', $mainmenu, 'stock', 0, '', '', '', img_picto('', 'inventory', 'class="pictofixedwidth"')); - if ($usemenuhider || empty($leftmenu) || $leftmenu == "stock_inventories") { - $newmenu->add("/product/inventory/card.php?action=create&leftmenu=stock_inventories", $langs->trans("NewInventory"), 1, $user->rights->stock->creer); - $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("List"), 1, $user->rights->stock->lire); - } - } else { - $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("Inventories"), 0, $user->rights->stock->inventory_advance->read, '', $mainmenu, 'stock', 0, '', '', '', img_picto('', 'inventory', 'class="pictofixedwidth"')); - if ($usemenuhider || empty($leftmenu) || $leftmenu == "stock_inventories") { - $newmenu->add("/product/inventory/card.php?action=create&leftmenu=stock_inventories", $langs->trans("NewInventory"), 1, $user->rights->stock->inventory_advance->write); - $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("List"), 1, $user->rights->stock->inventory_advance->read); - } + if (!empty($conf->stock->enabled)) { + $langs->load("stocks"); + if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { + $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("Inventories"), 0, $user->rights->stock->lire, '', $mainmenu, 'stock', 0, '', '', '', img_picto('', 'inventory', 'class="pictofixedwidth"')); + if ($usemenuhider || empty($leftmenu) || $leftmenu == "stock_inventories") { + $newmenu->add("/product/inventory/card.php?action=create&leftmenu=stock_inventories", $langs->trans("NewInventory"), 1, $user->rights->stock->creer); + $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("List"), 1, $user->rights->stock->lire); + } + } else { + $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("Inventories"), 0, $user->rights->stock->inventory_advance->read, '', $mainmenu, 'stock', 0, '', '', '', img_picto('', 'inventory', 'class="pictofixedwidth"')); + if ($usemenuhider || empty($leftmenu) || $leftmenu == "stock_inventories") { + $newmenu->add("/product/inventory/card.php?action=create&leftmenu=stock_inventories", $langs->trans("NewInventory"), 1, $user->rights->stock->inventory_advance->write); + $newmenu->add("/product/inventory/list.php?leftmenu=stock_inventories", $langs->trans("List"), 1, $user->rights->stock->inventory_advance->read); } } } diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index b92937cdada..3b7cc0d1184 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -192,6 +192,18 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it */ public $version; + /** + * Module last version + * @var string $lastVersion + */ + public $lastVersion = ''; + + /** + * true indicate this module need update + * @var bool $needUpdate + */ + public $needUpdate = false; + /** * @var string Module description (short text) * @@ -788,6 +800,23 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it return $ret; } + /** + * Gives the module position + * + * @return int Module position (an external module should never return a value lower than 100000. 1-100000 are reserved for core) + */ + public function getModulePosition() + { + if (in_array($this->version, array('dolibarr', 'experimental', 'development'))) { // core module + return $this->module_position; + } else { // external module + if ($this->module_position >= 100000) { + return $this->module_position; + } else { + return $this->module_position + 100000; + } + } + } /** * Tells if module is core or external @@ -1342,7 +1371,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it if ($command) { $sql .= " AND command = '".$this->db->escape($command)."'"; } - $sql .= " AND entity = ".$entity; // Must be exact entity + $sql .= " AND entity = ".((int) $entity); // Must be exact entity $now = dol_now(); @@ -1583,7 +1612,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $sql = "SELECT count(*)"; $sql .= " FROM ".MAIN_DB_PREFIX."const"; $sql .= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($name)."'"; - $sql .= " AND entity = ".$entity; + $sql .= " AND entity = ".((int) $entity); $result = $this->db->query($sql); if ($result) { @@ -2168,7 +2197,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; $sql .= " WHERE ".$this->db->decrypt('name')." LIKE '".$this->db->escape($this->const_name)."_".strtoupper($key)."'"; - $sql .= " AND entity = ".$entity; + $sql .= " AND entity = ".((int) $entity); dol_syslog(get_class($this)."::delete_const_".$key."", LOG_DEBUG); if (!$this->db->query($sql)) { @@ -2240,7 +2269,11 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it } print ' -
    +
    '; @@ -2258,7 +2291,12 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it } if ($this->isCoreOrExternalModule() == 'external' || preg_match('/development|experimental|deprecated/i', $version)) { - print 'getVersion(1).'">'; + $versionTitle = $langs->trans("Version").' '.$this->getVersion(1); + if ($this->needUpdate) { + $versionTitle.= '
    '.$langs->trans('ModuleUpdateAvailable').' : '.$this->lastVersion; + } + + print ''; print $this->getVersion(1); print ''; } @@ -2287,4 +2325,33 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
    '; } + + /** + * Check for module update + * TODO : store results for $this->url_last_version and $this->needUpdate + * Add a cron task to monitor for updates + * + * @return int <0 if Error, 0 == no update needed, >0 if need update + */ + public function checkForUpdate() + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; + if (!empty($this->url_last_version)) { + $lastVersion = getURLContent($this->url_last_version, 'GET', '', 1, array(), array('http', 'https'), 0); // Accept http or https links on external remote server only + if (isset($lastVersion['content']) && strlen($lastVersion['content']) < 30) { + // Security warning : be careful with remote data content, the module editor could be hacked (or evil) so limit to a-z A-Z 0-9 _ . - + $this->lastVersion = preg_replace("/[^a-zA-Z0-9_\.\-]+/", "", $lastVersion['content']); + if (version_compare($this->lastVersion, $this->version) > 0) { + $this->needUpdate = true; + return 1; + } else { + $this->needUpdate = false; + return 0; + } + } else { + return -1; + } + } + return 0; + } } diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index b759711ac49..bd6caafd15a 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -1255,6 +1255,9 @@ class pdf_einstein extends ModelePDFCommandes // phpcs:enable global $conf, $langs, $hookmanager; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies")); @@ -1300,7 +1303,7 @@ class pdf_einstein extends ModelePDFCommandes } } else { $text = $this->emetteur->name; - $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } } @@ -1408,7 +1411,7 @@ class pdf_einstein extends ModelePDFCommandes $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1417,7 +1420,7 @@ class pdf_einstein extends ModelePDFCommandes // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information @@ -1462,20 +1465,20 @@ class pdf_einstein extends ModelePDFCommandes $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index 2c7171fed8a..1dc8ce74db0 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1422,6 +1422,9 @@ class pdf_eratosthene extends ModelePDFCommandes // phpcs:enable global $conf, $langs, $hookmanager; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies")); @@ -1594,7 +1597,7 @@ class pdf_eratosthene extends ModelePDFCommandes $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -1603,13 +1606,13 @@ class pdf_eratosthene extends ModelePDFCommandes // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); // If CUSTOMER contact defined, we use it $usecontact = false; @@ -1647,20 +1650,20 @@ class pdf_eratosthene extends ModelePDFCommandes $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/delivery/doc/pdf_storm.modules.php b/htdocs/core/modules/delivery/doc/pdf_storm.modules.php index 057310a9976..a1c01002d2e 100644 --- a/htdocs/core/modules/delivery/doc/pdf_storm.modules.php +++ b/htdocs/core/modules/delivery/doc/pdf_storm.modules.php @@ -823,7 +823,7 @@ class pdf_storm extends ModelePDFDeliveryOrder $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -849,7 +849,7 @@ class pdf_storm extends ModelePDFDeliveryOrder $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress"), 0, 'L'); // If SHIPPING contact defined on order, we use it $usecontact = false; diff --git a/htdocs/core/modules/delivery/doc/pdf_typhon.modules.php b/htdocs/core/modules/delivery/doc/pdf_typhon.modules.php index 66f232653ac..4656784f50d 100644 --- a/htdocs/core/modules/delivery/doc/pdf_typhon.modules.php +++ b/htdocs/core/modules/delivery/doc/pdf_typhon.modules.php @@ -822,7 +822,7 @@ class pdf_typhon extends ModelePDFDeliveryOrder $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -848,7 +848,7 @@ class pdf_typhon extends ModelePDFDeliveryOrder $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress"), 0, 'L'); // If SHIPPING contact defined on order, we use it $usecontact = false; diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index 42a777a196f..42999248026 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -318,13 +318,13 @@ class pdf_espadon extends ModelePdfExpedition $pdf->useTemplate($tplidx); } $pagenb++; - $this->_pagehead($pdf, $object, 1, $outputlangs); + $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs); $pdf->SetFont('', '', $default_font_size - 1); $pdf->MultiCell(0, 3, ''); // Set interline to 3 $pdf->SetTextColor(0, 0, 0); $tab_top = 90; - $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10); + $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 + $top_shift: 10); $tab_height = 130; $tab_height_newpage = 150; @@ -361,17 +361,14 @@ class pdf_espadon extends ModelePdfExpedition } if (!empty($notetoshow) || !empty($object->tracking_number)) { - $tab_top = 88 + $height_incoterms; - $tab_top_alt = $tab_top; - - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->writeHTMLCell(60, 4, $this->posxdesc - 1, $tab_top - 1, $outputlangs->transnoentities("TrackingNumber")." : ".$object->tracking_number, 0, 1, false, true, 'L'); - - $tab_top_alt = $pdf->GetY(); - //$tab_top_alt += 1; + $tab_top -= 2; // Tracking number if (!empty($object->tracking_number)) { + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->writeHTMLCell(60, 4, $this->posxdesc - 1, $tab_top - 1, $outputlangs->transnoentities("TrackingNumber") . " : " . $object->tracking_number, 0, 1, false, true, 'L'); + + $tab_top_alt = $pdf->GetY(); $object->getUrlTrackingStatus($object->tracking_number); if (!empty($object->tracking_url)) { if ($object->shipping_method_id > 0) { @@ -390,28 +387,124 @@ class pdf_espadon extends ModelePdfExpedition $pdf->SetFont('', 'B', $default_font_size - 2); $pdf->writeHTMLCell(60, 4, $this->posxdesc - 1, $tab_top_alt, $label, 0, 1, false, true, 'L'); - $tab_top_alt = $pdf->GetY(); + $tab_top = $pdf->GetY(); } } } + // Notes + $pagenb = $pdf->getPage(); if (!empty($notetoshow)) { - $pdf->SetFont('', '', $default_font_size - 1); // In loop to manage multi-page - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top_alt, dol_htmlentitiesbr($notetoshow), 0, 1); + $tab_top -= 2; + + $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite; + $pageposbeforenote = $pagenb; + + $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); + $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); + + $pdf->startTransaction(); + + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); + // Description + $pageposafternote = $pdf->getPage(); + $posyafter = $pdf->GetY(); + + if ($pageposafternote > $pageposbeforenote) { + $pdf->rollbackTransaction(true); + + // prepare pages to receive notes + while ($pagenb < $pageposafternote) { + $pdf->AddPage(); + $pagenb++; + if (!empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + // $this->_pagefoot($pdf,$object,$outputlangs,1); + $pdf->setTopMargin($tab_top_newpage); + // The only function to edit the bottom margin of current page to set it. + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext); + } + + // back to start + $pdf->setPage($pageposbeforenote); + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext); + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); + $pageposafternote = $pdf->getPage(); + + $posyafter = $pdf->GetY(); + + if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text + $pdf->AddPage('', '', true); + $pagenb++; + $pageposafternote++; + $pdf->setPage($pageposafternote); + $pdf->setTopMargin($tab_top_newpage); + // The only function to edit the bottom margin of current page to set it. + $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext); + //$posyafter = $tab_top_newpage; + } + + + // apply note frame to previous pages + $i = $pageposbeforenote; + while ($i < $pageposafternote) { + $pdf->setPage($i); + + + $pdf->SetDrawColor(128, 128, 128); + // Draw note frame + if ($i > $pageposbeforenote) { + $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter); + $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1); + } else { + $height_note = $this->page_hauteur - ($tab_top + $heightforfooter); + $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1); + } + + // Add footer + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + $this->_pagefoot($pdf, $object, $outputlangs, 1); + + $i++; + } + + // apply note frame to last page + $pdf->setPage($pageposafternote); + if (!empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + $height_note = $posyafter - $tab_top_newpage; + $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1); + } else // No pagebreak + { + $pdf->commitTransaction(); + $posyafter = $pdf->GetY(); + $height_note = $posyafter - $tab_top; + $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1); + + + if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { + // not enough space, need to add page + $pdf->AddPage('', '', true); + $pagenb++; + $pageposafternote++; + $pdf->setPage($pageposafternote); + if (!empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + + $posyafter = $tab_top_newpage; + } + } + + $tab_height = $tab_height - $height_note; + $tab_top = $posyafter + 6; + } else { + $height_note = 0; } - - $nexY = $pdf->GetY(); - $height_note = $nexY - $tab_top; - - // Rect takes a length in 3rd parameter - $pdf->SetDrawColor(192, 192, 192); - $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1); - - $tab_height = $tab_height - $height_note; - $tab_top = $nexY + 6; - } else { - $height_note = 0; } @@ -420,13 +513,15 @@ class pdf_espadon extends ModelePdfExpedition // Table simulation to know the height of the title line $pdf->startTransaction(); - $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); + $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs); $pdf->rollbackTransaction(true); $nexY = $tab_top + $this->tabTitleHeight; // Loop on each lines + $pageposbeforeprintlines = $pdf->getPage(); + $pagenb = $pageposbeforeprintlines; for ($i = 0; $i < $nblines; $i++) { $curY = $nexY; $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage @@ -590,7 +685,7 @@ class pdf_espadon extends ModelePdfExpedition // Detect if some page were added automatically and output _tableau for past pages while ($pagenb < $pageposafter) { $pdf->setPage($pagenb); - if ($pagenb == 1) { + if ($pagenb == $pageposbeforeprintlines) { $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1); } else { $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1); @@ -995,7 +1090,7 @@ class pdf_espadon extends ModelePdfExpedition $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("Sender").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Sender"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -1048,7 +1143,7 @@ class pdf_espadon extends ModelePdfExpedition $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name diff --git a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php index c41fd92f524..79ceb166eed 100644 --- a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php @@ -1039,7 +1039,7 @@ class pdf_rouget extends ModelePdfExpedition $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("Sender").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Sender"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -1092,7 +1092,7 @@ class pdf_rouget extends ModelePdfExpedition $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index d1f959f5460..1815321ab18 100644 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -796,7 +796,7 @@ class pdf_standard extends ModeleExpenseReport $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', 'B', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("TripSociete")." :", '', 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("TripSociete"), '', 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(224, 224, 224); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index e60f272caf5..a01fab1dacf 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1607,12 +1607,16 @@ class pdf_crabe extends ModelePDFFactures * @param Facture $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output + * @param Translate $outputlangsbis Object lang for output bis * @return void */ - protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) + protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null) { global $conf, $langs; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "bills", "propal", "companies")); @@ -1621,7 +1625,7 @@ class pdf_crabe extends ModelePDFFactures pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == Facture::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->FACTURE_DRAFT_WATERMARK); } @@ -1658,7 +1662,7 @@ class pdf_crabe extends ModelePDFFactures } } else { $text = $this->emetteur->name; - $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } } @@ -1681,6 +1685,23 @@ class pdf_crabe extends ModelePDFFactures if ($this->situationinvoice) { $title = $outputlangs->transnoentities("PDFInvoiceSituation"); } + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '; + if ($object->type == 0) { + if ($this->situationinvoice) { + $title .= $outputlangsbis->transnoentities("PDFInvoiceSituation"); + } + $title .= $outputlangsbis->transnoentities("PdfInvoiceTitle"); + } elseif ($object->type == 1) { + $title .= $outputlangsbis->transnoentities("InvoiceReplacement"); + } elseif ($object->type == 2) { + $title .= $outputlangsbis->transnoentities("InvoiceAvoir"); + } elseif ($object->type == 3) { + $title .= $outputlangsbis->transnoentities("InvoiceDeposit"); + } elseif ($object->type == 4) { + $title .= $outputlangsbis->transnoentities("InvoiceProForma"); + } + } $pdf->MultiCell($w, 3, $title, '', 'R'); $pdf->SetFont('', 'B', $default_font_size); @@ -1689,7 +1710,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); - if ($object->statut == Facture::STATUS_DRAFT) { + if ($object->statut == $object::STATUS_DRAFT) { $pdf->SetTextColor(128, 0, 0); $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); } @@ -1758,7 +1779,11 @@ class pdf_crabe extends ModelePDFFactures $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DateInvoice")." : ".dol_print_date($object->date, "day", false, $outputlangs), '', 'R'); + $title = $outputlangs->transnoentities("DateInvoice"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateInvoice"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R'); if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) { $posy += 4; @@ -1771,7 +1796,11 @@ class pdf_crabe extends ModelePDFFactures $posy += 3; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DateDue")." : ".dol_print_date($object->date_lim_reglement, "day", false, $outputlangs, true), '', 'R'); + $title = $outputlangs->transnoentities("DateDue"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateDue"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->date_lim_reglement, "day", false, $outputlangs, true), '', 'R'); } if ($object->thirdparty->code_client) { @@ -1824,7 +1853,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -1833,14 +1862,13 @@ class pdf_crabe extends ModelePDFFactures // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); - + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); // If BILLING contact defined on invoice, we use it @@ -1879,20 +1907,20 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 6ffc043eb5e..ad793d3d6b8 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1851,6 +1851,9 @@ class pdf_sponge extends ModelePDFFactures { global $conf, $langs; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "bills", "propal", "companies")); @@ -1896,7 +1899,7 @@ class pdf_sponge extends ModelePDFFactures } } else { $text = $this->emetteur->name; - $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } } @@ -2088,7 +2091,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -2097,15 +2100,15 @@ class pdf_sponge extends ModelePDFFactures // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); - // If BILLING contact defined, we use it + // If BILLING contact defined on invoice, we use it $usecontact = false; $arrayidcontact = $object->getIdContact('external', 'BILLING'); if (count($arrayidcontact) > 0) { @@ -2141,20 +2144,20 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 2, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php index ac0cb1fac80..08d57587625 100644 --- a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php +++ b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php @@ -528,7 +528,7 @@ class pdf_soleil extends ModelePDFFicheinter if (empty($hidebottom)) { $pdf->SetXY(20, 230); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("NameAndSignatureOfInternalContact"), 0, 'L', 0); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("NameAndSignatureOfInternalContact"), 0, 'L', 0); $pdf->SetXY(20, 235); $pdf->MultiCell(80, 25, '', 1); diff --git a/htdocs/core/modules/mailings/pomme.modules.php b/htdocs/core/modules/mailings/pomme.modules.php index 03334e62322..a2a54c02c55 100644 --- a/htdocs/core/modules/mailings/pomme.modules.php +++ b/htdocs/core/modules/mailings/pomme.modules.php @@ -171,7 +171,7 @@ class mailing_pomme extends MailingTargets $sql .= " FROM ".MAIN_DB_PREFIX."user as u"; $sql .= " WHERE u.email <> ''"; // u.email IS NOT NULL est implicite dans ce test $sql .= " AND u.entity IN (0,".$conf->entity.")"; - $sql .= " AND u.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + $sql .= " AND u.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; if (GETPOSTISSET("filter") && GETPOST("filter") == '1') { $sql .= " AND u.statut=1"; } diff --git a/htdocs/core/modules/mailings/thirdparties.modules.php b/htdocs/core/modules/mailings/thirdparties.modules.php index b3b88224df6..f764c3f5f71 100644 --- a/htdocs/core/modules/mailings/thirdparties.modules.php +++ b/htdocs/core/modules/mailings/thirdparties.modules.php @@ -77,7 +77,7 @@ class mailing_thirdparties extends MailingTargets $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE s.email <> ''"; $sql .= " AND s.entity IN (".getEntity('societe').")"; - $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; } else { $addFilter = ""; if (GETPOSTISSET("filter_client") && GETPOST("filter_client") <> '-1') { @@ -112,7 +112,7 @@ class mailing_thirdparties extends MailingTargets $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."categorie_societe as cs, ".MAIN_DB_PREFIX."categorie as c"; $sql .= " WHERE s.email <> ''"; $sql .= " AND s.entity IN (".getEntity('societe').")"; - $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; $sql .= " AND cs.fk_soc = s.rowid"; $sql .= " AND c.rowid = cs.fk_categorie"; $sql .= " AND c.rowid=".((int) GETPOST('filter', 'int')); @@ -122,7 +122,7 @@ class mailing_thirdparties extends MailingTargets $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."categorie_fournisseur as cs, ".MAIN_DB_PREFIX."categorie as c"; $sql .= " WHERE s.email <> ''"; $sql .= " AND s.entity IN (".getEntity('societe').")"; - $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; $sql .= " AND cs.fk_soc = s.rowid"; $sql .= " AND c.rowid = cs.fk_categorie"; $sql .= " AND c.rowid=".((int) GETPOST('filter', 'int')); diff --git a/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php b/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php index 7b5d4f38737..4c848b69ac0 100644 --- a/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php +++ b/htdocs/core/modules/mailings/thirdparties_services_expired.modules.php @@ -110,7 +110,7 @@ class mailing_thirdparties_services_expired extends MailingTargets $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as c"; $sql .= ", ".MAIN_DB_PREFIX."contratdet as cd, ".MAIN_DB_PREFIX."product as p"; $sql .= " WHERE s.entity IN (".getEntity('societe').")"; - $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".$mailing_id.")"; + $sql .= " AND s.email NOT IN (SELECT email FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE fk_mailing=".((int) $mailing_id).")"; $sql .= " AND s.rowid = c.fk_soc AND cd.fk_contrat = c.rowid AND s.email != ''"; $sql .= " AND cd.statut= 4 AND cd.fk_product=p.rowid AND p.ref = '".$this->db->escape($product)."'"; $sql .= " AND cd.date_fin_validite < '".$this->db->idate($now)."'"; diff --git a/htdocs/core/modules/member/modules_member.class.php b/htdocs/core/modules/member/modules_member.class.php index 1ff1ffc3d30..3a1b4edcc1d 100644 --- a/htdocs/core/modules/member/modules_member.class.php +++ b/htdocs/core/modules/member/modules_member.class.php @@ -20,10 +20,6 @@ */ -/** - * \class ModeleProductCode - * \brief Parent class for product code generators - */ /** * \file htdocs/core/modules/member/modules_member.class.php diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index b4645b51a87..21618c56bc9 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -54,13 +54,13 @@ class modAccounting extends DolibarrModules $this->version = 'dolibarr'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); - $this->picto = 'accounting'; + $this->picto = 'accountancy'; // Data directories to create when module is enabled $this->dirs = array('/accounting/temp'); // Config pages - $this->config_page_url = array(); + $this->config_page_url = array('accounting.php'); // Dependencies $this->depends = array("modFacture", "modBanque", "modTax"); // List of modules id that must be enabled if this module is enabled diff --git a/htdocs/core/modules/modAgenda.class.php b/htdocs/core/modules/modAgenda.class.php index 691828cd9d2..7a593740590 100644 --- a/htdocs/core/modules/modAgenda.class.php +++ b/htdocs/core/modules/modAgenda.class.php @@ -415,7 +415,7 @@ class modAgenda extends DolibarrModules 'langs' => 'agenda', 'position' => 170, 'perms' => '$user->rights->agenda->allactions->read', - 'enabled' => '$conf->categorie->enabled&&$conf->categorie->enabled', + 'enabled' => '$conf->categorie->enabled', 'target' => '', 'user' => 2 ); @@ -456,8 +456,12 @@ class modAgenda extends DolibarrModules 'p.ref' => 'project', ); + $keyforselect = 'actioncomm'; $keyforelement = 'action'; $keyforaliasextra = 'extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'actioncomm as ac'; + $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_extrafields as extra ON ac.id = extra.fk_object'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_actioncomm as cac on ac.fk_action = cac.id'; if (!empty($user) && empty($user->rights->agenda->allactions->read)) { $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_resources acr on ac.id = acr.fk_actioncomm'; diff --git a/htdocs/core/modules/modAsset.class.php b/htdocs/core/modules/modAsset.class.php index 12b58bfcc38..3a51a366970 100644 --- a/htdocs/core/modules/modAsset.class.php +++ b/htdocs/core/modules/modAsset.class.php @@ -69,7 +69,7 @@ class modAsset extends DolibarrModules // Name of image file used for this module. // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' - $this->picto = 'accounting'; + $this->picto = 'asset'; // Defined all module parts (triggers, login, substitutions, menus, css, etc...) // for default path (eg: /asset/core/xxxxx) (0=disable, 1=enable) diff --git a/htdocs/core/modules/modBom.class.php b/htdocs/core/modules/modBom.class.php index 6b69c6b7af0..18f46fda70f 100644 --- a/htdocs/core/modules/modBom.class.php +++ b/htdocs/core/modules/modBom.class.php @@ -2,6 +2,7 @@ /* Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2019 Maxime Kohlhaas + * Copyright (C) 2021 Ferran Marcet * * 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 @@ -315,6 +316,142 @@ class modBom extends DolibarrModules $this->export_sql_end[$r] .= ' AND t.entity IN ('.getEntity('bom').')'; $r++; /* END MODULEBUILDER EXPORT BILLOFMATERIALS */ + + // Imports + //-------- + $r = 0; + //Import BOM Header + + $r++; + $this->import_code[$r] = 'bom_'.$r; + $this->import_label[$r] = 'BillOfMaterials'; + $this->import_icon[$r] = $this->picto; + $this->import_entities_array[$r] = []; + $this->import_tables_array[$r] = ['b' => MAIN_DB_PREFIX.'bom_bom', 'extra' => MAIN_DB_PREFIX.'bom_bom_extrafields']; + $this->import_tables_creator_array[$r] = ['b' => 'fk_user_creat']; // Fields to store import user id + $this->import_fields_array[$r] = [ + 'b.ref' => 'Document Ref*', + 'b.label' => 'BomLabel*', + 'b.fk_product' => 'ProductRef*', + 'b.description' => 'Description', + 'b.note_public' => 'Note', + 'b.note_private' => 'NotePrivate', + 'b.fk_warehouse' => 'WarehouseRef', + 'b.qty' => 'Qty', + 'b.efficiency' => 'Efficiency', + 'b.duration' => 'Duration', + 'b.date_creation' => 'DateCreation', + 'b.date_valid' => 'DateValid', + 'b.fk_user_modif' => 'ModifiedById', + 'b.fk_user_valid' => 'ValidatedById', + 'b.model_pdf' => 'Model', + 'b.status' => 'Status*', + 'b.bomtype' => 'BomType*' + + ]; + + // Add extra fields + $import_extrafield_sample = []; + $sql = "SELECT name, label, fieldrequired FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'bom_bom' AND entity IN (0, ".$conf->entity.")"; + $resql = $this->db->query($sql); + + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $fieldname = 'extra.'.$obj->name; + $fieldlabel = ucfirst($obj->label); + $this->import_fields_array[$r][$fieldname] = $fieldlabel.($obj->fieldrequired ? '*' : ''); + $import_extrafield_sample[$fieldname] = $fieldlabel; + } + } + // End add extra fields + + $this->import_fieldshidden_array[$r] = ['extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'bom_bom']; + $this->import_regex_array[$r] = [ + 'b.ref' => '(CPV\d{4}-\d{4}|BOM\d{4}-\d{4}|PROV.{1,32}$)' + ]; + + $this->import_updatekeys_array[$r] = ['b.ref' => 'Ref']; + $this->import_convertvalue_array[$r] = [ + 'b.fk_product' => [ + 'rule' => 'fetchidfromref', + 'file' => '/product/class/product.class.php', + 'class' => 'Product', + 'method' => 'fetch', + 'element' => 'Product' + ], + 'b.fk_warehouse' => [ + 'rule' => 'fetchidfromref', + 'file' => '/product/stock/class/entrepot.class.php', + 'class' => 'Entrepot', + 'method' => 'fetch', + 'element' => 'Warehouse' + ], + 'b.fk_user_valid' => [ + 'rule' => 'fetchidfromref', + 'file' => '/user/class/user.class.php', + 'class' => 'User', + 'method' => 'fetch', + 'element' => 'user' + ], + 'b.fk_user_modif' => [ + 'rule' => 'fetchidfromref', + 'file' => '/user/class/user.class.php', + 'class' => 'User', + 'method' => 'fetch', + 'element' => 'user' + ], + ]; + + //Import BOM Lines + $r++; + $this->import_code[$r] = 'bom_lines_'.$r; + $this->import_label[$r] = 'BillOfMaterialsLine'; + $this->import_icon[$r] = $this->picto; + $this->import_entities_array[$r] = []; + $this->import_tables_array[$r] = ['bd' => MAIN_DB_PREFIX.'bom_bomline', 'extra' => MAIN_DB_PREFIX.'bom_bomline_extrafields']; + $this->import_fields_array[$r] = [ + 'bd.fk_bom' => 'Document Ref*', + 'bd.fk_product' => 'ProductRef', + 'bd.fk_bom_child' => 'BOMChild', + 'bd.description' => 'Description', + 'bd.qty' => 'LineQty', + 'bd.qty_frozen' => 'LineIsFrozen', + 'bd.disable_stock_change' => 'Disable Stock Change', + 'bd.efficiency' => 'Efficiency', + 'bd.position' => 'LinePosition' + ]; + + // Add extra fields + $sql = "SELECT name, label, fieldrequired FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'bom_bomline' AND entity IN (0, ".$conf->entity.")"; + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $fieldname = 'extra.'.$obj->name; + $fieldlabel = ucfirst($obj->label); + $this->import_fields_array[$r][$fieldname] = $fieldlabel.($obj->fieldrequired ? '*' : ''); + } + } + // End add extra fields + + $this->import_fieldshidden_array[$r] = ['extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'bom_bomline']; + $this->import_regex_array[$r] = []; + $this->import_updatekeys_array[$r] = ['bd.fk_bom' => 'BOM Id']; + $this->import_convertvalue_array[$r] = [ + 'bd.fk_bom' => [ + 'rule' => 'fetchidfromref', + 'file' => '/bom/class/bom.class.php', + 'class' => 'BOM', + 'method' => 'fetch', + 'element' => 'bom' + ], + 'bd.fk_product' => [ + 'rule' => 'fetchidfromref', + 'file' => '/product/class/product.class.php', + 'class' => 'Product', + 'method' => 'fetch', + 'element' => 'Product' + ], + ]; } /** diff --git a/htdocs/core/modules/modCashDesk.class.php b/htdocs/core/modules/modCashDesk.class.php index ba6c7ddce6c..a128b92ee29 100644 --- a/htdocs/core/modules/modCashDesk.class.php +++ b/htdocs/core/modules/modCashDesk.class.php @@ -51,7 +51,7 @@ class modCashDesk extends DolibarrModules $this->name = preg_replace('/^mod/i', '', get_class($this)); $this->description = "CashDesk module"; - $this->version = 'dolibarr'; + $this->version = 'deprecated'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->picto = 'cash-register'; diff --git a/htdocs/core/modules/modComptabilite.class.php b/htdocs/core/modules/modComptabilite.class.php index 09f6cd85496..be8f1954959 100644 --- a/htdocs/core/modules/modComptabilite.class.php +++ b/htdocs/core/modules/modComptabilite.class.php @@ -57,7 +57,7 @@ class modComptabilite extends DolibarrModules $this->version = 'dolibarr'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); - $this->picto = 'accounting'; + $this->picto = 'accountancy'; // Config pages $this->config_page_url = array("compta.php"); diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index d1ad993af68..b296fa3b32c 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -121,6 +121,7 @@ class modFacture extends DolibarrModules $datestart = dol_mktime(23, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']); $this->cronjobs = array( 0=>array('label'=>'RecurringInvoices', 'jobtype'=>'method', 'class'=>'compta/facture/class/facture-rec.class.php', 'objectname'=>'FactureRec', 'method'=>'createRecurringInvoices', 'parameters'=>'', 'comment'=>'Generate recurring invoices', 'frequency'=>1, 'unitfrequency'=>3600 * 24, 'priority'=>50, 'status'=>1, 'test'=>'$conf->facture->enabled', 'datestart'=>$datestart), + 1=>array('label'=>'SendEmailsRemindersOnInvoiceDueDate', 'jobtype'=>'method', 'class'=>'compta/facture/class/facture.class.php', 'objectname'=>'Facture', 'method'=>'sendEmailsRemindersOnInvoiceDueDate', 'parameters'=>"10,all,EmailTemplateCode", 'comment'=>'Send an emails when the unpaid invoices reach a due date + n days = today. First param is the offset n of days, second parameter is "all" or a payment mode code, last paramater is the code of email template to use (an email template with EmailTemplateCode must exists. the version in the language of the thirdparty will be used in priority).', 'frequency'=>1, 'unitfrequency'=>3600 * 24, 'priority'=>50, 'status'=>0, 'test'=>'$conf->facture->enabled', 'datestart'=>$datestart), ); // Permissions @@ -207,7 +208,7 @@ class modFacture extends DolibarrModules //-------- $r = 1; - $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; + $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $this->export_code[$r] = $this->rights_class.'_'.$r; $this->export_label[$r] = 'CustomersInvoicesAndInvoiceLines'; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_icon[$r] = 'invoice'; @@ -296,7 +297,7 @@ class modFacture extends DolibarrModules $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facturedet_extrafields as extra2 on fd.rowid = extra2.fk_object'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra3 on p.rowid = extra3.fk_object'; $this->export_sql_end[$r] .= ' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 71f101014ad..fae1cfc0eb8 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -488,7 +488,8 @@ class modFournisseur extends DolibarrModules $tmp = ''; $tmpparam = unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null if ($tmpparam['options'] && is_array($tmpparam['options'])) { - $tmp = array_shift(array_keys($tmpparam['options'])); + $array_keys = array_keys($tmpparam['options']); + $tmp = array_shift($array_keys); } if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) { $typeFilter = "List:".$tmp; diff --git a/htdocs/core/modules/modIncoterm.class.php b/htdocs/core/modules/modIncoterm.class.php index a7a260dba6e..9ef50fe3aac 100644 --- a/htdocs/core/modules/modIncoterm.class.php +++ b/htdocs/core/modules/modIncoterm.class.php @@ -56,7 +56,7 @@ class modIncoterm extends DolibarrModules $this->version = 'dolibarr'; // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); - $this->picto = 'generic'; + $this->picto = 'incoterm'; $this->module_parts = array(); $this->dirs = array(); diff --git a/htdocs/core/modules/modKnowledgeManagement.class.php b/htdocs/core/modules/modKnowledgeManagement.class.php new file mode 100644 index 00000000000..504c363b648 --- /dev/null +++ b/htdocs/core/modules/modKnowledgeManagement.class.php @@ -0,0 +1,542 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2021 SuperAdmin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \defgroup knowledgemanagement Module KnowledgeManagement + * \brief KnowledgeManagement module descriptor. + * + * \file htdocs/knowledgemanagement/core/modules/modKnowledgeManagement.class.php + * \ingroup knowledgemanagement + * \brief Description and activation file for module KnowledgeManagement + */ +include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + +/** + * Description and activation class for module KnowledgeManagement + */ +class modKnowledgeManagement extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs, $conf; + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 57000; + + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'knowledgemanagement'; + + // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' + // It is used to group modules by family in module setup page + $this->family = "crm"; + + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '90'; + + // Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); + // Module label (no space allowed), used if translation string 'ModuleKnowledgeManagementName' not found (KnowledgeManagement is name of module). + $this->name = preg_replace('/^mod/i', '', get_class($this)); + + // Module description, used if translation string 'ModuleKnowledgeManagementDesc' not found (KnowledgeManagement is name of module). + $this->description = "Knowledge Management (KM)"; + // Used only if file README.md and README-LL.md not found. + $this->descriptionlong = "Manage a Knowledge Management (KM) or Help-Desk base"; + + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' + $this->version = 'development'; + // Url to the file with your last numberversion of this module + //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; + + // Key used in llx_const table to save module status enabled/disabled (where KNOWLEDGEMANAGEMENT is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' + $this->picto = 'knowledgemanagement'; + + // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + // Set this to 1 if module has its own trigger directory (core/triggers) + 'triggers' => 0, + // Set this to 1 if module has its own login method file (core/login) + 'login' => 0, + // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 0, + // Set this to 1 if module has its own menus handler directory (core/menus) + 'menus' => 0, + // Set this to 1 if module overwrite template dir (core/tpl) + 'tpl' => 0, + // Set this to 1 if module has its own barcode directory (core/modules/barcode) + 'barcode' => 0, + // Set this to 1 if module has its own models directory (core/modules/xxx) + 'models' => 1, + // Set this to 1 if module has its own printing directory (core/modules/printing) + 'printing' => 0, + // Set this to 1 if module has its own theme directory (theme) + 'theme' => 0, + // Set this to relative path of css file if module has its own css file + 'css' => array( + // '/knowledgemanagement/css/knowledgemanagement.css.php', + ), + // Set this to relative path of js file if module must load a js on all pages + 'js' => array( + // '/knowledgemanagement/js/knowledgemanagement.js.php', + ), + // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all' + 'hooks' => array( + // 'data' => array( + // 'hookcontext1', + // 'hookcontext2', + // ), + // 'entity' => '0', + ), + // Set this to 1 if features of module are opened to external users + 'moduleforexternal' => 0, + ); + + // Data directories to create when module is enabled. + // Example: this->dirs = array("/knowledgemanagement/temp","/knowledgemanagement/subdir"); + $this->dirs = array("/knowledgemanagement/temp"); + + // Config pages. Put here list of php page, stored into knowledgemanagement/admin directory, to use to setup module. + $this->config_page_url = array("knowledgemanagement.php"); + + // Dependencies + // A condition to hide module + $this->hidden = false; + // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) + $this->depends = array(); + $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) + + // The language file dedicated to your module + $this->langfiles = array("knowledgemanagement"); + + // Prerequisites + $this->phpmin = array(5, 6); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(11, -3); // Minimum version of Dolibarr required by module + + // Messages at activation + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + //$this->automatic_activation = array('FR'=>'KnowledgeManagementWasAutomaticallyActivatedBecauseOfYourCountryChoice'); + //$this->always_enabled = true; // If true, can't be disabled + + // Constants + // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) + // Example: $this->const=array(1 => array('KNOWLEDGEMANAGEMENT_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1), + // 2 => array('KNOWLEDGEMANAGEMENT_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1) + // ); + $this->const = array(); + + // Some keys to add into the overwriting translation tables + /*$this->overwrite_translation = array( + 'en_US:ParentCompany'=>'Parent company or reseller', + 'fr_FR:ParentCompany'=>'Maison mère ou revendeur' + )*/ + + if (!isset($conf->knowledgemanagement) || !isset($conf->knowledgemanagement->enabled)) { + $conf->knowledgemanagement = new stdClass(); + $conf->knowledgemanagement->enabled = 0; + } + + // Array to add new pages in new tabs + $this->tabs = array(); + // Example: + // $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@knowledgemanagement:$user->rights->knowledgemanagement->read:/knowledgemanagement/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1 + // $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@knowledgemanagement:$user->rights->othermodule->read:/knowledgemanagement/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // $this->tabs[] = array('data'=>'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // + // Where objecttype can be + // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) + // 'contact' to add a tab in contact view + // 'contract' to add a tab in contract view + // 'group' to add a tab in group view + // 'intervention' to add a tab in intervention view + // 'invoice' to add a tab in customer invoice view + // 'invoice_supplier' to add a tab in supplier invoice view + // 'member' to add a tab in fundation member view + // 'opensurveypoll' to add a tab in opensurvey poll view + // 'order' to add a tab in customer order view + // 'order_supplier' to add a tab in supplier order view + // 'payment' to add a tab in payment view + // 'payment_supplier' to add a tab in supplier payment view + // 'product' to add a tab in product view + // 'propal' to add a tab in propal view + // 'project' to add a tab in project view + // 'stock' to add a tab in stock view + // 'thirdparty' to add a tab in third party view + // 'user' to add a tab in user view + + // Dictionaries + $this->dictionaries = array(); + /* Example: + $this->dictionaries=array( + 'langs'=>'knowledgemanagement@knowledgemanagement', + // List of tables we want to see into dictonnary editor + 'tabname'=>array(MAIN_DB_PREFIX."table1", MAIN_DB_PREFIX."table2", MAIN_DB_PREFIX."table3"), + // Label of tables + 'tablib'=>array("Table1", "Table2", "Table3"), + // Request to select fields + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), + // Sort order + 'tabsqlsort'=>array("label ASC", "label ASC", "label ASC"), + // List of fields (result of select to show dictionary) + 'tabfield'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields to edit a record) + 'tabfieldvalue'=>array("code,label", "code,label", "code,label"), + // List of fields (list of fields for insert) + 'tabfieldinsert'=>array("code,label", "code,label", "code,label"), + // Name of columns with primary key (try to always name it 'rowid') + 'tabrowid'=>array("rowid", "rowid", "rowid"), + // Condition to show each dictionary + 'tabcond'=>array($conf->knowledgemanagement->enabled, $conf->knowledgemanagement->enabled, $conf->knowledgemanagement->enabled) + ); + */ + + // Boxes/Widgets + // Add here list of php file(s) stored in knowledgemanagement/core/boxes that contains a class to show a widget. + $this->boxes = array( + // 0 => array( + // 'file' => 'knowledgemanagementwidget1.php@knowledgemanagement', + // 'note' => 'Widget provided by KnowledgeManagement', + // 'enabledbydefaulton' => 'Home', + // ), + // ... + ); + + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week + $this->cronjobs = array( + // 0 => array( + // 'label' => 'MyJob label', + // 'jobtype' => 'method', + // 'class' => '/knowledgemanagement/class/knowledgerecord.class.php', + // 'objectname' => 'KnowledgeRecord', + // 'method' => 'doScheduledJob', + // 'parameters' => '', + // 'comment' => 'Comment', + // 'frequency' => 2, + // 'unitfrequency' => 3600, + // 'status' => 0, + // 'test' => '$conf->knowledgemanagement->enabled', + // 'priority' => 50, + // ), + ); + // Example: $this->cronjobs=array( + // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->knowledgemanagement->enabled', 'priority'=>50), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->knowledgemanagement->enabled', 'priority'=>50) + // ); + + // Permissions provided by this module + $this->rights = array(); + $r = 0; + // Add here entries to declare new permissions + /* BEGIN MODULEBUILDER PERMISSIONS */ + $this->rights[$r][0] = $this->numero + $r + 1; // Permission id (must not be already used) + $this->rights[$r][1] = 'Read objects of Knowledge Management'; // Permission label + $this->rights[$r][4] = 'knowledgerecord'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $this->rights[$r][5] = 'read'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r + 1; // Permission id (must not be already used) + $this->rights[$r][1] = 'Create/Update objects of Knowledge Management'; // Permission label + $this->rights[$r][4] = 'knowledgerecord'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $this->rights[$r][5] = 'write'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $r++; + $this->rights[$r][0] = $this->numero + $r + 1; // Permission id (must not be already used) + $this->rights[$r][1] = 'Delete objects of Knowledge Management'; // Permission label + $this->rights[$r][4] = 'knowledgerecord'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $this->rights[$r][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->knowledgemanagement->level1->level2) + $r++; + /* END MODULEBUILDER PERMISSIONS */ + + // Main menu entries to add + $this->menu = array(); + $r = 0; + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + $this->menu[$r++] = array( + 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'top', // This is a Top menu entry + 'titre'=>'ModuleKnowledgeManagementName', + 'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth em092"'), + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'', + 'url'=>'/knowledgemanagement/knowledgerecord_list.php', + 'langs'=>'knowledgemanagement', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000 + $r, + 'enabled'=>'$conf->knowledgemanagement->enabled', // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->knowledgemanagement->knowledgerecord->read' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + /* END MODULEBUILDER TOPMENU */ + /* BEGIN MODULEBUILDER LEFTMENU KNOWLEDGERECORD + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=knowledgemanagement', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Top menu entry + 'titre'=>'KnowledgeRecord', + 'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth"'), + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgerecord', + 'url'=>'/knowledgemanagement/knowledgemanagementindex.php', + 'langs'=>'knowledgemanagement@knowledgemanagement', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->knowledgemanagement->enabled', // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->knowledgemanagement->knowledgerecord->read', // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=knowledgemanagement,fk_leftmenu=knowledgerecord', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List_KnowledgeRecord', + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgemanagement_knowledgerecord_list', + 'url'=>'/knowledgemanagement/knowledgerecord_list.php', + 'langs'=>'knowledgemanagement@knowledgemanagement', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->knowledgemanagement->enabled', // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->knowledgemanagement->knowledgerecord->read', // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + $this->menu[$r++]=array( + 'fk_menu'=>'fk_mainmenu=knowledgemanagement,fk_leftmenu=knowledgerecord', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New_KnowledgeRecord', + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgemanagement_knowledgerecord_new', + 'url'=>'/knowledgemanagement/knowledgerecord_card.php?action=create', + 'langs'=>'knowledgemanagement@knowledgemanagement', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000+$r, + 'enabled'=>'$conf->knowledgemanagement->enabled', // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->knowledgemanagement->knowledgerecord->write', // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both + ); + */ + + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=knowledgemanagement', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'MenuKnowledgeRecord', + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgemanagement_knowledgerecord', + 'url'=>'/knowledgemanagement/knowledgerecord_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'knowledgemanagement', + 'position'=>101, + // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->knowledgemanagement->enabled', + // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=knowledgemanagement,fk_leftmenu=knowledgemanagement_knowledgerecord', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'ListKnowledgeRecord', + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgemanagement_list', + 'url'=>'/knowledgemanagement/knowledgerecord_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'knowledgemanagement', + 'position'=>111, + // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->knowledgemanagement->enabled', + // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + $this->menu[$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=knowledgemanagement,fk_leftmenu=knowledgemanagement_knowledgerecord', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'NewKnowledgeRecord', + 'mainmenu'=>'knowledgemanagement', + 'leftmenu'=>'knowledgemanagement_new', + 'url'=>'/knowledgemanagement/knowledgerecord_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'knowledgemanagement', + 'position'=>110, + // Define condition to show or hide menu entry. Use '$conf->knowledgemanagement->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->knowledgemanagement->enabled', + // Use 'perms'=>'$user->rights->knowledgemanagement->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + ); + + /* END MODULEBUILDER LEFTMENU KNOWLEDGERECORD */ + // Exports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER EXPORT KNOWLEDGERECORD */ + /* + $langs->load("knowledgemanagement"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='KnowledgeRecordLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='knowledgerecord@knowledgemanagement'; + // Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array + $keyforclass = 'KnowledgeRecord'; $keyforclassfile='/knowledgemanagement/class/knowledgerecord.class.php'; $keyforelement='knowledgerecord@knowledgemanagement'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; + //unset($this->export_fields_array[$r]['t.fieldtoremove']); + //$keyforclass = 'KnowledgeRecordLine'; $keyforclassfile='/knowledgemanagement/class/knowledgerecord.class.php'; $keyforelement='knowledgerecordline@knowledgemanagement'; $keyforalias='tl'; + //include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='knowledgerecord'; $keyforaliasextra='extra'; $keyforelement='knowledgerecord@knowledgemanagement'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$keyforselect='knowledgerecordline'; $keyforaliasextra='extraline'; $keyforelement='knowledgerecordline@knowledgemanagement'; + //include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r] = array('knowledgerecordline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + //$this->export_special_array[$r] = array('t.field'=>'...'); + //$this->export_examplevalues_array[$r] = array('t.field'=>'Example'); + //$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp'); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'knowledgerecord as t'; + //$this->export_sql_end[$r] =' LEFT JOIN '.MAIN_DB_PREFIX.'knowledgerecord_line as tl ON tl.fk_knowledgerecord = t.rowid'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('knowledgerecord').')'; + $r++; */ + /* END MODULEBUILDER EXPORT KNOWLEDGERECORD */ + + // Imports profiles provided by this module + $r = 1; + /* BEGIN MODULEBUILDER IMPORT KNOWLEDGERECORD */ + /* + $langs->load("knowledgemanagement"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='KnowledgeRecordLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='knowledgerecord@knowledgemanagement'; + $keyforclass = 'KnowledgeRecord'; $keyforclassfile='/knowledgemanagement/class/knowledgerecord.class.php'; $keyforelement='knowledgerecord@knowledgemanagement'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='knowledgerecord'; $keyforaliasextra='extra'; $keyforelement='knowledgerecord@knowledgemanagement'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'knowledgerecord as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('knowledgerecord').')'; + $r++; */ + /* END MODULEBUILDER IMPORT KNOWLEDGERECORD */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + global $conf, $langs; + + $result = $this->_load_tables('/knowledgemanagement/sql/'); + if ($result < 0) { + return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + } + + // Create extrafields during init + //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + //$extrafields = new ExtraFields($this->db); + //$result1=$extrafields->addExtraField('knowledgemanagement_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'knowledgemanagement@knowledgemanagement', '$conf->knowledgemanagement->enabled'); + //$result2=$extrafields->addExtraField('knowledgemanagement_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'knowledgemanagement@knowledgemanagement', '$conf->knowledgemanagement->enabled'); + //$result3=$extrafields->addExtraField('knowledgemanagement_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'knowledgemanagement@knowledgemanagement', '$conf->knowledgemanagement->enabled'); + //$result4=$extrafields->addExtraField('knowledgemanagement_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'knowledgemanagement@knowledgemanagement', '$conf->knowledgemanagement->enabled'); + //$result5=$extrafields->addExtraField('knowledgemanagement_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'knowledgemanagement@knowledgemanagement', '$conf->knowledgemanagement->enabled'); + + // Permissions + $this->remove($options); + + $sql = array(); + + // Document templates + $moduledir = 'knowledgemanagement'; + $myTmpObjects = array(); + $myTmpObjects['KnowledgeRecord'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); + + foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'KnowledgeRecord') { + continue; + } + if ($myTmpObjectArray['includerefgeneration']) { + $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/knowledgemanagement/template_knowledgerecords.odt'; + $dirodt = DOL_DATA_ROOT.'/doctemplates/knowledgemanagement'; + $dest = $dirodt.'/template_knowledgerecords.odt'; + + if (file_exists($src) && !file_exists($dest)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + dol_mkdir($dirodt); + $result = dol_copy($src, $dest, 0, 0); + if ($result < 0) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest); + return 0; + } + } + + $sql = array_merge($sql, array( + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".strtolower($myTmpObjectKey)."' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."','".strtolower($myTmpObjectKey)."',".$conf->entity.")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".strtolower($myTmpObjectKey)."' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".strtolower($myTmpObjectKey)."', ".$conf->entity.")" + )); + } + } + + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php index 17c137a7e3c..d7041eca754 100644 --- a/htdocs/core/modules/modPartnership.class.php +++ b/htdocs/core/modules/modPartnership.class.php @@ -48,7 +48,7 @@ class modPartnership extends DolibarrModules // Id for module (must be unique). // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). - $this->numero = 500000; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + $this->numero = 58000; // Key text used to identify module (for permissions, menus, etc...) $this->rights_class = 'partnership'; @@ -86,7 +86,7 @@ class modPartnership extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'generic'; + $this->picto = 'partnership'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( @@ -144,7 +144,7 @@ class modPartnership extends DolibarrModules $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) // The language file dedicated to your module - $this->langfiles = array("partnership@partnership"); + $this->langfiles = array("partnership"); // Prerequisites $this->phpmin = array(5, 6); // Minimum version of PHP required by module @@ -180,10 +180,8 @@ class modPartnership extends DolibarrModules $tabtoadd = (!empty(getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR')) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') ? 'member' : 'thirdparty'; if ($tabtoadd == 'member') { - $this->tabs[] = array('data'=>'member:+partnership:Partnership:partnership@partnership:$user->rights->partnership->read:/partnership/partnership.php?socid=__ID__'); $fk_mainmenu = "members"; } else { - $this->tabs[] = array('data'=>'thirdparty:+partnership:Partnership:partnership@partnership:$user->rights->partnership->read:/partnership/partnership.php?socid=__ID__'); $fk_mainmenu = "companies"; } @@ -214,30 +212,27 @@ class modPartnership extends DolibarrModules // 'user' to add a tab in user view // Dictionaries - $this->dictionaries = array(); - /* Example: $this->dictionaries=array( 'langs'=>'partnership@partnership', // List of tables we want to see into dictonnary editor - 'tabname'=>array(MAIN_DB_PREFIX."table1", MAIN_DB_PREFIX."table2", MAIN_DB_PREFIX."table3"), + 'tabname'=>array(MAIN_DB_PREFIX."c_partnership_type"), // Label of tables - 'tablib'=>array("Table1", "Table2", "Table3"), + 'tablib'=>array("PartnershipType"), // Request to select fields - 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), + 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'c_partnership_type as f WHERE f.entity = '.$conf->entity), // Sort order - 'tabsqlsort'=>array("label ASC", "label ASC", "label ASC"), + 'tabsqlsort'=>array("label ASC"), // List of fields (result of select to show dictionary) - 'tabfield'=>array("code,label", "code,label", "code,label"), + 'tabfield'=>array("code,label"), // List of fields (list of fields to edit a record) - 'tabfieldvalue'=>array("code,label", "code,label", "code,label"), + 'tabfieldvalue'=>array("code,label"), // List of fields (list of fields for insert) - 'tabfieldinsert'=>array("code,label", "code,label", "code,label"), + 'tabfieldinsert'=>array("code,label"), // Name of columns with primary key (try to always name it 'rowid') - 'tabrowid'=>array("rowid", "rowid", "rowid"), + 'tabrowid'=>array("rowid"), // Condition to show each dictionary - 'tabcond'=>array($conf->partnership->enabled, $conf->partnership->enabled, $conf->partnership->enabled) + 'tabcond'=>array($conf->partnership->enabled) ); - */ // Boxes/Widgets // Add here list of php file(s) stored in partnership/core/boxes that contains a class to show a widget. @@ -253,12 +248,12 @@ class modPartnership extends DolibarrModules // Cronjobs (List of cron jobs entries to add when module is enabled) // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week - $statusatinstall=0; $arraydate=dol_getdate(dol_now()); $datestart=dol_mktime(21, 15, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']); $this->cronjobs = array( - 0 => array('priority'=>60, 'label'=>'CancelPartnershipForExpiredMembers', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doCancelStatusOfPartnership', 'parameters'=>'', 'comment'=>'Cancel status of partnership when subscription is expired + x days.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>$statusatinstall, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart), + 0 => array('priority'=>60, 'label'=>'CancelPartnershipForExpiredMembers', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doCancelStatusOfMemberPartnership', 'parameters'=>'', 'comment'=>'Cancel status of partnership when subscription is expired + x days.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>1, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart), + 1 => array('priority'=>61, 'label'=>'PartnershipCheckBacklink', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doWarningOfPartnershipIfDolibarrBacklinkNotfound', 'parameters'=>'', 'comment'=>'Warning of partnership if Dolibarr backlink not found on partner website.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>0, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart), ); // Permissions provided by this module diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index e9dc9688217..3459973a699 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -176,7 +176,7 @@ class modProduct extends DolibarrModules //-------- $r = 0; - $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; + $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $r++; $this->export_code[$r] = $this->rights_class.'_'.$r; @@ -296,7 +296,7 @@ class modProduct extends DolibarrModules $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'product as p'; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } if (!empty($conf->global->EXPORTTOOL_CATEGORIES)) { $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cp.fk_categorie = cat.rowid'; @@ -447,7 +447,7 @@ class modProduct extends DolibarrModules $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'product as p'; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; $this->export_sql_end[$r] .= ' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; diff --git a/htdocs/core/modules/modPropale.class.php b/htdocs/core/modules/modPropale.class.php index ea9f9548cb7..048f8fcb508 100644 --- a/htdocs/core/modules/modPropale.class.php +++ b/htdocs/core/modules/modPropale.class.php @@ -157,7 +157,8 @@ class modPropale extends DolibarrModules $this->rights[$r][1] = 'Close commercial proposals'; // Set proposal to signed or refused $this->rights[$r][2] = 'd'; // type de la permission (deprecie a ce jour) $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut - $this->rights[$r][4] = 'cloturer'; + $this->rights[$r][4] = 'propal_advance'; + $this->rights[$r][5] = 'close'; $r++; $this->rights[$r][0] = 27; // id de la permission diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index fd019ca4c68..21a26bdc750 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -143,7 +143,7 @@ class modService extends DolibarrModules //-------- $r = 0; - $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "pa"; + $alias_product_perentity = empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p" : "ppe"; $r++; $this->export_code[$r] = $this->rights_class.'_'.$r; @@ -259,7 +259,7 @@ class modService extends DolibarrModules $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'product as p'; if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) { - $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as pa ON pa.fk_product = p.rowid AND pa.entity = " . ((int) $conf->entity); + $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } if (!empty($conf->global->EXPORTTOOL_CATEGORIES)) { $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cp.fk_categorie = cat.rowid'; diff --git a/htdocs/core/modules/modTakePos.class.php b/htdocs/core/modules/modTakePos.class.php index d34213f062c..5cb7a7f0c38 100644 --- a/htdocs/core/modules/modTakePos.class.php +++ b/htdocs/core/modules/modTakePos.class.php @@ -198,11 +198,25 @@ class modTakePos extends DolibarrModules $r++; $this->rights[$r][0] = 50151; - $this->rights[$r][1] = 'Use Point Of Sale'; + $this->rights[$r][1] = 'Use Point Of Sale (record a sale, add products, record payment)'; $this->rights[$r][2] = 'a'; $this->rights[$r][3] = 0; $this->rights[$r][4] = 'run'; + $r++; + $this->rights[$r][0] = 50152; + $this->rights[$r][1] = 'Can modify added sales lines (prices, discount)'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'editlines'; + + $r++; + $this->rights[$r][0] = 50153; + $this->rights[$r][1] = 'Edit ordered sales lines (useful only when option "Order printers" has been enabled). Allow to edit sales lines even after the order has been printed'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'editorderedlines'; + // Main menu entries $this->menu = array(); // List of menus to add diff --git a/htdocs/core/modules/modUser.class.php b/htdocs/core/modules/modUser.class.php index e84998635ff..01303892435 100644 --- a/htdocs/core/modules/modUser.class.php +++ b/htdocs/core/modules/modUser.class.php @@ -231,7 +231,8 @@ class modUser extends DolibarrModules 'u.birth'=>'DateOfBirth', 'u.datec'=>"DateCreation", 'u.tms'=>"DateLastModification", 'u.admin'=>"Administrator", 'u.statut'=>'Status', 'u.datelastlogin'=>'LastConnexion', 'u.datepreviouslogin'=>'PreviousConnexion', - 'u.fk_socpeople'=>"IdContact", 'u.fk_soc'=>"IdCompany", 'u.fk_member'=>"MemberId" + 'u.fk_socpeople'=>"IdContact", 'u.fk_soc'=>"IdCompany", 'u.fk_member'=>"MemberId", + 'g.nom'=>"Group" ); $this->export_TypeFields_array[$r] = array( 'u.rowid'=>'Numeric', 'u.login'=>"Text", 'u.lastname'=>"Text", 'u.firstname'=>"Text", 'u.employee'=>'Boolean', 'u.job'=>'Text', @@ -241,7 +242,8 @@ class modUser extends DolibarrModules 'u.email'=>'Text', 'u.datec'=>"Date", 'u.tms'=>"Date", 'u.admin'=>"Boolean", 'u.statut'=>'Status', 'u.note'=>"Text", 'u.datelastlogin'=>'Date', 'u.fk_user'=>"List:user:login", 'u.birth'=>'Date', - 'u.datepreviouslogin'=>'Date', 'u.fk_soc'=>"List:societe:nom:rowid", 'u.fk_member'=>"List:adherent:firstname" + 'u.datepreviouslogin'=>'Date', 'u.fk_soc'=>"List:societe:nom:rowid", 'u.fk_member'=>"List:adherent:firstname", + 'g.nom'=>"Text" ); $this->export_entities_array[$r] = array( 'u.rowid'=>"user", 'u.login'=>"user", 'u.lastname'=>"user", 'u.firstname'=>"user", 'u.employee'=>'user', 'u.job'=>'user', 'u.gender'=>'user', @@ -254,7 +256,8 @@ class modUser extends DolibarrModules 'u.birth'=>'user', 'u.datec'=>"user", 'u.tms'=>"user", 'u.admin'=>"user", 'u.statut'=>'user', 'u.datelastlogin'=>'user', 'u.datepreviouslogin'=>'user', - 'u.fk_socpeople'=>"contact", 'u.fk_soc'=>"company", 'u.fk_member'=>"member" + 'u.fk_socpeople'=>"contact", 'u.fk_soc'=>"company", 'u.fk_member'=>"member", + 'g.nom'=>"Group" ); $keyforselect = 'user'; $keyforelement = 'user'; @@ -267,6 +270,8 @@ class modUser extends DolibarrModules $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'user as u'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user_extrafields as extra ON u.rowid = extra.fk_object'; + $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'usergroup_user as ug ON u.rowid = ug.fk_user'; + $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'usergroup as g ON ug.fk_usergroup = g.rowid'; $this->export_sql_end[$r] .= ' WHERE u.entity IN ('.getEntity('user').')'; // Imports diff --git a/htdocs/core/modules/modWorkstation.class.php b/htdocs/core/modules/modWorkstation.class.php index b0fae39bb52..8e2d676bf27 100755 --- a/htdocs/core/modules/modWorkstation.class.php +++ b/htdocs/core/modules/modWorkstation.class.php @@ -263,73 +263,12 @@ class modWorkstation extends DolibarrModules $this->menu = array(); $r = 0; // Add here entries to declare new menus - /* BEGIN MODULEBUILDER TOPMENU */ - /*$this->menu[$r++] = array( - 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - 'type'=>'top', // This is a Top menu entry - 'titre'=>$langs->trans('GPAO'), - 'mainmenu'=>'gpao', - 'leftmenu'=>'', - 'url'=>'/workstation/workstationindex.php', - 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'position'=>1000 + $r, - 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->workstation->workstation->read' if you want your menu with a permission rules - 'target'=>'', - 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both - );*/ - /* END MODULEBUILDER TOPMENU */ - /* BEGIN MODULEBUILDER LEFTMENU WORKSTATION - $this->menu[$r++]=array( - 'fk_menu'=>'fk_mainmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - 'type'=>'left', // This is a Top menu entry - 'titre'=>'Workstation', - 'mainmenu'=>'workstation', - 'leftmenu'=>'workstation', - 'url'=>'/workstation/workstationindex.php', - 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'position'=>1000+$r, - 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. - 'perms'=>'$user->rights->workstation->workstation->read', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules - 'target'=>'', - 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both - ); - $this->menu[$r++]=array( - 'fk_menu'=>'fk_mainmenu=workstation,fk_leftmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - 'type'=>'left', // This is a Left menu entry - 'titre'=>'List_Workstation', - 'mainmenu'=>'workstation', - 'leftmenu'=>'workstation_workstation_list', - 'url'=>'/workstation/workstation_list.php', - 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'position'=>1000+$r, - 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. - 'perms'=>'$user->rights->workstation->workstation->read', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules - 'target'=>'', - 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both - ); - $this->menu[$r++]=array( - 'fk_menu'=>'fk_mainmenu=workstation,fk_leftmenu=workstation', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - 'type'=>'left', // This is a Left menu entry - 'titre'=>'New_Workstation', - 'mainmenu'=>'workstation', - 'leftmenu'=>'workstation_workstation_new', - 'url'=>'/workstation/workstation_card.php?action=create', - 'langs'=>'workstation@workstation', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'position'=>1000+$r, - 'enabled'=>'$conf->workstation->enabled', // Define condition to show or hide menu entry. Use '$conf->workstation->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. - 'perms'=>'$user->rights->workstation->workstation->write', // Use 'perms'=>'$user->rights->workstation->level1->level2' if you want your menu with a permission rules - 'target'=>'', - 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both - ); - */ - $this->menu[$r++]=array( // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'fk_menu'=>'fk_mainmenu=mrp', // This is a Left menu entry 'type'=>'left', - 'titre'=>$langs->trans('Workstations'), + 'titre'=>'Workstations', 'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth"'), 'mainmenu'=>'mrp', 'leftmenu'=>'workstation_workstation', @@ -350,7 +289,7 @@ class modWorkstation extends DolibarrModules 'fk_menu'=>'fk_mainmenu=mrp,fk_leftmenu=workstation_workstation', // This is a Left menu entry 'type'=>'left', - 'titre'=>$langs->trans('WorkstationCreate'), + 'titre'=>'WorkstationCreate', 'mainmenu'=>'mrp', 'leftmenu'=>'workstation_workstation_left_create', 'url'=>'/workstation/workstation_card.php?action=create', @@ -370,7 +309,7 @@ class modWorkstation extends DolibarrModules 'fk_menu'=>'fk_mainmenu=mrp,fk_leftmenu=workstation_workstation', // This is a Left menu entry 'type'=>'left', - 'titre'=>$langs->trans('List'), + 'titre'=>'List', 'mainmenu'=>'mrp', 'leftmenu'=>'workstation_workstation_left_list', 'url'=>'/workstation/workstation_list.php', diff --git a/htdocs/core/modules/movement/doc/pdf_standard.modules.php b/htdocs/core/modules/movement/doc/pdf_standard.modules.php index c8a0c50862b..872890958ff 100644 --- a/htdocs/core/modules/movement/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/movement/doc/pdf_standard.modules.php @@ -295,7 +295,7 @@ class pdf_stdandard extends ModelePDFMovement $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON m.batch = pl.batch AND m.fk_product = pl.fk_product"; $sql .= " WHERE m.fk_product = p.rowid"; if ($msid > 0) { - $sql .= " AND m.rowid = ".$msid; + $sql .= " AND m.rowid = ".((int) $msid); } $sql .= " AND m.fk_entrepot = e.rowid"; $sql .= " AND e.entity IN (".getEntity('stock').")"; @@ -303,13 +303,13 @@ class pdf_stdandard extends ModelePDFMovement $sql .= " AND p.fk_product_type = 0"; } if ($id > 0) { - $sql .= " AND e.rowid ='".$id."'"; + $sql .= " AND e.rowid = ".((int) $id); } if ($month > 0) { if ($year > 0) { $sql .= " AND m.datem BETWEEN '".$this->db->idate(dol_get_first_day($year, $month, false))."' AND '".$this->db->idate(dol_get_last_day($year, $month, false))."'"; } else { - $sql .= " AND date_format(m.datem, '%m') = '$month'"; + $sql .= " AND date_format(m.datem, '%m') = '".((int) $month)."'"; } } elseif ($year > 0) { $sql .= " AND m.datem BETWEEN '".$this->db->idate(dol_get_first_day($year, 1, false))."' AND '".$this->db->idate(dol_get_last_day($year, 12, false))."'"; @@ -529,8 +529,8 @@ class pdf_stdandard extends ModelePDFMovement if (!empty($conf->global->MAIN_MULTILANGS)) { // si l'option est active $sql = "SELECT label"; $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; - $sql .= " WHERE fk_product=".$objp->rowid; - $sql .= " AND lang='".$this->db->escape($langs->getDefaultLang())."'"; + $sql .= " WHERE fk_product = ".((int) $objp->rowid); + $sql .= " AND lang = '".$this->db->escape($langs->getDefaultLang())."'"; $sql .= " LIMIT 1"; $result = $this->db->query($sql); @@ -1158,7 +1158,7 @@ class pdf_stdandard extends ModelePDFMovement $pdf->SetTextColor(0,0,0); $pdf->SetFont('','', $default_font_size - 2); $pdf->SetXY($posx,$posy-5); - $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx,$posy); $pdf->SetFillColor(230,230,230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); diff --git a/htdocs/core/modules/product/doc/pdf_standard.modules.php b/htdocs/core/modules/product/doc/pdf_standard.modules.php index 72eaae364a5..99b6ff69236 100644 --- a/htdocs/core/modules/product/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/product/doc/pdf_standard.modules.php @@ -815,7 +815,7 @@ class pdf_standard extends ModelePDFProduct $pdf->SetTextColor(0,0,0); $pdf->SetFont('','', $default_font_size - 2); $pdf->SetXY($posx,$posy-5); - $pdf->MultiCell(66,5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx,$posy); $pdf->SetFillColor(230,230,230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); diff --git a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php index d007b421fd7..da95e841728 100644 --- a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php +++ b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php @@ -742,7 +742,7 @@ class doc_generic_project_odt extends ModelePDFProjects $sql .= ", u.lastname, u.firstname, t.thm"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql .= " , ".MAIN_DB_PREFIX."user as u"; - $sql .= " WHERE t.fk_task =".$task->id; + $sql .= " WHERE t.fk_task =".((int) $task->id); $sql .= " AND t.fk_user = u.rowid"; $sql .= " ORDER BY t.task_date DESC"; diff --git a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php index 2d263aae6c0..0662e1a5a76 100644 --- a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php +++ b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php @@ -657,7 +657,7 @@ class doc_generic_task_odt extends ModelePDFTask $sql .= ", u.lastname, u.firstname"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql .= " , ".MAIN_DB_PREFIX."user as u"; - $sql .= " WHERE t.fk_task =".$object->id; + $sql .= " WHERE t.fk_task =".((int) $object->id); $sql .= " AND t.fk_user = u.rowid"; $sql .= " ORDER BY t.task_date DESC"; diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 15de98e9a58..b56fbc758db 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -1419,6 +1419,9 @@ class pdf_azur extends ModelePDFPropales { global $conf, $langs; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "propal", "companies", "bills")); @@ -1462,7 +1465,7 @@ class pdf_azur extends ModelePDFPropales } } else { $text = $this->emetteur->name; - $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } } @@ -1513,7 +1516,7 @@ class pdf_azur extends ModelePDFPropales $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DatePropal")." : ".dol_print_date($object->date, "day", false, $outputlangs, true), '', 'R'); $posy += 4; $pdf->SetXY($posx, $posy); @@ -1575,7 +1578,7 @@ class pdf_azur extends ModelePDFPropales $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1584,13 +1587,13 @@ class pdf_azur extends ModelePDFPropales // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection); // If CUSTOMER contact defined, we use it @@ -1628,20 +1631,20 @@ class pdf_azur extends ModelePDFPropales $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index b7e44c6c4d5..f75f5ecab56 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -434,13 +434,12 @@ class pdf_cyan extends ModelePDFPropales if (!empty($conf->global->MAIN_ADD_CREATOR_IN_NOTE) && $object->user_author_id > 0) { $tmpuser = new User($this->db); $tmpuser->fetch($object->user_author_id); - $notetoshow .= $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs); - if ($tmpuser->email) { - $notetoshow .= ', Mail: '.$tmpuser->email; - } - if ($tmpuser->office_phone) { - $notetoshow .= ', Tel: '.$tmpuser->office_phone; - } + + $creator_info = $langs->trans("CaseFollowedBy").' '.$tmpuser->getFullName($langs); + if ($tmpuser->email) $creator_info .= ', '.$langs->trans("EMail").': '.$tmpuser->email; + if ($tmpuser->office_phone) $creator_info .= ', '.$langs->trans("Phone").': '.$tmpuser->office_phone; + + $notetoshow = dol_concatdesc($notetoshow, $creator_info); } $tab_height = $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter; @@ -1519,6 +1518,9 @@ class pdf_cyan extends ModelePDFPropales { global $conf, $langs; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "propal", "companies", "bills")); @@ -1564,7 +1566,7 @@ class pdf_cyan extends ModelePDFPropales } } else { $text = $this->emetteur->name; - $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } } @@ -1690,7 +1692,7 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -1699,13 +1701,13 @@ class pdf_cyan extends ModelePDFPropales // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, $ltrdirection); // If CUSTOMER contact defined, we use it @@ -1744,20 +1746,20 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } $pdf->SetTextColor(0, 0, 0); diff --git a/htdocs/core/modules/rapport/pdf_paiement.class.php b/htdocs/core/modules/rapport/pdf_paiement.class.php index b69ebdeb828..9f85aca1aff 100644 --- a/htdocs/core/modules/rapport/pdf_paiement.class.php +++ b/htdocs/core/modules/rapport/pdf_paiement.class.php @@ -209,7 +209,7 @@ class pdf_paiement $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; } if (!empty($socid)) { - $sql .= " AND s.rowid = ".$socid; + $sql .= " AND s.rowid = ".((int) $socid); } // If global param PAYMENTS_REPORT_GROUP_BY_MOD is set, payement are ordered by paiement_code if (!empty($conf->global->PAYMENTS_REPORT_GROUP_BY_MOD)) { diff --git a/htdocs/core/modules/reception/doc/pdf_squille.modules.php b/htdocs/core/modules/reception/doc/pdf_squille.modules.php index c9a2b397e17..0e4474b6b8c 100644 --- a/htdocs/core/modules/reception/doc/pdf_squille.modules.php +++ b/htdocs/core/modules/reception/doc/pdf_squille.modules.php @@ -388,6 +388,18 @@ class pdf_squille extends ModelePdfReception // Description of product line $curX = $this->posxdesc - 1; + // The desc of line is not store into reception, so we force it to the value of product. + /* + if (empty($object->lines[0]->desc)) { + // TODO We must get value from fk_commendefourndet + $sqldesc = 'SELECT description FROM '.MAIN_DB_PREFIX.' WHERE rowid = '.((int) $object->lines[0]->fk_commandefourndet); + $resqldesc = $this->db->query($sqldesc); + if ($resqldesc) { + $objdesc = $this->db->fetch_object($resqldesc); + $object->lines[0]->desc = $objdesc->description; + } + }*/ + $pdf->startTransaction(); pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX, 3, $curX, $curY, $hideref, $hidedesc); @@ -934,7 +946,7 @@ class pdf_squille extends ModelePdfReception $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("Sender").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Sender"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); @@ -988,7 +1000,7 @@ class pdf_squille extends ModelePdfReception $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); diff --git a/htdocs/core/modules/societe/mod_codeclient_elephant.php b/htdocs/core/modules/societe/mod_codeclient_elephant.php index d789f4f0d85..9ddf77abe44 100644 --- a/htdocs/core/modules/societe/mod_codeclient_elephant.php +++ b/htdocs/core/modules/societe/mod_codeclient_elephant.php @@ -348,6 +348,7 @@ class mod_codeclient_elephant extends ModeleThirdPartyCode if ($soc->id > 0) { $sql .= " AND rowid <> ".$soc->id; } + $sql .= " AND entity IN (".getEntity('societe').")"; $resql = $db->query($sql); if ($resql) { diff --git a/htdocs/core/modules/societe/mod_codecompta_digitaria.php b/htdocs/core/modules/societe/mod_codecompta_digitaria.php index 363d3984516..56c5b8e8885 100644 --- a/htdocs/core/modules/societe/mod_codecompta_digitaria.php +++ b/htdocs/core/modules/societe/mod_codecompta_digitaria.php @@ -207,7 +207,7 @@ class mod_codecompta_digitaria extends ModeleAccountancyCode if (!isset($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE) || !empty($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE)) { $disponibility = $this->checkIfAccountancyCodeIsAlreadyUsed($db, $this->code, $type); - while ($disponibility <> 0 && $i < 100) { + while ($disponibility <> 0 && $i < 1000) { $widthsupplier = $this->supplieraccountancycodecharacternumber; $widthcustomer = $this->customeraccountancycodecharacternumber; @@ -217,6 +217,9 @@ class mod_codecompta_digitaria extends ModeleAccountancyCode if ($i >= 10 && $i <= 99) { $a = 2; } + if ($i >= 100 && $i <= 999) { + $a = 3; + } if ($type == 'supplier') { $this->code = $prefix.strtoupper(substr($codetouse, 0, $widthsupplier - $a)).$i; diff --git a/htdocs/core/modules/stock/doc/pdf_standard.modules.php b/htdocs/core/modules/stock/doc/pdf_standard.modules.php index a57b996086b..b0cc07dcb62 100644 --- a/htdocs/core/modules/stock/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/stock/doc/pdf_standard.modules.php @@ -315,7 +315,7 @@ class pdf_standard extends ModelePDFStock $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product as p"; $sql .= " WHERE ps.fk_product = p.rowid"; $sql .= " AND ps.reel <> 0"; // We do not show if stock is 0 (no product in this warehouse) - $sql .= " AND ps.fk_entrepot = ".$object->id; + $sql .= " AND ps.fk_entrepot = ".((int) $object->id); $sql .= $this->db->order($sortfield, $sortorder); //dol_syslog('List products', LOG_DEBUG); diff --git a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php index b9c40645544..08345647b0f 100644 --- a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php +++ b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php @@ -2,7 +2,7 @@ /* Copyright (C) 2010-2011 Juanjo Menent * Copyright (C) 2010-2014 Laurent Destailleur * Copyright (C) 2015 Marcos García - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -376,7 +376,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($object->note_public), 0, 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1); $nexY = $pdf->GetY(); $height_note = $nexY - $tab_top; @@ -1062,7 +1062,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices * @param FactureFournisseur $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output - * @return void + * @return int */ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { @@ -1211,7 +1211,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1264,7 +1264,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name diff --git a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php index f2f75031d3b..245897e1956 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php @@ -231,17 +231,24 @@ class pdf_cornas extends ModelePDFSuppliersOrders $objphoto->fetch($object->lines[$i]->fk_product); if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { - $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; + $pdir = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; $dir = $conf->product->dir_output.'/'.$pdir; } else { - $pdir = get_exdir(0, 2, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/'; + $pdir = get_exdir($objphoto->id, 0, 0, 0, $objphoto, 'product'); $dir = $conf->product->dir_output.'/'.$pdir; } $realpath = ''; foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { - $filename = $obj['photo']; - //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette']; + if (empty($conf->global->CAT_HIGH_QUALITY_IMAGES)) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo + if ($obj['photo_vignette']) { + $filename = $obj['photo_vignette']; + } else { + $filename = $obj['photo']; + } + } else { + $filename = $obj['photo']; + } $realpath = $dir.$filename; break; } @@ -1211,6 +1218,9 @@ class pdf_cornas extends ModelePDFSuppliersOrders { global $langs, $conf, $mysoc; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load translation files required by the page $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "sendings")); @@ -1248,7 +1258,7 @@ class pdf_cornas extends ModelePDFSuppliersOrders } } else { $text = $this->emetteur->name; - $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } $pdf->SetFont('', 'B', $default_font_size + 3); @@ -1369,7 +1379,7 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1378,13 +1388,13 @@ class pdf_cornas extends ModelePDFSuppliersOrders // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection); @@ -1422,20 +1432,20 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } return $top_shift; diff --git a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php index de283265931..bb12b19c829 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php @@ -246,17 +246,23 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $objphoto->fetch($object->lines[$i]->fk_product); if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { - $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; + $pdir = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; $dir = $conf->product->dir_output.'/'.$pdir; } else { - $pdir = get_exdir(0, 2, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/'; + $pdir = get_exdir($objphoto->id, 0, 0, 0, $objphoto, 'product'); $dir = $conf->product->dir_output.'/'.$pdir; } - $realpath = ''; foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { - $filename = $obj['photo']; - //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette']; + if (empty($conf->global->CAT_HIGH_QUALITY_IMAGES)) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo + if ($obj['photo_vignette']) { + $filename = $obj['photo_vignette']; + } else { + $filename = $obj['photo']; + } + } else { + $filename = $obj['photo']; + } $realpath = $dir.$filename; break; } @@ -1120,6 +1126,9 @@ class pdf_muscadet extends ModelePDFSuppliersOrders { global $langs, $conf, $mysoc; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load translation files required by the page $outputlangs->loadLangs(array("main", "orders", "companies", "bills", "sendings")); @@ -1157,7 +1166,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders } } else { $text = $this->emetteur->name; - $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } $pdf->SetFont('', 'B', $default_font_size + 3); @@ -1278,7 +1287,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, $ltrdirection); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1287,13 +1296,13 @@ class pdf_muscadet extends ModelePDFSuppliersOrders // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, $ltrdirection); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, $ltrdirection); // If CUSTOMER contact defined on order, we use it. Note: Even if this is a supplier object, the code for external contat that follow order is 'CUSTOMER' @@ -1330,20 +1339,20 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, $ltrdirection); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, $ltrdirection); $posy = $pdf->getY(); // Show recipient information $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx + 2, $posy); - $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection); } return $top_shift; diff --git a/htdocs/core/modules/supplier_payment/doc/pdf_standard.modules.php b/htdocs/core/modules/supplier_payment/doc/pdf_standard.modules.php index 138a6210904..b6da2d4c294 100644 --- a/htdocs/core/modules/supplier_payment/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/supplier_payment/doc/pdf_standard.modules.php @@ -220,7 +220,7 @@ class pdf_standard extends ModelePDFSuppliersPayments $sql .= ', f.fk_statut, s.nom as name, s.rowid as socid'; $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf,'.MAIN_DB_PREFIX.'facture_fourn as f,'.MAIN_DB_PREFIX.'societe as s'; $sql .= ' WHERE pf.fk_facturefourn = f.rowid AND f.fk_soc = s.rowid'; - $sql .= ' AND pf.fk_paiementfourn = '.$object->id; + $sql .= ' AND pf.fk_paiementfourn = '.((int) $object->id); $resql = $this->db->query($sql); if ($resql) { if ($this->db->num_rows($resql) > 0) { @@ -757,7 +757,7 @@ class pdf_standard extends ModelePDFSuppliersPayments $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("PayedBy").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("PayedBy"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -798,7 +798,7 @@ class pdf_standard extends ModelePDFSuppliersPayments $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("PayedTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("PayedTo"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index 356c3550100..cbcec7cfdd9 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -245,14 +245,21 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/"; $dir = $conf->product->dir_output.'/'.$pdir; } else { - $pdir = get_exdir(0, 2, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/'; + $pdir = get_exdir(0, 0, 0, 0, $objphoto, 'product'); $dir = $conf->product->dir_output.'/'.$pdir; } $realpath = ''; foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) { - $filename = $obj['photo']; - //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette']; + if (empty($conf->global->CAT_HIGH_QUALITY_IMAGES)) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo + if ($obj['photo_vignette']) { + $filename = $obj['photo_vignette']; + } else { + $filename = $obj['photo']; + } + } else { + $filename = $obj['photo']; + } $realpath = $dir.$filename; break; } @@ -1383,7 +1390,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx, $posy - 5); - $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); + $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); @@ -1439,7 +1446,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdf->SetTextColor(0, 0, 0); $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posx + 2, $posy - 5); - $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":", 0, 'L'); + $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo"), 0, 'L'); $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre); // Show recipient name diff --git a/htdocs/core/modules/workstation/mod_workstation_standard.php b/htdocs/core/modules/workstation/mod_workstation_standard.php index 34e727dd272..7bef21a8599 100755 --- a/htdocs/core/modules/workstation/mod_workstation_standard.php +++ b/htdocs/core/modules/workstation/mod_workstation_standard.php @@ -36,7 +36,7 @@ class mod_workstation_standard extends ModeleNumRefWorkstation */ public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' - public $prefix = 'WORKSTATION'; + public $prefix = 'WKSTATION'; /** * @var string Error code (or message) @@ -57,7 +57,7 @@ class mod_workstation_standard extends ModeleNumRefWorkstation public function info() { global $langs; - return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + return $langs->trans("SimpleNumRefNoDateModelDesc", $this->prefix); } @@ -68,7 +68,7 @@ class mod_workstation_standard extends ModeleNumRefWorkstation */ public function getExample() { - return $this->prefix."0501-0001"; + return $this->prefix."-0001"; } @@ -83,13 +83,12 @@ class mod_workstation_standard extends ModeleNumRefWorkstation { global $conf, $langs, $db; - $coyymm = ''; $max = ''; - $posindice = strlen($this->prefix) + 6; + $posindice = strlen($this->prefix) + 2; $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql .= " FROM ".MAIN_DB_PREFIX."workstation_workstation"; - $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."-%'"; if ($object->ismultientitymanaged == 1) { $sql .= " AND entity = ".$conf->entity; } elseif ($object->ismultientitymanaged == 2) { @@ -100,15 +99,14 @@ class mod_workstation_standard extends ModeleNumRefWorkstation if ($resql) { $row = $db->fetch_row($resql); if ($row) { - $coyymm = substr($row[0], 0, 6); $max = $row[0]; } } - if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { + /*if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { $langs->load("errors"); $this->error = $langs->trans('ErrorNumRefModel', $max); return false; - } + }*/ return true; } @@ -124,10 +122,10 @@ class mod_workstation_standard extends ModeleNumRefWorkstation global $db, $conf; // First we get the max value - $posindice = strlen($this->prefix) + 6; + $posindice = strlen($this->prefix) + 2; $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql .= " FROM ".MAIN_DB_PREFIX."workstation_workstation"; - $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."-%'"; //$sql .= " AND entity = ".$conf->entity; $resql = $db->query($sql); @@ -143,17 +141,13 @@ class mod_workstation_standard extends ModeleNumRefWorkstation return -1; } - //$date=time(); - $date = dol_now(); - $yymm = strftime("%y%m", $date); - if ($max >= (pow(10, 4) - 1)) { $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is } else { $num = sprintf("%04s", $max + 1); } - dol_syslog("mod_workstation_standard::getNextValue return ".$this->prefix.$yymm."-".$num); - return $this->prefix.$yymm."-".$num; + dol_syslog("mod_workstation_standard::getNextValue return ".$this->prefix."-".$num); + return $this->prefix."-".$num; } } diff --git a/htdocs/core/photos_resize.php b/htdocs/core/photos_resize.php index b3079691cd5..7c7813fbe14 100644 --- a/htdocs/core/photos_resize.php +++ b/htdocs/core/photos_resize.php @@ -487,8 +487,10 @@ print load_fiche_titre($title); $infoarray = dol_getImageSize($dir."/".GETPOST("file", 'alpha')); $height = $infoarray['height']; $width = $infoarray['width']; -print ''.$langs->trans("CurrentInformationOnImage").': '; -print $langs->trans("Width").': '.$width.' x '.$langs->trans("Height").': '.$height.'
    '; +print ''.$langs->trans("CurrentInformationOnImage").': '; +print ''; +print $langs->trans("Width").': '.$width.' x '.$langs->trans("Height").': '.$height.''; +print '
    '; print '
    '."\n"; @@ -546,36 +548,42 @@ if (!empty($conf->use_javascript_ajax)) { print ''.$langs->trans("Recenter").''; print $langs->trans("DefineNewAreaToPick").'...
    '; print '
    '; - print '
    '; - print ''; - print '
    '; - print '

    '; - print '
    '; - print ''; - print ' -
    - '.$langs->trans("NewSizeAfterCropping").': - - - - - - -
    + if (empty($conf->dol_no_mouse_hover)) { + print '
    '; + print ''; + print '
    '; + print '

    '; - - - - - - - -
    - -   - - '."\n"; + print '
    '; + print ''; + print ' +
    + '.$langs->trans("NewSizeAfterCropping").': + + + + + + +
    + + + + + + + + +
    + +   + +
    '."\n"; + } else { + $langs->load("other"); + print '
    '.$langs->trans("FeatureNotAvailableOnDevicesWithoutMouse").'
    '; + } print ''."\n"; print '
    '; } diff --git a/htdocs/core/tpl/admin_extrafields_view.tpl.php b/htdocs/core/tpl/admin_extrafields_view.tpl.php index c4a21812b01..284407383d4 100644 --- a/htdocs/core/tpl/admin_extrafields_view.tpl.php +++ b/htdocs/core/tpl/admin_extrafields_view.tpl.php @@ -115,12 +115,14 @@ if (isset($extrafields->attributes[$elementtype]['type']) && is_array($extrafiel } print '
    '.img_edit().''; - print '  '.img_delete().''; + print ''.img_edit().''; + print '  '.img_delete().''; + print '
    '; - print ' '.$langs->trans("ECMSections"); + print ''.$langs->trans("ECMSections").''; print '
    '; if ($module == 'medias') { print $langs->trans("RootOfMedias"); } else { diff --git a/htdocs/core/tpl/list_print_total.tpl.php b/htdocs/core/tpl/list_print_total.tpl.php index d7252f891ae..62052b82cec 100644 --- a/htdocs/core/tpl/list_print_total.tpl.php +++ b/htdocs/core/tpl/list_print_total.tpl.php @@ -1,6 +1,6 @@ $valtotalizable) { $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable; $totalarray['val'][$keytotalizable] = $valtotalizable['total']; diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index b5dc9b90be0..9af5bc7d7b4 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -180,7 +180,7 @@ if ($disablenofollow) { } ?> -" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" autofocus="autofocus" /> +" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" autofocus="autofocus" />
    @@ -192,7 +192,7 @@ if ($disablenofollow) { } ?> -" name="password" class="flat input-icon-password minwidth150" type="password" value="" tabindex="2" autocomplete="global->MAIN_LOGIN_ENABLE_PASSWORD_AUTOCOMPLETE) ? 'off' : 'on'; ?>" /> +" name="password" class="flat input-icon-password minwidth150" value="" tabindex="2" autocomplete="global->MAIN_LOGIN_ENABLE_PASSWORD_AUTOCOMPLETE) ? 'off' : 'on'; ?>" /> fetch($thirdpartyid); $liste['thirdparty'] = $fuser->getFullName($langs)." <".$fuser->email.">"; + } elseif ($objecttmp->element == 'partnership' && $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') { + $fadherent = new Adherent($db); + $fadherent->fetch($objecttmp->fk_member); + $liste['member'] = $fadherent->getFullName($langs)." <".$fadherent->email.">"; } else { $soc = new Societe($db); $soc->fetch($thirdpartyid); @@ -145,7 +149,7 @@ if ($massaction == 'presend') { $formmail->withtofree = empty($liste) ? 1 : 0; $formmail->withtocc = 1; $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; - $formmail->withtopic = $langs->transnoentities($topicmail, '__REF__', '__REFCLIENT__'); + $formmail->withtopic = $langs->transnoentities($topicmail, '__REF__', '__REF_CLIENT__'); $formmail->withfile = 1; // $formmail->withfile = 2; Not yet supported in mass action $formmail->withmaindocfile = 1; // Add a checkbox "Attach also main document" @@ -161,7 +165,7 @@ if ($massaction == 'presend') { $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); $substitutionarray['__EMAIL__'] = $sendto; - $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; + $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; $substitutionarray['__PERSONALIZED__'] = ''; // deprecated $substitutionarray['__CONTACTCIVNAME__'] = ''; diff --git a/htdocs/core/tpl/onlinepaymentlinks.tpl.php b/htdocs/core/tpl/onlinepaymentlinks.tpl.php index c4b2ad5e3e4..06d93e5ea5f 100644 --- a/htdocs/core/tpl/onlinepaymentlinks.tpl.php +++ b/htdocs/core/tpl/onlinepaymentlinks.tpl.php @@ -27,11 +27,12 @@ print ''; // Url list print ''.$langs->trans("FollowingUrlAreAvailableToMakePayments").':

    '; -print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnFreeAmount", $servicename).':
    '; +print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnFreeAmount", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'free')."

    \n"; + if (!empty($conf->commande->enabled)) { print '
    '; - print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnOrder", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnOrder", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'order')."
    \n"; if (!empty($conf->global->PAYMENT_SECURITY_TOKEN) && !empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { $langs->load("orders"); @@ -40,7 +41,7 @@ if (!empty($conf->commande->enabled)) { print $langs->trans("EnterRefToBuildUrl", $langs->transnoentitiesnoconv("Order")).': '; print ''; - print ''; + print ''; if (GETPOST('generate_order_ref', 'alpha')) { print '
    -> '; $url = getOnlinePaymentUrl(0, 'order', GETPOST('generate_order_ref', 'alpha')); @@ -53,7 +54,7 @@ if (!empty($conf->commande->enabled)) { } if (!empty($conf->facture->enabled)) { print '
    '; - print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnInvoice", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnInvoice", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'invoice')."
    \n"; if (!empty($conf->global->PAYMENT_SECURITY_TOKEN) && !empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { $langs->load("bills"); @@ -62,7 +63,7 @@ if (!empty($conf->facture->enabled)) { print $langs->trans("EnterRefToBuildUrl", $langs->transnoentitiesnoconv("Invoice")).': '; print ''; - print ''; + print ''; if (GETPOST('generate_invoice_ref', 'alpha')) { print '
    -> '; $url = getOnlinePaymentUrl(0, 'invoice', GETPOST('generate_invoice_ref', 'alpha')); @@ -75,7 +76,7 @@ if (!empty($conf->facture->enabled)) { } if (!empty($conf->contrat->enabled)) { print '
    '; - print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnContractLine", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnContractLine", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'contractline')."
    \n"; if (!empty($conf->global->PAYMENT_SECURITY_TOKEN) && !empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { $langs->load("contracts"); @@ -84,7 +85,7 @@ if (!empty($conf->contrat->enabled)) { print $langs->trans("EnterRefToBuildUrl", $langs->transnoentitiesnoconv("ContractLine")).': '; print ''; - print ''; + print ''; if (GETPOST('generate_contract_ref')) { print '
    -> '; $url = getOnlinePaymentUrl(0, 'contractline', GETPOST('generate_contract_ref', 'alpha')); @@ -97,7 +98,7 @@ if (!empty($conf->contrat->enabled)) { } if (!empty($conf->adherent->enabled)) { print '
    '; - print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnMemberSubscription", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnMemberSubscription", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'membersubscription')."
    \n"; if (!empty($conf->global->PAYMENT_SECURITY_TOKEN) && !empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { $langs->load("members"); @@ -106,7 +107,7 @@ if (!empty($conf->adherent->enabled)) { print $langs->trans("EnterRefToBuildUrl", $langs->transnoentitiesnoconv("Member")).': '; print ''; - print ''; + print ''; if (GETPOST('generate_member_ref')) { print '
    -> '; $url = getOnlinePaymentUrl(0, 'membersubscription', GETPOST('generate_member_ref', 'alpha')); @@ -119,7 +120,7 @@ if (!empty($conf->adherent->enabled)) { } if (!empty($conf->don->enabled)) { print '
    '; - print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnDonation", $servicename).':
    '; + print img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForOnlinePaymentOnDonation", $servicename).':
    '; print ''.getOnlinePaymentUrl(1, 'donation')."
    \n"; if (!empty($conf->global->PAYMENT_SECURITY_TOKEN) && !empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { $langs->load("members"); @@ -128,7 +129,7 @@ if (!empty($conf->don->enabled)) { print $langs->trans("EnterRefToBuildUrl", $langs->transnoentitiesnoconv("Don")).': '; print ''; - print ''; + print ''; if (GETPOST('generate_donation_ref')) { print '
    -> '; $url = getOnlinePaymentUrl(0, 'donation', GETPOST('generate_donation_ref', 'alpha')); diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index 3e2fb78bdb0..6e890f06e80 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -129,7 +129,7 @@ if (!empty($disablenofollow)) {
    -" id="username" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" /> +" id="username" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" />
    diff --git a/htdocs/core/tpl/resource_view.tpl.php b/htdocs/core/tpl/resource_view.tpl.php index 81ad11ebdc9..740590cb34a 100644 --- a/htdocs/core/tpl/resource_view.tpl.php +++ b/htdocs/core/tpl/resource_view.tpl.php @@ -33,7 +33,7 @@ if ((array) $linked_resources && count($linked_resources) > 0) { //$element_id = $linked_resource['rowid']; - if ($mode == 'edit' && $linked_resource['rowid'] == GETPOST('lineid')) { + if ($mode == 'edit' && $linked_resource['rowid'] == GETPOST('lineid', 'int')) { print '
    '; print ''; print ''; @@ -47,7 +47,7 @@ if ((array) $linked_resources && count($linked_resources) > 0) { print '
    '; } else { $class = ''; - if ($linked_resource['rowid'] == GETPOST('lineid')) { + if ($linked_resource['rowid'] == GETPOST('lineid', 'int')) { $class = 'highlight'; } diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index 7f7cd5a77be..8e23c258d88 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -108,6 +108,17 @@ class InterfaceActionsAuto extends DolibarrTriggers } $object->actionmsg = $langs->transnoentities("NewCompanyToDolibarr", $object->name); + $object->sendtoid = 0; + $object->socid = $object->id; + } elseif ($action == 'COMPANY_MODIFY') { + // Load translation files required by the page + $langs->loadLangs(array("agenda", "other", "companies")); + + if (empty($object->actionmsg2)) { + $object->actionmsg2 = $langs->transnoentities("COMPANY_MODIFYInDolibarr", $object->name); + } + $object->actionmsg = $langs->transnoentities("COMPANY_MODIFYInDolibarr", $object->name); + $object->sendtoid = 0; $object->socid = $object->id; } elseif ($action == 'COMPANY_SENTBYMAIL') { @@ -129,6 +140,17 @@ class InterfaceActionsAuto extends DolibarrTriggers } $object->actionmsg = $langs->transnoentities("CONTACT_CREATEInDolibarr", $object->getFullName($langs)); + $object->sendtoid = array($object->id => $object->id); + $object->socid = $object->socid; + } elseif ($action == 'CONTACT_MODIFY') { + // Load translation files required by the page + $langs->loadLangs(array("agenda", "other", "companies")); + + if (empty($object->actionmsg2)) { + $object->actionmsg2 = $langs->transnoentities("CONTACT_MODIFYInDolibarr", $object->name); + } + $object->actionmsg = $langs->transnoentities("CONTACT_MODIFYInDolibarr", $object->name); + $object->sendtoid = array($object->id => $object->id); $object->socid = $object->socid; } elseif ($action == 'CONTRACT_VALIDATE') { @@ -522,13 +544,18 @@ class InterfaceActionsAuto extends DolibarrTriggers $object->sendtoid = 0; } elseif ($action == 'ORDER_SUPPLIER_REFUSE') { // Load translation files required by the page - $langs->loadLangs(array("agenda", "other", "orders")); + $langs->loadLangs(array("agenda", "other", "orders", "main")); if (empty($object->actionmsg2)) { $object->actionmsg2 = $langs->transnoentities("OrderRefusedInDolibarr", $object->ref); } $object->actionmsg = $langs->transnoentities("OrderRefusedInDolibarr", $object->ref); + if (!empty($object->refuse_note)) { + $object->actionmsg .= '
    '; + $object->actionmsg .= $langs->trans("Reason") . ': '.$object->refuse_note; + } + $object->sendtoid = 0; } elseif ($action == 'ORDER_SUPPLIER_SUBMIT') { // Load translation files required by the page diff --git a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php index b8454b80ea1..d4db5ebccfc 100644 --- a/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php +++ b/htdocs/core/triggers/interface_50_modLdap_Ldapsynchro.class.php @@ -125,6 +125,50 @@ class InterfaceLdapsynchro extends DolibarrTriggers $newparent = $object->_load_ldap_dn($info, 1); $result = $ldap->update($dn, $info, $user, $olddn, $newrdn, $newparent); + + if ($result > 0 && !empty($object->context['newgroupid'])) { // We are in context of adding a new group to user + $usergroup = new Usergroup($this->db); + + $usergroup->fetch($object->context['newgroupid']); + + $oldinfo = $usergroup->_load_ldap_info(); + $olddn = $usergroup->_load_ldap_dn($oldinfo); + + // Verify if entry exist + $container = $usergroup->_load_ldap_dn($oldinfo, 1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")"; + $records = $ldap->search($container, $search); + if (count($records) && $records['count'] == 0) { + $olddn = ''; + } + + $info = $usergroup->_load_ldap_info(); // Contains all members, included the new one (insert already done before trigger call) + $dn = $usergroup->_load_ldap_dn($info); + + $result = $ldap->update($dn, $info, $user, $olddn); + } + + if ($result > 0 && !empty($object->context['oldgroupid'])) { // We are in context of removing a group from user + $usergroup = new Usergroup($this->db); + + $usergroup->fetch($object->context['oldgroupid']); + + $oldinfo = $usergroup->_load_ldap_info(); + $olddn = $usergroup->_load_ldap_dn($oldinfo); + + // Verify if an entry exists + $container = $usergroup->_load_ldap_dn($oldinfo, 1); + $search = "(".$usergroup->_load_ldap_dn($oldinfo, 2).")"; + $records = $ldap->search($container, $search); + if (count($records) && $records['count'] == 0) { + $olddn = ''; + } + + $info = $usergroup->_load_ldap_info(); // Contains all members, except the old one (remove already done before trigger call) + $dn = $usergroup->_load_ldap_dn($info); + + $result = $ldap->update($dn, $info, $user, $olddn); + } } if ($result < 0) { @@ -183,7 +227,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers $this->error = "ErrorLDAP ".$ldap->error; } } - } elseif ($action == 'USER_SETINGROUP') { + /*} elseif ($action == 'USER_SETINGROUP') { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); if (!empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') { $ldap = new Ldap(); @@ -217,7 +261,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers $this->error = "ErrorLDAP ".$ldap->error; } } - } elseif ($action == 'USER_REMOVEFROMGROUP') { + } elseif ($action == 'USER_REMOVEFROMGROUP') { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); if (!empty($conf->global->LDAP_SYNCHRO_ACTIVE) && $conf->global->LDAP_SYNCHRO_ACTIVE === 'dolibarr2ldap') { $ldap = new Ldap(); @@ -250,7 +294,7 @@ class InterfaceLdapsynchro extends DolibarrTriggers if ($result < 0) { $this->error = "ErrorLDAP ".$ldap->error; } - } + } */ } elseif ($action == 'USERGROUP_CREATE') { // Groupes dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); @@ -262,8 +306,8 @@ class InterfaceLdapsynchro extends DolibarrTriggers $info = $object->_load_ldap_info(); $dn = $object->_load_ldap_dn($info); - // Get a gid number for objectclass PosixGroup - if (in_array('posixGroup', $info['objectclass'])) { + // Get a gid number for objectclass PosixGroup if none was provided + if (empty($info[$conf->global->LDAP_GROUP_FIELD_GROUPID]) && in_array('posixGroup', $info['objectclass'])) { $info['gidNumber'] = $ldap->getNextGroupGid('LDAP_KEY_GROUPS'); } diff --git a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php index 69903ce45f3..7d315f142a7 100644 --- a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php +++ b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php @@ -34,6 +34,7 @@ class InterfaceNotification extends DolibarrTriggers public $listofmanagedevents = array( 'BILL_VALIDATE', 'BILL_PAYED', + 'ORDER_CREATE', 'ORDER_VALIDATE', 'PROPAL_VALIDATE', 'PROPAL_CLOSE_SIGNED', @@ -128,7 +129,7 @@ class InterfaceNotification extends DolibarrTriggers } // Check if module for this event is active if ($qualified) { - //print 'xx'.$obj->code; + //print 'xx'.$obj->code.' '.$obj->elementtype.'
    '; $element = $obj->elementtype; // Exclude events if related module is disabled @@ -142,7 +143,9 @@ class InterfaceNotification extends DolibarrTriggers $qualified = 0; } elseif ($element == 'member' && empty($conf->adherent->enabled)) { $qualified = 0; - } elseif (!in_array($element, array('order_supplier', 'invoice_supplier', 'withdraw', 'shipping', 'member', 'expensereport')) && empty($conf->$element->enabled)) { + } elseif (($element == 'expense_report' || $element == 'expensereport') && empty($conf->expensereport->enabled)) { + $qualified = 0; + } elseif (!in_array($element, array('order_supplier', 'invoice_supplier', 'withdraw', 'shipping', 'member', 'expense_report', 'expensereport')) && empty($conf->$element->enabled)) { $qualified = 0; } } diff --git a/htdocs/core/triggers/interface_99_modZapier_ZapierTriggers.class.php b/htdocs/core/triggers/interface_99_modZapier_ZapierTriggers.class.php index f2d77553827..8025f0c0293 100644 --- a/htdocs/core/triggers/interface_99_modZapier_ZapierTriggers.class.php +++ b/htdocs/core/triggers/interface_99_modZapier_ZapierTriggers.class.php @@ -111,13 +111,9 @@ class InterfaceZapierTriggers extends DolibarrTriggers //case 'USER_NEW_PASSWORD': //case 'USER_ENABLEDISABLE': //case 'USER_DELETE': - //case 'USER_SETINGROUP': - //case 'USER_REMOVEFROMGROUP': - // case 'USER_LOGIN': - // case 'USER_LOGIN_FAILED': - // case 'USER_LOGOUT': - // Warning: To increase performances, this action is triggered only if constant MAIN_ACTIVATE_UPDATESESSIONTRIGGER is set to 1. - // // case 'USER_UPDATE_SESSION': + //case 'USER_LOGIN': + //case 'USER_LOGIN_FAILED': + //case 'USER_LOGOUT': // Actions case 'ACTION_MODIFY': @@ -178,8 +174,27 @@ class InterfaceZapierTriggers extends DolibarrTriggers // Contacts case 'CONTACT_CREATE': + $resql = $this->db->query($sql); + while ($resql && $obj = $this->db->fetch_array($resql)) { + $cleaned = cleanObjectDatas(dol_clone($object)); + $json = json_encode($cleaned); + // call the zapierPostWebhook() function + zapierPostWebhook($obj['url'], $json); + } + $logtriggeraction = true; + break; case 'CONTACT_MODIFY': + $resql = $this->db->query($sql); + while ($resql && $obj = $this->db->fetch_array($resql)) { + $cleaned = cleanObjectDatas(dol_clone($object)); + $json = json_encode($cleaned); + // call the zapierPostWebhook() function + zapierPostWebhook($obj['url'], $json); + } + $logtriggeraction = true; + break; case 'CONTACT_DELETE': + break; case 'CONTACT_ENABLEDISABLE': break; // Products @@ -324,10 +339,28 @@ class InterfaceZapierTriggers extends DolibarrTriggers // case 'LINEFICHINTER_DELETE': // Members - // case 'MEMBER_CREATE': + case 'MEMBER_CREATE': + $resql = $this->db->query($sql); + while ($resql && $obj = $this->db->fetch_array($resql)) { + $cleaned = cleanObjectDatas(dol_clone($object)); + $json = json_encode($cleaned); + // call the zapierPostWebhook() function + zapierPostWebhook($obj['url'], $json); + } + $logtriggeraction = true; + break; + case 'MEMBER_MODIFY': + $resql = $this->db->query($sql); + while ($resql && $obj = $this->db->fetch_array($resql)) { + $cleaned = cleanObjectDatas(dol_clone($object)); + $json = json_encode($cleaned); + // call the zapierPostWebhook() function + zapierPostWebhook($obj['url'], $json); + } + $logtriggeraction = true; + break; // case 'MEMBER_VALIDATE': // case 'MEMBER_SUBSCRIPTION': - // case 'MEMBER_MODIFY': // case 'MEMBER_NEW_PASSWORD': // case 'MEMBER_RESILIATE': // case 'MEMBER_DELETE': diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 30ffee00248..8ffa69e31ac 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -94,7 +94,7 @@ if ($_SERVER['PHP_SELF'] != DOL_URL_ROOT.'/website/index.php') { // If we browsi $sql = "SELECT wp.rowid, wp.lang, wp.pageurl, wp.fk_page"; $sql .= " FROM ".MAIN_DB_PREFIX."website_page as wp"; $sql .= " WHERE wp.fk_website = ".((int) $website->id); - $sql .= " AND (wp.fk_page = ".$pageid." OR wp.rowid = ".$pageid; + $sql .= " AND (wp.fk_page = ".((int) $pageid)." OR wp.rowid = ".((int) $pageid); if (is_object($websitepage) && $websitepage->fk_page > 0) { $sql .= " OR wp.fk_page = ".$websitepage->fk_page." OR wp.rowid = ".$websitepage->fk_page; } diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index f58f1740f4d..fb8699b911e 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -2,7 +2,7 @@ /* Copyright (C) 2012 Nicolas Villa aka Boyquotes http://informetic.fr * Copyright (C) 2013 Florian Henry * Copyright (C) 2013-2016 Laurent Destailleur - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,10 +36,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/cron.lib.php'; // Load translation files required by the page $langs->loadLangs(array('admin', 'cron', 'members')); -if (!$user->rights->cron->create) { - accessforbidden(); -} - $id = GETPOST('id', 'int'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); @@ -49,6 +45,12 @@ $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); $securitykey = GETPOST('securitykey', 'alpha'); +$permissiontoadd = $user->rights->cron->create; + +if (!$user->rights->cron->create) { + accessforbidden(); +} + /* * Actions @@ -219,6 +221,30 @@ if ($action == 'inactive') { } } +// Action clone object +if ($action == 'confirm_clone' && $confirm == 'yes' && !empty($permissiontoadd)) { + if (1 == 0 && !GETPOST('clone_content') && !GETPOST('clone_receivers')) { + setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors'); + } else { + $objectutil = dol_clone($object, 1); // To avoid to denaturate loaded object when setting some properties for clone or if createFromClone modifies the object. We use native clone to keep this->db valid. + + $result = $objectutil->createFromClone($user, (($object->id > 0) ? $object->id : $id)); + if (is_object($result) || $result > 0) { + $newid = 0; + if (is_object($result)) { + $newid = $result->id; + } else { + $newid = $result; + } + header("Location: ".$_SERVER['PHP_SELF'].'?id='.$newid); // Open record of new object + exit; + } else { + setEventMessages($objectutil->error, $objectutil->errors, 'errors'); + $action = ''; + } + } +} + /* @@ -230,9 +256,9 @@ $formCron = new FormCron($db); llxHeader('', $langs->trans("CronTask")); -if ($action == 'edit' || empty($action) || $action == 'delete' || $action == 'execute') { - $head = cron_prepare_head($object); -} elseif ($action == 'create') { +$head = cron_prepare_head($object); + +if ($action == 'create') { print load_fiche_titre($langs->trans("CronTask"), '', 'title_setup'); } @@ -259,17 +285,26 @@ if ($conf->use_javascript_ajax) { } if ($action == 'delete') { - print $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CronDelete"), $langs->trans("CronConfirmDelete"), "confirm_delete", '', '', 1); + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CronDelete"), $langs->trans("CronConfirmDelete"), "confirm_delete", '', '', 1); $action = ''; } if ($action == 'execute') { - print $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id.'&securitykey='.$securitykey, $langs->trans("CronExecute"), $langs->trans("CronConfirmExecute"), "confirm_execute", '', '', 1); + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id.'&securitykey='.$securitykey, $langs->trans("CronExecute"), $langs->trans("CronConfirmExecute"), "confirm_execute", '', '', 1); $action = ''; } +// 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); +} + +// Print form confirm +print $formconfirm; /* @@ -317,7 +352,7 @@ if (($action == "create") || ($action == "edit")) { print '
    '; print $langs->trans('CronModule').""; - print "module_name."\" /> "; + print "module_name."\" /> "; print ""; print $form->textwithpicto('', $langs->trans("CronModuleHelp"), 1, 'help'); @@ -335,7 +370,7 @@ if (($action == "create") || ($action == "edit")) { print '
    '; print $langs->trans('CronObject').""; - print "objectname."\" /> "; + print "objectname."\" /> "; print ""; print $form->textwithpicto('', $langs->trans("CronObjectHelp"), 1, 'help'); @@ -727,8 +762,10 @@ if (($action == "create") || ($action == "edit")) { if (!$user->rights->cron->create) { print ''.$langs->trans("CronStatusActiveBtn").'/'.$langs->trans("CronStatusInactiveBtn").''; } else { + print ''.$langs->trans("Clone").''; + if (empty($object->status)) { - print ''.$langs->trans("CronStatusActiveBtn").''; + print ''.$langs->trans("CronStatusActiveBtn").''; } else { print ''.$langs->trans("CronStatusInactiveBtn").''; } diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index 0b926f6a802..2ffce20a924 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -553,11 +553,11 @@ class Cronjob extends CommonObject } elseif ($status == 2) { $sql .= " AND t.status = 2"; } - //Manage filter + // Manage filter if (is_array($filter) && count($filter) > 0) { foreach ($filter as $key => $value) { if ($key == 't.rowid') { - $sql .= ' AND '.$key.' = '.$this->db->escape($value); + $sql .= ' AND '.$key.' = '.((int) $value); } else { $sql .= ' AND '.$key.' LIKE \'%'.$this->db->escape($value).'%\''; } @@ -859,6 +859,8 @@ class Cronjob extends CommonObject */ public function createFromClone(User $user, $fromid) { + global $langs; + $error = 0; $object = new Cronjob($this->db); @@ -868,10 +870,10 @@ class Cronjob extends CommonObject // Load source object $object->fetch($fromid); $object->id = 0; - $object->statut = 0; // Clear fields - // ... + $object->status = self::STATUS_DISABLED; + $object->label = $langs->trans("CopyOf").' '.$object->label; // Create clone $object->context['createfromclone'] = 'createfromclone'; @@ -883,11 +885,6 @@ class Cronjob extends CommonObject $error++; } - //if (! $error) - //{ - - //} - unset($object->context['createfromclone']); // End @@ -1140,9 +1137,9 @@ class Cronjob extends CommonObject $ret = dol_include_once($this->classesname); if ($ret === false || (!class_exists($this->objectname))) { if ($ret === false) { - $this->error = $langs->trans('CronCannotLoadClass', $this->classesname, $this->objectname); + $this->error = $langs->transnoentitiesnoconv('CronCannotLoadClass', $this->classesname, $this->objectname); } else { - $this->error = $langs->trans('CronCannotLoadObject', $this->classesname, $this->objectname); + $this->error = $langs->transnoentitiesnoconv('CronCannotLoadObject', $this->classesname, $this->objectname); } dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR); $this->lastoutput = $this->error; @@ -1155,7 +1152,7 @@ class Cronjob extends CommonObject // test if method exists if (!$error) { if (!method_exists($this->objectname, $this->methodename)) { - $this->error = $langs->trans('CronMethodDoesNotExists', $this->objectname, $this->methodename); + $this->error = $langs->transnoentitiesnoconv('CronMethodDoesNotExists', $this->objectname, $this->methodename); dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR); $this->lastoutput = $this->error; $this->lastresult = -1; @@ -1163,7 +1160,7 @@ class Cronjob extends CommonObject $error++; } if (in_array(strtolower(trim($this->methodename)), array('executecli'))) { - $this->error = $langs->trans('CronMethodNotAllowed', $this->methodename, $this->objectname); + $this->error = $langs->transnoentitiesnoconv('CronMethodNotAllowed', $this->methodename, $this->objectname); dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR); $this->lastoutput = $this->error; $this->lastresult = -1; diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php index a88bcda9a66..4d829258b2b 100644 --- a/htdocs/cron/list.php +++ b/htdocs/cron/list.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013-2019 Laurent Destailleur + * Copyright (C) 2013-2021 Laurent Destailleur * Copyright (C) 2019 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,6 @@ * \brief Lists Jobs */ - require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/cron/class/cronjob.class.php'; @@ -68,7 +67,7 @@ $mode = GETPOST('mode', 'aZ09'); $search_status = (GETPOSTISSET('search_status') ?GETPOST('search_status', 'int') : GETPOST('status', 'int')); $search_label = GETPOST("search_label", 'alpha'); $search_module_name = GETPOST("search_module_name", 'alpha'); -$search_lastresult = GETPOST("search_lastresult", "alpha"); +$search_lastresult = GETPOST("search_lastresult", "alphawithlgt"); $securitykey = GETPOST('securitykey', 'alpha'); $outputdir = $conf->cron->dir_output; @@ -202,7 +201,7 @@ if (empty($reshook)) { $permissiontodelete = $user->rights->cron->delete; $uploaddir = $conf->cron->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; - if ($permissiontoadd) { + if ($massaction && $permissiontoadd) { $tmpcron = new Cronjob($db); foreach ($toselect as $id) { $result = $tmpcron->fetch($id); @@ -350,9 +349,6 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; $stringcurrentdate = $langs->trans("CurrentHour").': '.dol_print_date(dol_now(), 'dayhour'); -if ($action == 'delete') { - print $form->formconfirm($_SERVER['PHP_SELF']."?id=".$id.$param, $langs->trans("CronDelete"), $langs->trans("CronConfirmDelete"), "confirm_delete", '', '', 1); -} if ($action == 'execute') { print $form->formconfirm($_SERVER['PHP_SELF']."?id=".$id.'&securitykey='.$securitykey.$param, $langs->trans("CronExecute"), $langs->trans("CronConfirmExecute"), "confirm_execute", '', '', 1); } @@ -362,12 +358,12 @@ $arrayofmassactions = array( //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), 'enable'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("CronStatusActiveBtn"), - 'disable'=>img_picto('', 'title_close', 'class="pictofixedwidth"').$langs->trans("CronStatusInactiveBtn"), + 'disable'=>img_picto('', 'uncheck', 'class="pictofixedwidth"').$langs->trans("CronStatusInactiveBtn"), ); if ($user->rights->cron->delete) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } -if (in_array($massaction, array('presend', 'predelete'))) { +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); @@ -406,6 +402,12 @@ if ($mode == 'modulesetup') { print_barre_liste($pagetitle, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, ($mode == 'modulesetup' ? '' : 'title_setup'), 0, $newcardbutton, '', $limit); +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendCronRef"; +$modelmail = "cron"; +$objecttmp = new Cronjob($db); +$trackid = 'cron'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; $text = $langs->trans("HoursOnThisPageAreOnServerTZ").' '.$stringcurrentdate.'
    '; if (!empty($conf->global->CRON_WARNING_DELAY_HOURS)) { @@ -597,7 +599,7 @@ if ($num > 0) { print '
    '; + print ''; if (!empty($obj->lastoutput)) { print dol_trunc(nl2br($obj->lastoutput), 50); } diff --git a/htdocs/datapolicy/admin/setup.php b/htdocs/datapolicy/admin/setup.php index a334b36929e..dde8644571e 100644 --- a/htdocs/datapolicy/admin/setup.php +++ b/htdocs/datapolicy/admin/setup.php @@ -27,15 +27,7 @@ require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; require_once '../lib/datapolicy.lib.php'; // Translations -$langs->load('admin'); -$langs->load('companies'); -$langs->load('members'); -$langs->load('datapolicy@datapolicy'); - -// Access control -if (!$user->admin) { - accessforbidden(); -} +$langs->loadLangs(array('admin', 'companies', 'members', 'datapolicy@datapolicy')); // Parameters $action = GETPOST('action', 'aZ09'); @@ -43,35 +35,27 @@ $backtopage = GETPOST('backtopage', 'alpha'); $arrayofparameters = array(); $arrayofparameters['ThirdParty'] = array( - 'DATAPOLICY_TIERS_CLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_TIERS_PROSPECT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_TIERS_PROSPECT_CLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_TIERS_NIPROSPECT_NICLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_TIERS_FOURNISSEUR'=>array('css'=>'minwidth200'), + 'DATAPOLICY_TIERS_CLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'company', 'class="pictofixedwidth"')), + 'DATAPOLICY_TIERS_PROSPECT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'company', 'class="pictofixedwidth"')), + 'DATAPOLICY_TIERS_PROSPECT_CLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'company', 'class="pictofixedwidth"')), + 'DATAPOLICY_TIERS_NIPROSPECT_NICLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'company', 'class="pictofixedwidth"')), + 'DATAPOLICY_TIERS_FOURNISSEUR'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'supplier', 'class="pictofixedwidth"')), ); if (!empty($conf->global->DATAPOLICY_USE_SPECIFIC_DELAY_FOR_CONTACT)) { $arrayofparameters['Contact'] = array( - 'DATAPOLICY_CONTACT_CLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_CONTACT_PROSPECT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_CONTACT_PROSPECT_CLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_CONTACT_NIPROSPECT_NICLIENT'=>array('css'=>'minwidth200'), - 'DATAPOLICY_CONTACT_FOURNISSEUR'=>array('css'=>'minwidth200'), + 'DATAPOLICY_CONTACT_CLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'contact', 'class="pictofixedwidth"')), + 'DATAPOLICY_CONTACT_PROSPECT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'contact', 'class="pictofixedwidth"')), + 'DATAPOLICY_CONTACT_PROSPECT_CLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'contact', 'class="pictofixedwidth"')), + 'DATAPOLICY_CONTACT_NIPROSPECT_NICLIENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'contact', 'class="pictofixedwidth"')), + 'DATAPOLICY_CONTACT_FOURNISSEUR'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'contact', 'class="pictofixedwidth"')), ); } if (!empty($conf->adherent->enabled)) { $arrayofparameters['Member'] = array( - 'DATAPOLICY_ADHERENT'=>array('css'=>'minwidth200'), + 'DATAPOLICY_ADHERENT'=>array('css'=>'minwidth200', 'picto'=>img_picto('', 'member', 'class="pictofixedwidth"')), ); } - - -/* - * Actions - */ - -include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; - $valTab = array( '' => $langs->trans('Never'), '6' => $langs->trans('NB_MONTHS', 6), @@ -85,6 +69,40 @@ $valTab = array( '240' => $langs->trans('NB_YEARS', 20), ); +// Access control +if (!$user->admin) { + accessforbidden(); +} + + +/* + * Actions + */ + +foreach ($arrayofparameters as $title => $tab) { + foreach ($tab as $key => $val) { + // Modify constant only if key was posted (avoid resetting key to the null value) + if (GETPOSTISSET($key)) { + if (preg_match('/category:/', $val['type'])) { + if (GETPOST($key, 'int') == '-1') { + $val_const = ''; + } else { + $val_const = GETPOST($key, 'int'); + } + } else { + $val_const = GETPOST($key, 'alpha'); + } + + $result = dolibarr_set_const($db, $key, $val_const, 'chaine', 0, '', $conf->entity); + if ($result < 0) { + $error++; + break; + } + } + } +} + + /* * View @@ -96,11 +114,11 @@ llxHeader('', $langs->trans($page_name)); // Subheader $linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans($page_name), $linkback, 'object_generic'); +print load_fiche_titre($langs->trans($page_name), $linkback, 'generic'); // Configuration header $head = datapolicyAdminPrepareHead(); -print dol_get_fiche_head($head, 'settings', '', -1, "datapolicy@datapolicy"); +print dol_get_fiche_head($head, 'settings', '', -1, ''); // Setup page goes here echo ''.$langs->trans("datapolicySetupPage").'

    '; @@ -118,6 +136,7 @@ if ($action == 'edit') { print '
    '.$langs->trans($title).'
    '; + print $val['picto']; print $form->textwithpicto($langs->trans($key), $langs->trans($key.'Tooltip')); print ''; print '
    '.$langs->trans($title).'
    '; + print $val['picto']; print $form->textwithpicto($langs->trans($key), $langs->trans('DATAPOLICY_Tooltip_SETUP')); print ''.($conf->global->$key == '' ? $langs->trans('None') : $valTab[$conf->global->$key]).'
    '; + print '
    '; /* * Documents generated @@ -687,11 +687,11 @@ if ($action == 'create') { // Create. Seems to no be used } - print '
    '; + print '
    '; - // Rien a droite + // Nothing on right - print '
    '; + print '
    '; } else { /* Expedition non trouvee */ print "Expedition inexistante ou acces refuse"; diff --git a/htdocs/don/card.php b/htdocs/don/card.php index 1dfade00bec..0763ff9b7e5 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -120,7 +120,7 @@ if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) { if ($action == 'update') { if (!empty($cancel)) { - header("Location: ".$_SERVER['PHP_SELF']."?id=".$id); + header("Location: ".$_SERVER['PHP_SELF']."?id=".urlencode($id)); exit; } diff --git a/htdocs/don/class/api_donations.class.php b/htdocs/don/class/api_donations.class.php index 2773ab62c14..cfd9e8ccd8b 100644 --- a/htdocs/don/class/api_donations.class.php +++ b/htdocs/don/class/api_donations.class.php @@ -16,9 +16,9 @@ * along with this program. If not, see . */ - use Luracast\Restler\RestException; +use Luracast\Restler\RestException; - require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; +require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; /** * API class for donations @@ -33,7 +33,7 @@ class Donations extends DolibarrApi * @var array $FIELDS Mandatory fields, checked when create and update object */ public static $FIELDS = array( - 'socid' + 'amount' ); /** @@ -123,7 +123,7 @@ class Donations extends DolibarrApi $sql .= " AND t.fk_soc = sc.fk_soc"; } if ($thirdparty_ids) { - $sql .= " AND t.fk_soc = ".$thirdparty_ids." "; + $sql .= " AND t.fk_soc = ".((int) $thirdparty_ids)." "; } // Add sql filters @@ -131,7 +131,7 @@ class Donations extends DolibarrApi if (!DolibarrApi::_checkFilters($sqlfilters)) { throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); } - $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } @@ -199,7 +199,7 @@ class Donations extends DolibarrApi }*/ if ($this->don->create(DolibarrApiAccess::$user) < 0) { - throw new RestException(500, "Error creating order", array_merge(array($this->don->error), $this->don->errors)); + throw new RestException(500, "Error creating donation", array_merge(array($this->don->error), $this->don->errors)); } return $this->don->id; @@ -311,7 +311,7 @@ class Donations extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $result = $this->don->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger); + $result = $this->don->valid_promesse($id, DolibarrApiAccess::$user->id, $notrigger); if ($result == 0) { throw new RestException(304, 'Error nothing done. May be object is already validated'); } @@ -364,7 +364,7 @@ class Donations extends DolibarrApi private function _validate($data) { $don = array(); - foreach (Orders::$FIELDS as $field) { + foreach (Donations::$FIELDS as $field) { if (!isset($data[$field])) { throw new RestException(400, $field." field missing"); } diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index 1ec3ebe1cc5..181b3fc0ca3 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -7,6 +7,7 @@ * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2019 Thibault FOUCART * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2021 Maxime DEMAREST * * 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 @@ -379,7 +380,7 @@ class Don extends CommonObject $sql .= ", phone"; $sql .= ", phone_mobile"; $sql .= ") VALUES ("; - $sql .= "'".$this->db->idate($now)."'"; + $sql .= "'".$this->db->idate($this->date ? $this->date : $now)."'"; $sql .= ", ".$conf->entity; $sql .= ", ".price2num($this->amount); $sql .= ", ".($this->modepaymentid ? $this->modepaymentid : "null"); @@ -475,8 +476,8 @@ class Don extends CommonObject $sql .= ",address='".$this->db->escape($this->address)."'"; $sql .= ",zip='".$this->db->escape($this->zip)."'"; $sql .= ",town='".$this->db->escape($this->town)."'"; - $sql .= ",fk_country = ".($this->country_id > 0 ? $this->country_id : '0'); - $sql .= ",public=".$this->public; + $sql .= ",fk_country = ".($this->country_id > 0 ? ((int) $this->country_id) : '0'); + $sql .= ",public=".((int) $this->public); $sql .= ",fk_projet=".($this->fk_project > 0 ? $this->fk_project : 'null'); $sql .= ",note_private=".(!empty($this->note_private) ? ("'".$this->db->escape($this->note_private)."'") : "NULL"); $sql .= ",note_public=".(!empty($this->note_public) ? ("'".$this->db->escape($this->note_public)."'") : "NULL"); @@ -485,8 +486,8 @@ class Don extends CommonObject $sql .= ",email='".$this->db->escape(trim($this->email))."'"; $sql .= ",phone='".$this->db->escape(trim($this->phone))."'"; $sql .= ",phone_mobile='".$this->db->escape(trim($this->phone_mobile))."'"; - $sql .= ",fk_statut=".$this->statut; - $sql .= " WHERE rowid = ".$this->id; + $sql .= ",fk_statut=".((int) $this->statut); + $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::Update", LOG_DEBUG); $resql = $this->db->query($sql); @@ -612,7 +613,7 @@ class Don extends CommonObject $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.fk_country = c.rowid"; $sql .= " WHERE d.entity IN (".getEntity('donation').")"; if (!empty($id)) { - $sql .= " AND d.rowid=".$id; + $sql .= " AND d.rowid=".((int) $id); } elseif (!empty($ref)) { $sql .= " AND d.ref='".$this->db->escape($ref)."'"; } @@ -1098,4 +1099,31 @@ class Don extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Function to get reamain to pay for a donation + * + * @return int <0 if KO, > reamain to pay if OK + */ + public function getRemainToPay() + { + dol_syslog(__METHOD__, LOG_DEBUG); + + if (empty($this->id)) { + $this->error = 'Missing object id'; + $this->errors[] = $this->error; + dol_syslog(__METHOD__.' : '.$this->error, LOG_ERR); + return -1; + } + + $sql = 'SELECT SUM(amount) as sum_amount FROM '.MAIN_DB_PREFIX.'payment_donation WHERE fk_donation = '.$this->id; + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + return -2; + } else { + $sum_amount = (float) $this->db->fetch_object($resql)->sum_amount; + return (float) $this->amount - $sum_amount; + } + } } diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php index 7c8bd71ccd2..82c3ddde7fa 100644 --- a/htdocs/don/class/paymentdonation.class.php +++ b/htdocs/don/class/paymentdonation.class.php @@ -92,6 +92,15 @@ class PaymentDonation extends CommonObject public $type_code; public $type_label; + /** + * @var string Id of external payment mode + */ + public $ext_payment_id; + + /** + * @var string Name of external payment mode + */ + public $ext_payment_site; /** * Constructor @@ -126,6 +135,13 @@ class PaymentDonation extends CommonObject } // Clean parameters + if (isset($this->chid)) { + $this->chid = (int) $this->chid; + } elseif (isset($this->fk_donation)) { + // NOTE : The property used in INSERT for fk_donation is not fk_donation but chid + // (keep priority to chid property) + $this->chid = (int) $this->fk_donation; + } if (isset($this->fk_donation)) { $this->fk_donation = (int) $this->fk_donation; } @@ -169,12 +185,14 @@ class PaymentDonation extends CommonObject if ($totalamount != 0) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."payment_donation (fk_donation, datec, datep, amount,"; - $sql .= " fk_typepayment, num_payment, note, fk_user_creat, fk_bank)"; + $sql .= " fk_typepayment, num_payment, note, ext_payment_id, ext_payment_site,"; + $sql .= " fk_user_creat, fk_bank)"; $sql .= " VALUES ($this->chid, '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datepaid)."',"; $sql .= " ".$totalamount.","; - $sql .= " ".$this->paymenttype.", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_public)."', ".$user->id.","; - $sql .= " 0)"; + $sql .= " ".$this->paymenttype.", '".$this->db->escape($this->num_payment)."', '".$this->db->escape($this->note_public)."', "; + $sql .= " ".($this->ext_payment_id ? "'".$this->db->escape($this->ext_payment_id)."'" : "null").", ".($this->ext_payment_site ? "'".$this->db->escape($this->ext_payment_site)."'" : "null").","; + $sql .= " ".$user->id.", 0)"; dol_syslog(get_class($this)."::create", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/don/document.php b/htdocs/don/document.php index 0bd4edbc77b..374306bc7b0 100644 --- a/htdocs/don/document.php +++ b/htdocs/don/document.php @@ -188,7 +188,7 @@ if ($object->id) { print dol_get_fiche_end(); $modulepart = 'don'; - $permission = $user->rights->don->creer; + $permissiontoadd = $user->rights->don->creer; $permtoedit = $user->rights->don->creer; $param = '&id='.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index e5e7ce8549b..035a7aee9c6 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -425,10 +425,10 @@ class EcmFiles extends CommonObject //$sql .= " AND t.entity = ".$conf->entity; // hashforshare already unique } elseif ($src_object_type && $src_object_id) { // Warning: May return several record, and only first one is returned ! - $sql .= " AND t.src_object_type ='".$this->db->escape($src_object_type)."' AND t.src_object_id = ".$this->db->escape($src_object_id); + $sql .= " AND t.src_object_type = '".$this->db->escape($src_object_type)."' AND t.src_object_id = ".((int) $src_object_id); $sql .= " AND t.entity = ".$conf->entity; } else { - $sql .= ' AND t.rowid = '.$this->db->escape($id); // rowid already unique + $sql .= ' AND t.rowid = '.((int) $id); // rowid already unique } $this->db->plimit(1); // When we search on src or on hash of content (hashforfile) to solve hash conflict when several files has same content, we take first one only @@ -529,7 +529,11 @@ class EcmFiles extends CommonObject $sqlwhere = array(); if (count($filter) > 0) { foreach ($filter as $key => $value) { - $sqlwhere [] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + if ($key == 't.src_object_id') { + $sqlwhere[] = $key.' = '.((int) $value); + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } } } $sql .= ' WHERE 1 = 1'; diff --git a/htdocs/ecm/dir_add_card.php b/htdocs/ecm/dir_add_card.php index f5140cf296a..1416983e3a3 100644 --- a/htdocs/ecm/dir_add_card.php +++ b/htdocs/ecm/dir_add_card.php @@ -23,6 +23,8 @@ * \brief Main page for ECM section area */ +if (! defined('DISABLE_JS_GRAHP')) define('DISABLE_JS_GRAPH', 1); + require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/ecm/class/htmlecm.form.class.php'; @@ -124,7 +126,7 @@ if ($action == 'add' && $permtoadd) { } $ref = (string) GETPOST("ref", 'alpha'); - $label = (string) GETPOST("label", 'alpha'); + $label = dol_sanitizeFileName(GETPOST("label", 'alpha')); $desc = (string) GETPOST("desc", 'alpha'); $catParent = GETPOST("catParent", 'alpha'); // Can be an int (with ECM) or a string (with generic filemanager) if ($catParent == '-1') { @@ -153,8 +155,7 @@ if ($action == 'add' && $permtoadd) { setEventMessages($ecmdir->error, $ecmdir->errors, 'errors'); $action = 'create'; } - } else // For example $module == 'medias' - { + } else { // For example $module == 'medias' $dirfornewdir = ''; if ($module == 'medias') { $dirfornewdir = $conf->medias->multidir_output[$conf->entity]; @@ -168,6 +169,7 @@ if ($action == 'add' && $permtoadd) { $fullpathofdir = $dirfornewdir.'/'.($catParent ? $catParent.'/' : '').$label; $result = dol_mkdir($fullpathofdir, DOL_DATA_ROOT); if ($result < 0) { + $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateDir', $label), null, 'errors'); $error++; } else { @@ -186,7 +188,7 @@ if ($action == 'add' && $permtoadd) { exit; } } -} elseif ($action == 'confirm_deletesection' && $confirm == 'yes') { +} elseif ($action == 'confirm_deletesection' && $confirm == 'yes' && $permtoadd) { // Deleting file $result = $ecmdir->delete($user); setEventMessages($langs->trans("ECMSectionWasRemoved", $ecmdir->label), null, 'mesgs'); diff --git a/htdocs/ecm/dir_card.php b/htdocs/ecm/dir_card.php index 4c93e005266..d84a7330e69 100644 --- a/htdocs/ecm/dir_card.php +++ b/htdocs/ecm/dir_card.php @@ -88,17 +88,23 @@ if ($module == 'ecm') { } // Permissions +$permtoread = 0; $permtoadd = 0; $permtoupload = 0; if ($module == 'ecm') { + $permtoread = $user->rights->ecm->read; $permtoadd = $user->rights->ecm->setup; $permtoupload = $user->rights->ecm->upload; } if ($module == 'medias') { + $permtoread = ($user->rights->mailing->lire || $user->rights->website->read); $permtoadd = ($user->rights->mailing->creer || $user->rights->website->write); $permtoupload = ($user->rights->mailing->creer || $user->rights->website->write); } +if (!$permtoread) { + accessforbidden(); +} /* @@ -106,7 +112,7 @@ if ($module == 'medias') { */ // Upload file -if (GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC)) { +if (GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC) && $permtoupload) { if (dol_mkdir($upload_dir) >= 0) { $resupload = dol_move_uploaded_file($_FILES['userfile']['tmp_name'], $upload_dir."/".dol_unescapefile($_FILES['userfile']['name']), 0, 0, $_FILES['userfile']['error']); if (is_numeric($resupload) && $resupload > 0) { @@ -131,7 +137,7 @@ if (GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC)) { } // Remove file -if ($action == 'confirm_deletefile' && $confirm == 'yes') { +if ($action == 'confirm_deletefile' && $confirm == 'yes' && $permtoupload) { $langs->load("other"); $file = $upload_dir."/".GETPOST('urlfile'); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). $ret = dol_delete_file($file); @@ -145,7 +151,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { } // Remove dir -if ($action == 'confirm_deletedir' && $confirm == 'yes') { +if ($action == 'confirm_deletedir' && $confirm == 'yes' && $permtoupload) { $backtourl = DOL_URL_ROOT."/ecm/index.php"; if ($module == 'medias') { $backtourl = DOL_URL_ROOT."/website/index.php?file_manager=1"; @@ -181,7 +187,7 @@ if ($action == 'confirm_deletedir' && $confirm == 'yes') { } // Update dirname or description -if ($action == 'update' && !GETPOST('cancel', 'alpha')) { +if ($action == 'update' && !GETPOST('cancel', 'alpha') && $permtoadd) { $error = 0; if ($module == 'ecm') { diff --git a/htdocs/ecm/file_card.php b/htdocs/ecm/file_card.php index 93885c2843a..14bc7e377f0 100644 --- a/htdocs/ecm/file_card.php +++ b/htdocs/ecm/file_card.php @@ -36,10 +36,6 @@ $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); -if (!$user->rights->ecm->setup) { - accessforbidden(); -} - // Get parameters $socid = GETPOST("socid", "int"); @@ -105,6 +101,14 @@ if ($result < 0) { exit; } +// Permissions +$permtoread = $user->rights->ecm->read; +$permtoadd = $user->rights->ecm->setup; +$permtoupload = $user->rights->ecm->upload; + +if (!$permtoread) { + accessforbidden(); +} /* @@ -123,7 +127,7 @@ if ($cancel) { } // Rename file -if ($action == 'update') { +if ($action == 'update' && $permtoadd) { $error = 0; $oldlabel = GETPOST('urlfile', 'alpha'); diff --git a/htdocs/ecm/file_note.php b/htdocs/ecm/file_note.php index d2f3f7b4792..505e432f982 100644 --- a/htdocs/ecm/file_note.php +++ b/htdocs/ecm/file_note.php @@ -22,7 +22,7 @@ /** * \file htdocs/ecm/file_note.php * \ingroup ecm - * \brief Fiche de notes sur une ecm file + * \brief Tab for notes on an ECM file */ require '../main.inc.php'; @@ -39,10 +39,6 @@ $ref = GETPOST('ref', 'alpha'); $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); -if (!$user->rights->ecm->setup) { - accessforbidden(); -} - // Get parameters $socid = GETPOST("socid", "int"); // Security check @@ -109,6 +105,13 @@ if ($result < 0) { $permissionnote = $user->rights->ecm->setup; // Used by the include of actions_setnotes.inc.php +$permtoread = $user->rights->ecm->read; + +if (!$permtoread) { + accessforbidden(); +} + + /* * Actions */ diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php index 26bf242b0f2..3a8d33343c7 100644 --- a/htdocs/ecm/index.php +++ b/htdocs/ecm/index.php @@ -34,12 +34,6 @@ require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php'; // Load translation files required by the page $langs->loadLangs(array("ecm", "companies", "other", "users", "orders", "propal", "bills", "contracts")); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'ecm', 0); - // Get parameters $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); @@ -81,6 +75,12 @@ $userstatic = new User($db); $error = 0; +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'ecm', 0); + /* * Actions diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index bcfff8aa2da..d54dcf14d1e 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -440,15 +440,13 @@ if (empty($action) || $action == 'file_manager' || preg_match('/refresh/i', $act continue; // If condition to show is ok } - $var = false; - print '