Merge branch 'develop' of github.com:Dolibarr/dolibarr into dev_new_project_upgrade_external_user_perms_project
11
.github/CONTRIBUTING.md
vendored
@@ -26,8 +26,9 @@ Default **language here is english**. So please prepare your contributions in en
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo) the [GitHub repository](https://github.com/Dolibarr/dolibarr).
|
||||
2. Clone your fork.
|
||||
3. Choose a branch(See the [Branches](#branches) section below).
|
||||
4. Commit and push your changes.
|
||||
5. [Make a pull request](https://help.github.com/articles/creating-a-pull-request).
|
||||
4. Read our developer documentation on the [Dolibarr Wiki](https://wiki.dolibarr.org/index.php?title=Developer_documentation).
|
||||
5. Commit and push your changes.
|
||||
6. [Make a pull request](https://help.github.com/articles/creating-a-pull-request).
|
||||
|
||||
<span id="branches" name="branches"></span>
|
||||
### Branches
|
||||
@@ -116,13 +117,13 @@ a process to follow to optimize the chance to have PRs merged efficiently...
|
||||
|
||||
Also, some code changes need a prior approbation:
|
||||
|
||||
* if you want to include a new external library (into htdocs/includes directory), please ask before to the core project manager (mention @dolibarr-yoda in your issue) to see if such a library can be accepted.
|
||||
* if you want to include a new external library (into htdocs/includes directory), please ask before to the core project manager (mention @dolibarr-jedi in your issue) to see if such a library can be accepted.
|
||||
|
||||
* if you add a new table, you must first create a page on https://wiki.dolibarr.org/index.php/Category:Table_SQL (copy an existing page changing its name to see it into this index page). Then ask the project manager (@dolibarr-yoda) if the new data model you plan to add is compatible with curent and future works in progress and can be accepted as you suggest.
|
||||
* if you add a new tables or fields, you MUST first submit a standalone PR with the data structure changes you plan to add/modify (and only data structure changes). Start development only once this data structure has been accepted.
|
||||
|
||||
Once a PR has been submitted, you may need to wait for its integration. It is common that the project leader let the PR open for a long delay to allow every developer discuss about the PR (A label is added in such a case).
|
||||
|
||||
If the label of PR start with "Draft" or "WIP" (Work In Progress), it will not be analyzed for merging until you change the label of PR (but it can be analyzed for discussion).
|
||||
If the label of PR start with "Draft" or "WIP" (Work In Progress), it will not be analyzed for merging until you change the label of the PR (but it can be analyzed for discussion).
|
||||
|
||||
If your PR has errors reported by the Continuous Integration Platform, it means your PR is not valid and nothing will be done with it. It will be kept open to allow developers to fix this, or it may be closed several month later. Don't expect anything on your PR if you have such errors, you MUST first fix the Continuous Integration error to have it taken into consideration.
|
||||
|
||||
|
||||
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,35 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us fix something that is broken
|
||||
title: ''
|
||||
labels: Bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Instructions
|
||||
*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*
|
||||
*Please:*
|
||||
- *replace the bracket enclosed texts with meaningful information*
|
||||
- *remove any unused sub-section*
|
||||
|
||||
|
||||
# Bug
|
||||
[*Short description*]
|
||||
|
||||
## Environment
|
||||
- **Version**: [*Affected Dolibarr version(s)*]
|
||||
- **OS**: [*Server OS type and version*]
|
||||
- **Web server**: [*Webserver type and version*]
|
||||
- **PHP**: [*PHP version*]
|
||||
- **Database**: [*Database type and version*]
|
||||
- **URL(s)**: [*Affected URL(s)*]
|
||||
|
||||
## Expected and actual behavior
|
||||
[*Verbose description*]
|
||||
|
||||
## Steps to reproduce the behavior
|
||||
[*Verbose description*]
|
||||
|
||||
## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging informations…)
|
||||
[*Files*]
|
||||
71
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Bug report
|
||||
description: Create a report to help us fix something that is broken
|
||||
labels: ["Bug"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.
|
||||
|
||||
- type: textarea
|
||||
id: bug
|
||||
attributes:
|
||||
label: Bug
|
||||
description: Please give a short description of the bug
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: environment-version
|
||||
attributes:
|
||||
label: Environment Version
|
||||
description: Affected Dolibarr version(s)
|
||||
|
||||
- type: input
|
||||
id: environment-os
|
||||
attributes:
|
||||
label: Environment OS
|
||||
description: Server OS type and version
|
||||
|
||||
- type: input
|
||||
id: environment-webserver
|
||||
attributes:
|
||||
label: Environment Web server
|
||||
description: Webserver type and version
|
||||
|
||||
- type: input
|
||||
id: environment-php
|
||||
attributes:
|
||||
label: Environment PHP
|
||||
description: PHP version
|
||||
|
||||
- type: input
|
||||
id: environment-database
|
||||
attributes:
|
||||
label: Environment Database
|
||||
description: Database type and version
|
||||
|
||||
- type: input
|
||||
id: environment-urls
|
||||
attributes:
|
||||
label: Environment URL(s)
|
||||
description: Affected URL(s)
|
||||
|
||||
- type: textarea
|
||||
id: expected-behaviour
|
||||
attributes:
|
||||
label: Expected and actual behavior
|
||||
description: Verbose description
|
||||
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce the behavior
|
||||
description: Verbose description
|
||||
|
||||
- type: textarea
|
||||
id: files
|
||||
attributes:
|
||||
label: Attached files
|
||||
description: Screenshots, screencasts, dolibarr.log, debugging informations
|
||||
27
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a new idea for this project
|
||||
title: ''
|
||||
labels: Feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Instructions
|
||||
*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*
|
||||
*Please:*
|
||||
- *replace the bracket enclosed texts with meaningful information*
|
||||
- *remove any unused sub-section*
|
||||
|
||||
|
||||
# Feature Request
|
||||
[*Short description*]
|
||||
|
||||
## Use case
|
||||
[*Verbose description*]
|
||||
|
||||
## Suggested implementation
|
||||
[*Verbose description*]
|
||||
|
||||
## Suggested steps
|
||||
[*List of tasks to achieve goal*]
|
||||
35
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Feature request
|
||||
description: Suggest a new idea for this project
|
||||
labels: ["Feature request"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.
|
||||
|
||||
- type: textarea
|
||||
id: feature-request
|
||||
attributes:
|
||||
label: Feature Request
|
||||
description: Short description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-case
|
||||
attributes:
|
||||
label: Use case
|
||||
description: Verbose description
|
||||
|
||||
- type: textarea
|
||||
id: suggested-implementation
|
||||
attributes:
|
||||
label: Suggested implementation
|
||||
description: Verbose description
|
||||
|
||||
- type: textarea
|
||||
id: suggested-steps
|
||||
attributes:
|
||||
label: Suggested steps
|
||||
description: List of tasks to achieve goal
|
||||
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,18 +1,18 @@
|
||||
# Instructions
|
||||
*This is a template to help you make good pull requests. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*
|
||||
*Please:*
|
||||
- *only keep the "Fix", "Close" or "New" section*
|
||||
- *only keep the "FIX", "CLOSE" or "NEW" section* (use uppercase to have the PR appears into the ChangeLog, lowercase will not appears)
|
||||
- *follow the project [contributing guidelines](/.github/CONTRIBUTING.md)*
|
||||
- *replace the bracket enclosed texts with meaningful information*
|
||||
|
||||
|
||||
# Fix #[*issue_number Short description*]
|
||||
# FIX|Fix #[*issue_number Short description*]
|
||||
[*Long description*]
|
||||
|
||||
|
||||
# Close #[*issue_number Short description*]
|
||||
# CLOSE|Close #[*issue_number Short description*]
|
||||
[*Long description*]
|
||||
|
||||
|
||||
# New [*Short description*]
|
||||
# NEW|New [*Short description*]
|
||||
[*Long description*]
|
||||
|
||||
1
.gitignore
vendored
@@ -55,3 +55,4 @@ yarn.lock
|
||||
package-lock.json
|
||||
|
||||
doc/install.lock
|
||||
/factory/
|
||||
|
||||
18
.travis.yml
@@ -50,14 +50,14 @@ jobs:
|
||||
env: DB=postgresql
|
||||
- stage: PHP 5.6-7.4
|
||||
if: type = pull_request OR type = push
|
||||
php: '7.4'
|
||||
php: '7.4.22'
|
||||
env: DB=mysql
|
||||
- stage: PHP Dev
|
||||
if: type = push AND branch = develop
|
||||
php: nightly
|
||||
env: DB=mysql
|
||||
- stage: PHP Dev
|
||||
if: type = push AND branch = 14.0
|
||||
if: type = push AND branch = 15.0
|
||||
php: nightly
|
||||
env: DB=mysql
|
||||
|
||||
@@ -106,7 +106,7 @@ install:
|
||||
php-parallel-lint/php-console-highlighter ^0 \
|
||||
squizlabs/php_codesniffer ^3
|
||||
fi
|
||||
if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ]; then
|
||||
if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '7.4.22' ]; then
|
||||
composer -n require phpunit/phpunit ^7 \
|
||||
php-parallel-lint/php-parallel-lint ^1.2 \
|
||||
php-parallel-lint/php-console-highlighter ^0 \
|
||||
@@ -241,7 +241,7 @@ before_script:
|
||||
# enable php-fpm
|
||||
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
|
||||
- |
|
||||
if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then
|
||||
if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '7.4.22' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then
|
||||
# Copy the included pool
|
||||
sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf
|
||||
fi
|
||||
@@ -276,7 +276,7 @@ script:
|
||||
set -e
|
||||
#parallel-lint --exclude htdocs/includes --blame .
|
||||
# Exclusions are defined in the ruleset.xml file
|
||||
if [ "$TRAVIS_PHP_VERSION" = "7.4" ]; then
|
||||
if [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then
|
||||
parallel-lint -e php --exclude dev/tools/test/namespacemig --exclude htdocs/includes/composer --exclude htdocs/includes/myclabs --exclude htdocs/includes/phpspec --exclude dev/initdata/dbf/includes \
|
||||
--exclude htdocs/includes/sabre --exclude htdocs/includes/phpoffice/PhpSpreadsheet --exclude htdocs/includes/sebastian \
|
||||
--exclude htdocs/includes/squizlabs/php_codesniffer --exclude htdocs/includes/jakub-onderka --exclude htdocs/includes/php-parallel-lint --exclude htdocs/includes/symfony \
|
||||
@@ -291,7 +291,7 @@ script:
|
||||
# Ensure we catch errors
|
||||
set -e
|
||||
# Exclusions are defined in the ruleset.xml file
|
||||
if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_PHP_VERSION" = "7.4" ]; then
|
||||
if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_PHP_VERSION" = "7.4.22" ]; then
|
||||
phpcs -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true .;
|
||||
fi
|
||||
set +e
|
||||
@@ -411,6 +411,12 @@ script:
|
||||
php upgrade.php 13.0.0 14.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade13001400.log
|
||||
php upgrade2.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-2.log
|
||||
php step5.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-3.log
|
||||
php upgrade.php 14.0.0 15.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade14001500.log
|
||||
php upgrade2.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-2.log
|
||||
php step5.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-3.log
|
||||
php upgrade.php 15.0.0 16.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade15001600.log
|
||||
php upgrade2.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-2.log
|
||||
php step5.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-3.log
|
||||
ls -alrt $TRAVIS_BUILD_DIR/
|
||||
|
||||
- |
|
||||
|
||||
10
COPYRIGHT
@@ -28,7 +28,7 @@ CKEditor 4.12.1 LGPL-2.1+ Yes
|
||||
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 Apache License 2.0 Yes Lib to make geoip convert
|
||||
Mobiledetect 2.8.34 MIT License Yes Detect mobile devices browsers
|
||||
Mobiledetect 2.8.39 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
|
||||
@@ -48,10 +48,10 @@ TCPDF 6.3.2 LGPL-3+ Yes
|
||||
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
|
||||
jQuery 3.5.1 MIT License Yes JS library
|
||||
jQuery UI 1.12.1 GPL and MIT License Yes JS library plugin UI
|
||||
Ace 1.4.14 BSD Yes JS library to get code syntaxique coloration in a textarea.
|
||||
ChartJS 3.7.1 MIT License Yes JS library for graph
|
||||
jQuery 3.6.0 MIT License Yes JS library
|
||||
jQuery UI 1.13.1 GPL and MIT License Yes JS library plugin UI
|
||||
jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css
|
||||
jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups)
|
||||
jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors
|
||||
|
||||
508
ChangeLog
@@ -2,6 +2,469 @@
|
||||
English Dolibarr ChangeLog
|
||||
--------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
***** ChangeLog for 16.0.0 compared to 15.0.0 *****
|
||||
|
||||
For users:
|
||||
---------------
|
||||
|
||||
NEW: PHP 8.0 compatibility
|
||||
|
||||
|
||||
|
||||
Modules
|
||||
NEW: Experimental module Event Organization Management
|
||||
NEW: Experimental module Workstations Management
|
||||
NEW: Experimental module Partnership Management
|
||||
|
||||
|
||||
For developers:
|
||||
---------------
|
||||
|
||||
NEW: A lot of addition of hooks.
|
||||
|
||||
|
||||
|
||||
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
|
||||
* The default value for MAIN_SECURITY_CSRF_WITH_TOKEN has been set to 2. It means any POST and any GET request that contains the "action" or "massaction"
|
||||
with a value of a sensitive action must also a valid token parameter (With previous value 1, only POST was concerned). Note: With value 3, any URL
|
||||
with parameter "action" or "massaction" need the token, whatever is the value of the action.
|
||||
* verifCond('stringtoevaluate') now return false when string contains a bad syntax content instead of true.
|
||||
* The deprecated method thirdparty_doc_create() has been removed. You can use the generateDocument() instead.
|
||||
* All triggers with a name XXX_UPDATE have been renamed with name XXX_MODIFY for code consistency purpose.
|
||||
* Rename build_path_from_id_categ() into buildPathFromId() and set method to private.
|
||||
* Move massaction 'confirm_createbills' from actions_massactions.inc.php to commande/list.php
|
||||
* Method fetch_all_resources(), fetch_all_used(), fetch_all_available() of DolResource has been removed (they were not used by core code).
|
||||
* Method fetch_all of DolResource has been renamed into fetchAll() to match naming conventions.
|
||||
|
||||
|
||||
***** ChangeLog for 15.0.1 compared to 15.0.0 *****
|
||||
FIX: #19777 #20281
|
||||
FIX: bad position of extrafields for interventions
|
||||
FIX: Blocking situation when a payment was deleted in bank.
|
||||
FIX: creation of the shipment if order contains services
|
||||
FIX: Drag and drop line of files on join files tab
|
||||
FIX: Error management on mass action "Approve holiday"
|
||||
FIX: error with php8
|
||||
FIX: in case of VAT refund, negative amount must be allowed
|
||||
FIX: invoice pdf: lines originating from deposits were not detailed anymore
|
||||
FIX: Invoice - When you create an invoice for a given thirdparty, fk_account is not retrieved from company card
|
||||
FIX: list of visible type of event was not correctly filtered
|
||||
FIX: Missing or bad permissions
|
||||
FIX: Missing the field date start/end in export supplier invoice/order
|
||||
FIX: On large proposal or invoice, fix n(n+1) sql into a n sql.
|
||||
FIX: options should not exists on invoices
|
||||
FIX: payment not completed when using Paypal.
|
||||
FIX: permission to download files of expense report with readall.
|
||||
FIX- Preview icon in documents list PDF in the admin page third-party
|
||||
FIX: shipping list, e.shipping_method_id should be e.fk_shipping_method.
|
||||
FIX: Show product photo on Supplier order Cornas model.
|
||||
FIX: User name in ManufacturingOrder
|
||||
FIX: viewimage.php blocks requests with multicompany from other enties
|
||||
FIX: #yogosha9048
|
||||
FIX: #yogosha9054
|
||||
FIX: #yogosha9095
|
||||
|
||||
|
||||
***** ChangeLog for 15.0.0 compared to 14.0.0 *****
|
||||
|
||||
For users:
|
||||
---------------
|
||||
|
||||
NEW: Online proposal signature
|
||||
NEW: Can define some max limit on expense report (per period, per type or expense, ...)
|
||||
NEW: Provide a special pages for bookmarks and multicompany for a better use of some mobile applications (like DoliDroid)
|
||||
NEW: Allow the use of __NEWREF__ to get for example the new reference a draft order will get after validation.
|
||||
NEW: Add option to disable globaly some notifications emails.
|
||||
NEW: #18401 Add __NEWREF__ subtitute to get new object reference.
|
||||
NEW: #18403 Add __URL_SHIPMENT__ substitute to get the URL of a shipment
|
||||
NEW: #18689 REST API module: add api key generate / modify permission.
|
||||
NEW: #18663 Make "L'Annuaire des Entreprises" the default provider for SIREN verification for French thirdparties.
|
||||
NEW: #18046 Add tags on ticket/categories
|
||||
NEW: #18326 Workflow: Close order on shipment closing.
|
||||
NEW: #18770 Can enter the buying price (for Weighted Average Price update) on lines during the reception step
|
||||
NEW: #18814 Add legal form for Sweden
|
||||
NEW: #18820 Accountancy - Add product account in import/export of thirdparty (level 3)
|
||||
NEW: Accountancy - Format FEC/FEC2 - Add column NumFacture
|
||||
NEW: Add $dolibarr_main_db_readonly in conf.php for readonly access.
|
||||
NEW: add auto creation of agenda event on supplier_order cancellation
|
||||
NEW: Add a PDF document template for Manufacturing Orders
|
||||
NEW: Add budget field into task #18986
|
||||
NEW: add cancel button to `classify reception` form on supplier_orders
|
||||
NEW: Added address field into contacts list
|
||||
NEW: Added documents page and send mail possibility in payments
|
||||
NEW: Add edit option in propal
|
||||
NEW: Added linked files page and send mail possibility in payments
|
||||
NEW: Add field date from/to in customer and supplier payment list
|
||||
NEW: Add filter from date to date into action/evt list
|
||||
NEW: Add import / export of MO and BOMLines - Close #18499
|
||||
NEW: Adding accounting export model for iSuite Expert
|
||||
NEW: add link to an element by ref
|
||||
NEW: add missing printFieldListFrom hook call on several lists
|
||||
NEW: add MRP into Object Linked Box
|
||||
NEW: Add option to hide customer code on PDF documents
|
||||
NEW: Add param $nolog to avoid logging into dol_delete_recursive_dir()
|
||||
NEW: Add sale representative in order and invoice list
|
||||
NEW: add a setting to create PDF in PDF/A - 1b format #18990
|
||||
NEW: Add `SOCIETE_SHOW_VAT_IN_LIST` to display VAT number in combo list of thirdparties
|
||||
NEW: Add sortorder on units list
|
||||
NEW: Adds PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES to hide product label in supplier order lines
|
||||
NEW: Add STOCK_MOVEMENT_LIST_HIDE_UNIT_PRICE to hide unit price on some pages
|
||||
NEW: add support for zstd compression
|
||||
NEW: Allow drag and drop on kits
|
||||
NEW: Allow exporting supplier order validation date + validation user
|
||||
NEW: Allows product ref generation after the form is validated with PRODUCT_GENERATE_REF_AFTER_FORM
|
||||
NEW: autocomplete account group when editing an account card
|
||||
NEW: Auto create invoice for payment done on an order with online payment link of order
|
||||
NEW: Can edit fields of proposal when proposal is not yet signed
|
||||
NEW: Can edit the translation key of an overwrote translation key.
|
||||
NEW: can enable/disable external calendar by default
|
||||
NEW: Can hide sender name on PDF documents
|
||||
NEW: Can select lot from a combo list of existing batch numbers (in MRP consumtion)
|
||||
NEW: Can set the default BOM on a product
|
||||
NEW: Can set/unset the usual working day of the week (friday, saturday, sunday)
|
||||
NEW: Can show progression of task into combo list of tasks
|
||||
NEW: can upload the odt file for the product doc template
|
||||
NEW: Contract - Add From/to input on search date
|
||||
NEW: Customer Display with TakePOS
|
||||
NEW: Split Sale in TakePOS
|
||||
NEW: Customer invoice template list - Add input date from/to
|
||||
NEW: date filter on project list and task list From->To
|
||||
NEW: display shipping method and tracking url on shipment list
|
||||
NEW: expense reports: conf to force amounts to be entered only including taxes
|
||||
NEW: expense reports: conf to pre-fill start/end dates with bounds of current month
|
||||
NEW: expense reports: show link to already existing overlapping expense report
|
||||
NEW: expense reports: can make project field mandatory on lines
|
||||
NEW: Expose bank account holder, label and number
|
||||
NEW: feature #18986
|
||||
NEW: field and behavior in product object
|
||||
NEW: generate intervention from time spent
|
||||
NEW: holiday: handle monthly balance updates with cronjob
|
||||
NEW: HRM integration, source code
|
||||
NEW: HRM admin - Add tabs
|
||||
NEW: HRM - Include more options to manage/custom dashboard
|
||||
NEW: Increase size of params of actions for emailcollector
|
||||
NEW: Invoice list - Use complete country select field with EEC or not
|
||||
NEW: mass action delete, no more break if at least one object has child
|
||||
NEW: mass action paid on customer invoice list
|
||||
NEW: massaction validate on supplier orders list
|
||||
NEW: Mass action send email to all attendees of an event.
|
||||
NEW: expense reports: conf to pre-fill start/end dates with bounds of current month
|
||||
NEW: Option "Add a link on the PDF to make the online payment"
|
||||
NEW: More options to generate PDF (show Frame option, width of picture option)
|
||||
NEW: Preview of pdf files of expense report lines
|
||||
NEW: print without details
|
||||
NEW: project time spent: conf to prevent recording time after X months
|
||||
NEW: rewrite bind accountancy code finding on customer and sales invoice
|
||||
NEW: Societe - Add perentity functionality on customer/supplier accountancy auxiliary account
|
||||
NEW: Survey - Add a clickable link in email send
|
||||
NEW: Social Contributions - Add from/to filter on list
|
||||
NEW: Supplier order and proposal - Add From/to input on search date
|
||||
NEW: Task - Add From/to input on search date
|
||||
NEW: Add theme option THEME_ELDY_USEBORDERONTABLE
|
||||
NEW: The Anti-CSRF protection MAIN_SECURITY_CSRF_WITH_TOKEN is on to value 1 by default
|
||||
NEW: Update SQL : install and migration
|
||||
NEW: Use an ajax call for the clicktodial feature instead of href link.
|
||||
NEW: when multiple order linked to facture, show list into note.
|
||||
NEW: when we delete several objects with massaction, if somes object has child we must see which objects are concerned and nevertheless delete objects which can be deleted
|
||||
NEW: Editing a page in website module keep old page with name .back
|
||||
NEW: External backups can be downloaded from the "About info page".
|
||||
NEW: Add massaction to switch status on sale / on purchase of a product.
|
||||
|
||||
|
||||
Modules
|
||||
NEW: Stable module Knowledge Management
|
||||
NEW: Experimental module Event Organization Management
|
||||
NEW: Experimental module Workstations Management
|
||||
NEW: Development of module Partnership Management
|
||||
|
||||
|
||||
For developers:
|
||||
---------------
|
||||
|
||||
NEW: Introduce method hasRight
|
||||
NEW: Can use textarea field into a confirm popup.
|
||||
NEW: Can use the result_mode of mysqli driver. Save memory for list count
|
||||
NEW: #18319 REST API - Shipment: Add 'close' action / endpoint / POST method.
|
||||
NEW: Add API /approve and /makeOrder for purchase orders.
|
||||
NEW: add action trigger for member excluded
|
||||
NEW: add option MAIN_IBAN_IS_NEVER_MANDATORY, MAIN_IBAN_NOT_MANDATORY, PROPAL_NOT_BILLABLE, PROPAL_REOPEN_UNSIGNED_ONLY, PROPOSAL_ARE_NOT_BILLABLE, TICKETS_MESSAGE_FORCE_MAIL
|
||||
NEW: Add code codebar column on serial/lot structure
|
||||
NEW: Add date_valid and date_approve columns in the list of supplier orders
|
||||
NEW: add hook `beforeBodyClose`
|
||||
NEW: Add hook hookGetEntity.
|
||||
NEW: add hookmanager on note pages
|
||||
NEW: add hook 'menuLeftMenuItems' to filter the leftmenu items
|
||||
NEW: Add the property "copytoclipboard" in modulebuilder
|
||||
NEW: api for knowledgemanagement
|
||||
NEW: API get list of legal form of business
|
||||
NEW: API list of staff units
|
||||
NEW: hook after rank update
|
||||
NEW: printFieldListFrom hook call on several lists
|
||||
NEW: Use lang selector when using a field key 'lang' in modulebuilder
|
||||
NEW: we need to be able to put more filters on deleteByParentField() function
|
||||
NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object
|
||||
NEW: Experimental feature to manage user sessions in database
|
||||
NEW: Hidden option API_DISABLE_COMPRESSION is now visible in API setup page.
|
||||
NEW: Add hook printUnderHeaderPDFline on invoice PDF templates (can be used for example to add a barcode or more information on header of invoices).
|
||||
|
||||
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
|
||||
* ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field
|
||||
into forms will be broken. The security token field is expected since Dolibarr v9 but a lot of external modules did not implement it).
|
||||
* Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook.
|
||||
* Old deprecated module "SimplePOS" has been completely removed. Use module "TakePOS" is you need a Point Of Sale.
|
||||
* The method static ActionComm::getActions($db, ...) is no more static. Use $actioncomm->getActions(...) instead (without $db param).
|
||||
* The 'action=delete&file=...' has been replaced with 'action=deletefile&file=...' to avoid confusion with deletion of object lines.
|
||||
* Method getDictvalue has been renamed into getDictionaryValue to match camel case rule.
|
||||
* To execute shell or command line command, your code must never use method like exec, shell_exec, popen, .. but must use the built-in
|
||||
method executeCLI() available into core/class/utils.class.php
|
||||
* Class file expeditionbatch.class.php renamed to expeditionlinebatch.class.php
|
||||
* ExpeditionLineBatch::fetchAll is not static anymore and first parameter $db is removed
|
||||
* ExtraFields->showOutputField parameter 4 'extrafieldsobjectkey' is now required
|
||||
* CommonObject method add_object_linked now sets targettype to 'mymodule_myobject' instead of 'myobject',
|
||||
you can use hook 'setLinkedObjectSourceTargetType' to set your usual targettype
|
||||
|
||||
|
||||
***** ChangeLog for 14.0.5 compared to 14.0.4 *****
|
||||
|
||||
FIX: 13.0: printFieldListWhere called twice on same query
|
||||
FIX: 14.0.4 fatal error on cron list.
|
||||
FIX: #19476
|
||||
FIX: #19564
|
||||
FIX: #19651
|
||||
FIX: Accountancy - SQL error on subledger account search in journal
|
||||
FIX: apply eldy's suggestion to not overwrite existing extrafields of $line
|
||||
FIX: Can't close a down payment if paid with credit notes.
|
||||
FIX: better compatibility with multicompany
|
||||
FIX: contact card: bad colspan value for separator extrafield in creation/modification form
|
||||
FIX: discounts are applied both when fetching the best supplier price and when displaying it
|
||||
FIX: double display for contact categorie on societe create card
|
||||
FIX: fatal error on cron list.
|
||||
FIX: holiday list: only mass delete if leave request is not in draft, canceled or refused, like in card
|
||||
FIX: holiday mass deletion: correct return of record deleted
|
||||
FIX: Holiday month report
|
||||
FIX: info tab on customer invoice record not found
|
||||
FIX: line extrafields are inoperative in dispatch cards even when they exist
|
||||
FIX: list of categories in stats of supplier invoices
|
||||
FIX: missing default value for more comprehensive
|
||||
FIX: multicurrency: fields in discount unitialized when creating deposit
|
||||
FIX: Navigation on bank transaction list
|
||||
FIX: Can't edit a bank transaction due to bad permission check.
|
||||
FIX: Option MAIN_DIRECT_STATUS_UPDATE broken. Ajax on/off not saving value in DB after updating to version >=12
|
||||
FIX: postgresql compatibility, "" as is not authorized
|
||||
FIX: printFieldListWhere called twice (at different locations) for the same SQL query, can result in syntax errors
|
||||
FIX: select too large into addrights (pb of missing parenthesis)
|
||||
FIX: set optional from post, we can't untick boolean field on product card
|
||||
FIX: Take into consideration work leave over serveral months
|
||||
FIX: test if method exist on wrong object
|
||||
FIX: title for nature of third party in company list
|
||||
FIX: Urgent onglet contact inaccessible depuis une facture
|
||||
FIX: wrong syntax of sql request
|
||||
|
||||
***** ChangeLog for 14.0.4 compared to 14.0.3 *****
|
||||
|
||||
FIX: $totalarray is overwritten, totals were lost
|
||||
FIX: 13.0 - due to a typo in the 'mode' parameter, the "first name" column of the list of members displays the full name
|
||||
FIX: 13.0: end date required to edit a ticket message
|
||||
FIX: 13.0 feedback of PR #18993: make ticket messages punctual events with attr percentage = -1
|
||||
FIX: 13.0 PR #18993: add comment on modified part
|
||||
FIX: 13.0: sometimes firstname was mistyped as fistname
|
||||
FIX: 14.0 - civility field of private third party creation form has inadequate width
|
||||
FIX: 14.0 - civility field width inadequate due to select2 calculating the width while the field has no width (display: none)
|
||||
FIX: 14.0 - due to a typo in the 'mode' parameter, the "first name" co…
|
||||
FIX: #18634 : Problem of virtual stock with reception module enabled
|
||||
FIX: #18695 Added ref_ext to supplier invoice
|
||||
FIX: #18698 Supplier invoice list - "alert" checkbox not working
|
||||
FIX: #18735
|
||||
FIX: #18767 : Adherent delete
|
||||
FIX: #18797
|
||||
FIX: #18854
|
||||
FIX: #18875 in v14
|
||||
FIX: #18910
|
||||
FIX: #18910 : MRP List SQL query syntax error with more than one extrafileds.
|
||||
FIX: #18912 Accountancy - SQL error when custom group is added without country defined
|
||||
FIX: #18934 on-registration in the extrafieldsline database for deliveries
|
||||
FIX: #18968
|
||||
FIX: #19008
|
||||
FIX: #19014 - the properties of some fields are not updated when you submit the form
|
||||
FIX: #19210
|
||||
FIX: #19214 : PostgreSQL error on admin/limits.php
|
||||
FIX: #19241 Project - Fix display salary in overview
|
||||
FIX: #19305
|
||||
FIX: 2 columns for total labels
|
||||
FIX: Accountancy - Format Quadra export - Missing line type C to create automaticly a subledger account with label
|
||||
FIX: Accountancy - If deposit invoice is used, force binding in deposit accounting account to solve transaction
|
||||
FIX: Accountancy - Missing specific filename for export on format FEC2, Ciel & repare it
|
||||
FIX: Accountancy - Option of export popup are inverted
|
||||
FIX: Accountancy - PHP8
|
||||
FIX: Accountancy - Product admin - SQL error when we affect accounting account with product_perentity activated
|
||||
FIX: Accountancy simplified - Salaries are not present in report
|
||||
FIX: Accountancy - Some correction on export name
|
||||
FIX: Accountancy - Trunc code_journal to 2 in format XIMPORT (Ciel, Sage50)
|
||||
FIX: add warehouse in projects' overview count
|
||||
FIX: also on customer index for automatic binding
|
||||
FIX: Attachment of pdf into shipment when sending email
|
||||
FIX: autocalculation of the supplier price in main currency.
|
||||
FIX: avoid warning if $categories is an id
|
||||
FIX: bad sign of amount stored for multicurrency columns on credit notes
|
||||
FIX: Bad use of a forced contact of another company on PDF/ODT documents
|
||||
FIX: Bad use of dol_concatdesc()
|
||||
FIX: Button text on proposal card for create a invoice
|
||||
FIX: calculateCosts of BOM must not be included into fetch
|
||||
FIX: calculation of balance in conciliation page on desc sorting.
|
||||
FIX: card.php
|
||||
FIX: Change date format of the inventorycode to be equal as mass stock transfert
|
||||
FIX: check if greater 0
|
||||
FIX: close cash with some terminals in TakePOS
|
||||
FIX: compatibility with Multicompany
|
||||
FIX: consistent UX when calling a tab from the invoice card with empty ref/id
|
||||
FIX: default language defined for IN country
|
||||
FIX: Expense report - In edit mode, field qty doesn't accept decimal unlike the create mode
|
||||
FIX: fetch of product with modulebuilder load too much data
|
||||
FIX: filter for export of accounting documents
|
||||
FIX: Filter on categories
|
||||
FIX: generate documents with PDF options
|
||||
FIX: indentation
|
||||
FIX: init hookmanager after loading $conf values
|
||||
FIX: invoice: inpossible to create an invoice because of very bad check + warnings when trying to print tabs for invoice with no ID
|
||||
FIX: legal issue on expense report pdf (must also show price without tax)
|
||||
FIX: list of categories in stats of supplier invoices
|
||||
FIX: load tranlate array after setting lang
|
||||
FIX: lost superadmin grade after edit user card
|
||||
FIX: missing filter status=1 on rss feeds
|
||||
FIX: missing permission check reported by me@lainwir3d.net on product api
|
||||
FIX: missing return status
|
||||
FIX: missing sql filter by entity
|
||||
FIX: move fetch_optionnal into $ac_static->fetch()
|
||||
FIX: only a superadmin can modify entity
|
||||
FIX: only ones value is return for dictionaries
|
||||
FIX: optional visibility on create card
|
||||
FIX: payment style and html5 tags
|
||||
FIX: payment using wrong type in takepos when too many payment mode
|
||||
FIX: PR#18931 Remove useless explicit call to dol_shutdown
|
||||
FIX: Product accountancy affectation with product_perentity activated (PR #18620)
|
||||
FIX: products/services card: hidden extrafields were overridden
|
||||
FIX: project task list: extrafields could not be displayed
|
||||
FIX: Propal list - Problem of pagination on date
|
||||
FIX: reload user lang
|
||||
FIX: Remove not complete order from the virtual stock
|
||||
FIX: Replenish: SQL error when no warehouse has been created + Warning when there are no warehouses
|
||||
FIX: resource list : Use standard code to handle list filters
|
||||
FIX: restrictedArea for payment delete
|
||||
FIX: Ret PR
|
||||
FIX: second approval back in stable feature as is the setting for minimum amount (last part from PR#14286)
|
||||
FIX: selected lines on supplier invoice create
|
||||
FIX: Selection of type "people" for membership must hide the company
|
||||
FIX: select list of orders not complete when field type of company is on
|
||||
FIX: show end hours in events linked to objects
|
||||
FIX: support of localtax on expense report
|
||||
FIX: task time: can't filter by user with pgsql + show error message
|
||||
FIX: task time: keep on using natural_search
|
||||
FIX: tcpdf vulnerability to roman numeral bomb, cf. tecnickom/TCPDF issue #315
|
||||
FIX: Test when date of invoie is in future (pb with TZ and offset)
|
||||
FIX: Ticket - Card - Wrong font awesome library
|
||||
FIX: Ticket - Duplicate field project when we create ticket from project
|
||||
FIX: translation into email for member at membership validation.
|
||||
FIX: Travis Sanitize SQL
|
||||
FIX: unprivileged user can see task associated with a not allowed project
|
||||
FIX: URGENT: impossible to create an invoice
|
||||
FIX: Use of accent into filename of GED
|
||||
FIX: user date timezone offset
|
||||
FIX: User salary card - translation problem
|
||||
FIX: user without permission can set ticket subject
|
||||
FIX: We need a default price base type in variant creation case with multiprices when parent has been created with only one level price
|
||||
FIX: wrong array key value
|
||||
FIX: wrong check
|
||||
FIX: wrong position of error message
|
||||
Sync transifex.
|
||||
|
||||
***** ChangeLog for 14.0.3 compared to 14.0.2 *****
|
||||
|
||||
FIX: #18698 Supplier invoice list - "alert" checkbox not working
|
||||
FIX: #18735
|
||||
FIX: #18767 : Member delete
|
||||
FIX: #18854
|
||||
FIX: #18910 : MRP List SQL query syntax error with more than one extrafileds.
|
||||
FIX: Accountancy - Format Quadra export - Missing line type C to create automaticly a subledger account with label
|
||||
FIX: Accountancy - Missing specific filename for export on format FEC2, Ciel & repare it
|
||||
FIX: Accountancy - Option of export popup are inverted
|
||||
FIX: Accountancy - Some correction on export name
|
||||
FIX: Accountancy - Trunc code_journal to 2 in format XIMPORT (Ciel, Sage50)
|
||||
FIX: add warehouse in projects' overview count
|
||||
FIX: autocalculation of the supplier price in main currency.
|
||||
FIX: avoid warning if $categories is an id
|
||||
FIX: Bad use of a forced contact of another company on PDF/ODT documents
|
||||
FIX: Button text on proposal card to create a invoice
|
||||
FIX: calculateCosts of BOM must not be included into fetch
|
||||
FIX: check if greater 0
|
||||
FIX: default language defined for IN country
|
||||
FIX: fetch of product with modulebuilder load too much data
|
||||
FIX: Filter on categories
|
||||
FIX: indentation
|
||||
FIX: init hookmanager after loading $conf values
|
||||
FIX: legal issue on expense report pdf (must also show price without tax)
|
||||
FIX: missing filter status=1 on rss feeds
|
||||
FIX: move fetch_optionnal into $ac_static->fetch()
|
||||
FIX: payment using wrong type in takepos when too many payment mode
|
||||
FIX: Product accountancy affectation with product_perentity activated (PR #18620)
|
||||
FIX: products/services card: hidden extrafields were overridden
|
||||
FIX: Propal list - Problem of pagination on date
|
||||
FIX: selected lines on supplier invoice create
|
||||
FIX: Selection of type "people" for membership must hide the company
|
||||
FIX: select list of orders not complete when field type of company is on
|
||||
FIX: support of localtax on expense report
|
||||
FIX: task time: can't filter by user with pgsql + show error message
|
||||
FIX: task time: keep on using natural_search
|
||||
FIX: Test when date of invoie is in future (pb with TZ and offset)
|
||||
FIX: translation into email for member at membership validation.
|
||||
FIX: unprivileged user can see task associated with a not allowed project
|
||||
FIX: user without permission can set ticket subject
|
||||
|
||||
***** ChangeLog for 14.0.2 compared to 14.0.1 *****
|
||||
|
||||
FIX: #18353 Invoice list translation issue
|
||||
FIX: #18375 SQL Error on tasks statistics
|
||||
FIX: #18465
|
||||
FIX: #18484
|
||||
FIX: #18531
|
||||
FIX: #18542 REST API: set global $user variable to DolibarrApiAccess::user.
|
||||
FIX: #18544 Shipment REST API: load thirdparty object into the shipment before validating.
|
||||
FIX: #18544 Shipment rest api: load thirdparty object when validating
|
||||
FIX: #18565
|
||||
FIX: #18589 #18617
|
||||
FIX: #18591 : Remove double quotes of SQL Queries for postgresql compatibility
|
||||
FIX: #18666 Order / Shipment list: Don't SQL JOIN category table when not necessary.
|
||||
FIX: Accountancy - Some problems of length with general & subledger account
|
||||
FIX: add DISTINCT
|
||||
FIX: Add option $noescapecommand in executeCLI for better compatibility
|
||||
FIX: Add token to remove error when removing widget
|
||||
FIX: Add token when remove the last widget on home page
|
||||
FIX: an approved holiday can be canceled by an admin.
|
||||
FIX: better sql request
|
||||
FIX: change LOG_DEBUG with LOG_WARNING in syslog and remove sql error in syslog (already done)
|
||||
FIX: Collapsing of extrafields has disappeared.
|
||||
FIX: Date of payment of subscription must not be set to 1970-01-01.
|
||||
FIX: Export of website generates a package that contains a sql error
|
||||
FIX: Field already present in SQL request
|
||||
FIX: increase maxlength of password input
|
||||
FIX: invoice fetch not found syslog debug level instead of error
|
||||
FIX: Invoice list - Wrong name for column total_tva
|
||||
FIX: invoice validation: when checking if any vat rate has a negative amount, prevent false positives with -1E-14 amounts
|
||||
FIX: Manage credit note on situation invoice for calculate margin
|
||||
FIX: Menu List of project was not visible.
|
||||
FIX: migration script
|
||||
FIX: multicompany transverse mode compatibility
|
||||
FIX: option "Default value for field 'Refuse bulk emailings'"
|
||||
FIX: Recommended session.cookie_samesite must be 'Lax' not 'Strict'.
|
||||
FIX: Relative discount with high nb of decimals
|
||||
FIX: salary extrafields don't work and table is not well named
|
||||
FIX: Supplier invoice list - Wrong language key used
|
||||
FIX: wrong table_element_line
|
||||
FIX: wrong users count in multicompany transverse mode
|
||||
FIX: #yogosha6944 Protection against traversal path.
|
||||
|
||||
|
||||
***** ChangeLog for 14.0.1 compared to 14.0.0 *****
|
||||
|
||||
FIX: $conf->task used but it does not exist, use $conf->projet instead
|
||||
@@ -42,19 +505,6 @@ FIX: using Tulip, deposit mask was not saved
|
||||
FIX: #yogosha6907
|
||||
|
||||
|
||||
***** ChangeLog for 15.0.0 compared to 14.0.0 *****
|
||||
|
||||
For developers:
|
||||
---------------
|
||||
|
||||
WARNING:
|
||||
|
||||
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
|
||||
* Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook.
|
||||
* Old deprecated module "SimplePOS" has been completely removed. Use module "TakePOS" is you need a Point Of Sale.
|
||||
|
||||
|
||||
|
||||
***** ChangeLog for 14.0.0 compared to 13.0.0 *****
|
||||
|
||||
For users:
|
||||
@@ -283,6 +733,38 @@ Following changes may create regressions for some external modules, but were nec
|
||||
* Removed deprecated substitution key __REFCLIENT__ (replaced with __REF_CLIENT__)
|
||||
* Removed constant MAIN_COUNTRIES_IN_EEC. You can now set if country is in Europe or not from the dictionary of countries.
|
||||
* v14 seems to work correctly on PHP v8 but it generates a lot of verbose warnings. Currently, v14 i snot yet officialy supported with PHP 8.
|
||||
* To execute shell or command line command, your code must never use method like exec, shell_exec, popen, .. but must use the built-in
|
||||
method executeCLI() available into core/class/utils.class.php
|
||||
|
||||
|
||||
***** ChangeLog for 13.0.5 compared to 13.0.4 *****
|
||||
|
||||
FIX: 13.0: class CommandeFournisseurDispatch provides trigger for UPDATE but not for CREATE / DELETE
|
||||
FIX: #18389 Accountancy - Bug on LDcompta10 export for supplier invoice
|
||||
FIX: #18591 : Remove double quotes of SQL Queries for postgresql compatibility
|
||||
FIX: Accountancy - Debug Export Sage50 / CIEL Compta / CIEL Compta Evo (Format XIMPORT)
|
||||
FIX: Accountancy - Some problems of length with general & subledger account
|
||||
FIX: add DISTINCT
|
||||
FIX: an approved holiday can be canceled by an admin.
|
||||
FIX: autocalculation of the supplier price in main currency.
|
||||
FIX: better sql request
|
||||
FIX: cannot add time spend when column ref is not displayed
|
||||
FIX: compatibility postgre sql
|
||||
FIX: holiday card: hooks uninitialized
|
||||
FIX: Invoice - Missing button to reopen an abandoned situation invoice
|
||||
FIX: invoice validation: when checking if any VAT rate has a negative amount, prevent false positives with -1.0E-14 amounts
|
||||
FIX: list of categories in stats of supplier invoices
|
||||
FIX: Manage credit note on situation invoice for calculate margin
|
||||
FIX: method_exists needs object at first param
|
||||
FIX: move fetch_optionnal into $ac_static->fetch()
|
||||
FIX: multicompany transverse mode compatibility
|
||||
FIX: on supplier order, JOIN with product fourn price table must be done with fk_soc too to avoid display several times a same line (because of same supplier product ref)
|
||||
FIX: postgre filter select search extrafield
|
||||
FIX: products/services card: hidden extrafields were overridden
|
||||
FIX: shipping validation workflow: 'ORDER_NEW' trigger called from wrong object
|
||||
FIX: task time: can't filter by user with pgsql + show error message
|
||||
FIX: task time: keep on using natural_search
|
||||
FIX: wrong users count in multicompany transverse mode
|
||||
|
||||
|
||||
***** ChangeLog for 13.0.4 compared to 13.0.3 *****
|
||||
|
||||
16
README-FR.md
@@ -8,12 +8,10 @@ Il est simple d'utilisation et modulaire, vous permettant de n'activez que les f
|
||||
|
||||

|
||||
|
||||
|
||||
## LICENCE
|
||||
|
||||
Dolibarr est distribué sous les termes de la licence GNU General Public License v3+ ou supérieure.
|
||||
|
||||
|
||||
## INSTALLER DOLIBARR
|
||||
|
||||
### Configuration simple
|
||||
@@ -54,7 +52,6 @@ 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:
|
||||
@@ -65,14 +62,12 @@ Pour mettre à jour Dolibarr depuis une vieille version vers celle ci:
|
||||
- Au prochain accès, Dolibarr proposera la page de "mise à jour" des données (si nécessaire).
|
||||
Si un fichier install.lock existe pour verrouiller le processus de mise à jour, il sera demandé de le supprimer manuellement (vous devriez trouver le fichier install.lock dans le répertoire utilisé pour stocker les documents générés ou transférés sur le serveur. Dans la plupart des cas, c'est le répertoire appelé "documents")
|
||||
|
||||
*Note: Le processus de migration peut être lancé manuellement et plusieurs fois, sans risque, en appelant la page /install/*
|
||||
|
||||
Note: *Le processus de migration peut être lancé manuellement et plusieurs fois, sans risque, en appelant la page /install/*
|
||||
|
||||
## CE QUI EST NOUVEAU
|
||||
|
||||
See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) file.
|
||||
|
||||
|
||||
## CE QUE DOLIBARR PEUT FAIRE
|
||||
|
||||
### Modules principaux (tous optionnels)
|
||||
@@ -122,7 +117,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
|
||||
- Peux être multi-société par ajout du module externe multi-société.
|
||||
- Plusieurs thèmes visuels.
|
||||
- Application simple à utiliser.
|
||||
- Requiert PHP et MariaDb, Mysql ou Postgresql (Voir versions exactes sur https://wiki.dolibarr.org/index.php/Prérequis).
|
||||
- Requiert PHP et MariaDb, Mysql ou Postgresql (Voir versions exactes sur [https://wiki.dolibarr.org/index.php/Prérequis](https://wiki.dolibarr.org/index.php/Prérequis)).
|
||||
- Compatible avec toutes les offres Cloud du marché respectant les prérequis de base de données et PHP.
|
||||
- APIs.
|
||||
- Génération PDF et ODT des éléments (factures, propositions commerciales, commandes, bons expéditions, etc...)
|
||||
@@ -142,7 +137,6 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/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:
|
||||
@@ -152,18 +146,15 @@ Voici un liste de fonctionnalités pas encore gérées par Dolibarr:
|
||||
- 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)].
|
||||
|
||||
<a href="https://github.com/Dolibarr/dolibarr/graphs/contributors"><img src="https://opencollective.com/dolibarr/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
[](https://github.com/Dolibarr/dolibarr/graphs/contributors)
|
||||
|
||||
## CREDITS
|
||||
|
||||
@@ -171,7 +162,6 @@ Dolibarr est le résultat du travail de nombreux contributeurs depuis des année
|
||||
|
||||
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
|
||||
|
||||
137
README.md
@@ -4,6 +4,7 @@
|
||||

|
||||
[](https://php.net/)
|
||||
[](https://github.com/Dolibarr/dolibarr)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/5521)
|
||||
|
||||
Dolibarr ERP & CRM is a modern software package that helps manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda…).
|
||||
|
||||
@@ -43,7 +44,7 @@ You can use a web server and a supported database (MariaDB, MySQL or PostgreSQL)
|
||||
|
||||
On GNU/Linux, first check if your distribution has already packaged Dolibarr.
|
||||
|
||||
#### Generic install steps:
|
||||
#### Generic install steps
|
||||
|
||||
- Check that your installed PHP version is supported [see PHP support](https://wiki.dolibarr.org/index.php/Releases).
|
||||
|
||||
@@ -71,107 +72,107 @@ On GNU/Linux, first check if your distribution has already packaged Dolibarr.
|
||||
|
||||
- Follow the installer instructions
|
||||
|
||||
|
||||
### Saas/Cloud setup
|
||||
|
||||
If you don't have time to install it yourself, you can try some commercial 'ready to use' Cloud offers (See https://saas.dolibarr.org). However, this third solution is not free.
|
||||
|
||||
If you don't have time to install it yourself, you can try some commercial 'ready to use' Cloud offers (See [https://saas.dolibarr.org](https://saas.dolibarr.org)). However, this third solution is not free.
|
||||
|
||||
## UPGRADING
|
||||
|
||||
Dolibarr supports upgrading, usually without the need for any (commercial) support (depending on if you use any commercial extensions). It supports upgrading all the way from any version after 2.8 without breakage. This is unique in the ERP ecosystem and a benefit our users highly appreciate!
|
||||
|
||||
- At first make a backup of your Dolibarr files & than [see](https://wiki.dolibarr.org/index.php/Installation_-_Upgrade#Upgrade_Dolibarr)
|
||||
|
||||
- At first make a backup of your Dolibarr files & then [see](https://wiki.dolibarr.org/index.php/Installation_-_Upgrade#Upgrade_Dolibarr)
|
||||
- Check that your installed PHP version is supported by the new version [see PHP support](./doc/phpmatrix.md).
|
||||
- Overwrite all old files from 'dolibarr' directory with files provided into the new version's package.
|
||||
- At first next access, Dolibarr will redirect you to the "install/" page to follow the upgrade process.
|
||||
If an `install.lock` file exists to lock any other upgrade process, the application will ask you to remove the file manually (you should find the `install.lock` file in the directory used to store generated and uploaded documents, in most cases, it is the directory called "*documents*").
|
||||
|
||||
|
||||
## WHAT'S NEW
|
||||
|
||||
See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) file.
|
||||
|
||||
|
||||
## FEATURES
|
||||
|
||||
### Main application/modules (all optional)
|
||||
|
||||
- Third-Parties Management: Customers, Prospects (Leads) and/or Suppliers + Contacts
|
||||
- Members/Membership/Foundation management
|
||||
- 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
|
||||
Product Management
|
||||
|
||||
- Products and/or Services catalog
|
||||
- Stock / Warehouse management + Inventory
|
||||
- Barcodes
|
||||
- Batches / Lots / Serials
|
||||
- Product Variants
|
||||
- Bill of Materials (BOM)
|
||||
- Manufacturing Orders
|
||||
- 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)
|
||||
Customer/Sales Management
|
||||
|
||||
Supplier/Purchase Management
|
||||
- Suppliers/Vendors + Contacts
|
||||
- Supplier (price) requests
|
||||
- Purchase Orders management
|
||||
- Delivery/Receiption
|
||||
- Supplier Invoices/credit notes and payment management
|
||||
- INCOTERMS
|
||||
- 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)
|
||||
|
||||
Finance / Accounting
|
||||
- Invoices / Payments
|
||||
- Bank accounts management
|
||||
- Direct debit orders management (European SEPA)
|
||||
- Accounting management
|
||||
- Donations management
|
||||
- Loan management
|
||||
- Margins
|
||||
- Reports
|
||||
Supplier/Purchase Management
|
||||
|
||||
Collaboration
|
||||
- Shared calendar/agenda (with ical and vcal export for third party tools integration)
|
||||
- Projects & Tasks management
|
||||
- Ticket System
|
||||
- Suppliers/Vendors + Contacts
|
||||
- Supplier (price) requests
|
||||
- Purchase Orders management
|
||||
- Delivery/Receiption
|
||||
- Supplier Invoices/credit notes and payment management
|
||||
- INCOTERMS
|
||||
|
||||
Finance / Accounting
|
||||
|
||||
- Invoices / Payments
|
||||
- Bank accounts management
|
||||
- Direct debit orders management (European SEPA)
|
||||
- Accounting management
|
||||
- Donations management
|
||||
- Loan management
|
||||
- Margins
|
||||
- Reports
|
||||
|
||||
Collaboration
|
||||
|
||||
- Shared calendar/agenda (with ical and vcal export for third party tools integration)
|
||||
- Projects & Tasks management
|
||||
- Ticket System
|
||||
- Surveys
|
||||
|
||||
HR
|
||||
- Employee's leave requests management
|
||||
- Expense reports
|
||||
- Recruitment management
|
||||
- Timesheets
|
||||
HR
|
||||
|
||||
- Employee's leave requests management
|
||||
- Expense reports
|
||||
- Recruitment management
|
||||
- Timesheets
|
||||
|
||||
### Other application/modules
|
||||
|
||||
- Electronic Document Management (EDM)
|
||||
- Electronic Document Management (EDM)
|
||||
- Bookmarks management
|
||||
- Reporting
|
||||
- Data export/import
|
||||
- Barcodes
|
||||
- Barcodes
|
||||
- Margin calculations
|
||||
- LDAP connectivity
|
||||
- ClickToDial integration
|
||||
- Mass emailing
|
||||
- RSS integration
|
||||
- Skype integration
|
||||
- Social platforms linking
|
||||
- Social platforms linking
|
||||
- Payment platforms integration (PayPal, Stripe, Paybox...)
|
||||
- Email-Collector
|
||||
|
||||
(around 100 modules available by default, 1000+ on the addon market place)
|
||||
|
||||
|
||||
### Other general features
|
||||
|
||||
- Localization in most major languages
|
||||
@@ -179,41 +180,35 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog)
|
||||
- Multi-Users and groups with finely grained rights
|
||||
- Multi-Currency
|
||||
- Multi-Company (by adding of an external module)
|
||||
|
||||
- Very user friendly and easy to use
|
||||
- customizable Dashboard
|
||||
- Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one)
|
||||
|
||||
- APIs (REST, SOAP)
|
||||
- Code that is easy to understand, maintain and develop (PHP with no heavy framework; trigger and hook architecture)
|
||||
|
||||
- Support a lot of country specific features:
|
||||
- Spanish Tax RE and ISPF
|
||||
- French NPR VAT rate (VAT called "Non Perçue Récupérable" for DOM-TOM)
|
||||
- Canadian double taxes (federal/province) and other countries using cumulative VAT
|
||||
- Tunisian tax stamp
|
||||
- Argentina invoice numbering using A,B,C...
|
||||
- Compatible with [European directives] (https://europa.eu/legislation_summaries/taxation/l31057_en.htm) (2006/112/CE ... 2010/45/UE)
|
||||
- Compatible with [European directives](https://europa.eu/legislation_summaries/taxation/l31057_en.htm) (2006/112/CE ... 2010/45/UE)
|
||||
- Compatible with European GDPR rules
|
||||
- ...
|
||||
- Flexible PDF & ODT generation for invoices, proposals, orders...
|
||||
- …
|
||||
|
||||
- ...
|
||||
|
||||
### System Environment / Requirements
|
||||
|
||||
- PHP
|
||||
- MariaDB, MySQL or PostgreSQL
|
||||
- MariaDB, MySQL or PostgreSQL
|
||||
- Compatible with all Cloud solutions that match PHP & MySQL or PostgreSQL prerequisites.
|
||||
|
||||
See exact requirements on the [Wiki](https://wiki.dolibarr.org/index.php/Prerequisite)
|
||||
|
||||
|
||||
### Extending
|
||||
|
||||
Dolibarr can be extended with a lot of other external application or modules from third party developers available at the [DoliStore](https://www.dolistore.com).
|
||||
|
||||
|
||||
## WHAT DOLIBARR CAN'T DO YET
|
||||
|
||||
These are features that Dolibarr does **not** yet fully support:
|
||||
@@ -223,21 +218,18 @@ These are features that Dolibarr does **not** yet fully support:
|
||||
- No native embedded Webmail, but you can send email to contacts in Dolibarr with e.g. offers, invoices, etc.
|
||||
- Dolibarr can't do coffee (yet)
|
||||
|
||||
|
||||
## DOCUMENTATION
|
||||
|
||||
Administrator, user, developer and translator's documentations are available along with other community resources in the [Wiki](https://wiki.dolibarr.org).
|
||||
|
||||
|
||||
## CONTRIBUTING
|
||||
|
||||
This project exists thanks to all the people who contribute.
|
||||
This project exists thanks to all the people who contribute.
|
||||
Please read the instructions how to contribute (report a bug/error, a feature request, send code ...) [[Contribute](https://github.com/Dolibarr/dolibarr/blob/develop/.github/CONTRIBUTING.md)]
|
||||
|
||||
A view on Contributors:
|
||||
|
||||
<a href="https://github.com/Dolibarr/dolibarr/graphs/contributors"><img src="https://opencollective.com/dolibarr/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
[](https://github.com/Dolibarr/dolibarr/graphs/contributors)
|
||||
|
||||
## CREDITS
|
||||
|
||||
@@ -245,7 +237,6 @@ Dolibarr is the work of many contributors over the years and uses some fine PHP
|
||||
|
||||
See [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) file.
|
||||
|
||||
|
||||
## NEWS AND SOCIAL NETWORKS
|
||||
|
||||
Follow Dolibarr project on:
|
||||
@@ -256,8 +247,6 @@ Follow Dolibarr project on:
|
||||
- [YouTube](https://www.youtube.com/user/DolibarrERPCRM)
|
||||
- [GitHub](https://github.com/Dolibarr/dolibarr)
|
||||
|
||||
|
||||
### Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here. 🙏 [[Become a sponsor/backer](https://opencollective.com/dolibarr#backer)]
|
||||
|
||||
|
||||
40
SECURITY.md
@@ -4,26 +4,26 @@ This file contains some policies about the security reports on Dolibarr ERP CRM
|
||||
|
||||
## Supported Versions for security reports
|
||||
|
||||
| Version | Supported |
|
||||
| --------- | ------------------ |
|
||||
| <= 12.* | :x: |
|
||||
| >= 13.* | :white_check_mark: |
|
||||
|
||||
| Version | Supported |
|
||||
| ---------- | ---------------------- |
|
||||
| <= 14.0.4 | :x: |
|
||||
| >= 14.0.5+ | :white_check_mark: except CSRF attacks|
|
||||
| >= develop | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a vulnerability, please use GitHub security advisory at https://github.com/Dolibarr/dolibarr/security/advisories/new (if you have permissions) or alternatively send an email to security@dolibarr.org (for everybody)
|
||||
|
||||
To report a vulnerability, for a private report, please use GitHub security advisory at [https://github.com/Dolibarr/dolibarr/security/advisories/new](https://github.com/Dolibarr/dolibarr/security/advisories/new) (if you have permissions).
|
||||
Alternatively send an email to security@dolibarr.org (for everybody)
|
||||
|
||||
## Hunting vulnerabilities on Dolibarr
|
||||
|
||||
We believe that future of software is online SaaS. This means software are more and more critical and no technology is perfect. Working with skilled security researchers is crucial in identifying weaknesses in our technology.
|
||||
We believe that the future of software is online SaaS. This means software are more and more critical and no technology is perfect. Working with skilled security researchers is crucial in identifying weaknesses in our technology.
|
||||
|
||||
If you believe you've found a security bug in our service, we are happy to work with you to resolve the issue promptly and ensure you are fairly rewarded for your discovery.
|
||||
|
||||
Any type of denial of service attacks is strictly forbidden, as well as any interference with network equipment and Dolibarr infrastructure.
|
||||
|
||||
We recommand to install Dolibarr ERP CRM on your own server (as most Open Source software, download and use is free: https://www.dolibarr.org/download) to get access on every side of application.
|
||||
We recommand to install Dolibarr ERP CRM on your own server (as most Open Source software, download and use is free: [https://www.dolibarr.org/download](https://www.dolibarr.org/download)) to get access on every side of application.
|
||||
|
||||
### User Agent
|
||||
|
||||
@@ -31,22 +31,20 @@ If you try to find bug on Dolibarr, we recommend to append to your user-agent he
|
||||
|
||||
### Account access
|
||||
|
||||
You can install the web application yourself on your own platform/server so you get full access to application and sources. Download the zip of the files to put into your own web server virtual host from https://www.dolibarr.org/download
|
||||
|
||||
You can install the web application yourself on your own platform/server so you get full access to application and sources. Download the zip of the files to put into your own web server virtual host from [https://www.dolibarr.org/download](https://www.dolibarr.org/download)
|
||||
|
||||
## Eligibility and Responsible Disclosure
|
||||
|
||||
We are happy to thank everyone who submits valid reports which help us improve the security of Dolibarr however, only those that meet the following eligibility requirements will be "validated reports" (if not, we may close the report without any answer):
|
||||
We are happy to thank everyone who submits valid reports which help us improve the security of Dolibarr, however only those that meet the following eligibility requirements will be "validated reports" (if not, we may close the report without any answer):
|
||||
|
||||
You must be the first reporter of the vulnerability (duplicate reports are closed).
|
||||
|
||||
You must send a clear textual description of the report along with steps to reproduce the issue, include attachments such as screenshots or proof of concept code as necessary.
|
||||
|
||||
You must avoid tests that could cause degradation or interruption of our service (refrain from using automated tools, and limit yourself about requests per second), that's why we recommand to install softwate on your own platform.
|
||||
You must avoid tests that could cause degradation or interruption of our service (refrain from using automated tools, and limit yourself about requests per second), that's why we recommand to install software on your own platform.
|
||||
|
||||
You must not leak, manipulate, or destroy any user data of third parties to find your vulnerability.
|
||||
|
||||
|
||||
## Scope for qualified vulnerabilities
|
||||
|
||||
ONLY vulnerabilities discovered, when the following setup on test platform is used, are "valid":
|
||||
@@ -54,23 +52,22 @@ ONLY vulnerabilities discovered, when the following setup on test platform is us
|
||||
* $dolibarr_main_prod must be set to 1 into conf.php
|
||||
* $dolibarr_nocsrfcheck must be kept to the value 0 into conf.php (this is the default value)
|
||||
* $dolibarr_main_force_https must be set to something else than 0.
|
||||
* The constant MAIN_SECURITY_CSRF_WITH_TOKEN must be set to 1 into backoffice menu Home - Setup - Other (this protection should be set to 1 soon by default)
|
||||
* The constant MAIN_SECURITY_CSRF_WITH_TOKEN must be set to 3 into backoffice menu Home - Setup - Other (this protection should be set to 3 soon by default)
|
||||
* The module DebugBar and ModuleBuilder must NOT be enabled (by default, these modules are not enabled. They are developer tools)
|
||||
* ONLY security reports on modules provided by default and with the "stable" status are valid (troubles into "experimental", "developement" or external modules are not valid vulnerabilities).
|
||||
* The root of web server must link to htdocs and the documents directory must be outside of the web server root (this is the default when using the default installer but may differs with external installer).
|
||||
* The web server setup must be done so only the documents directory is in write mode. The root directory called htdocs must be readonly.
|
||||
* CSRF attacks are accepted when using a POST URL, but when using GET URL, they are validated only for creating, updating or deleting data resctricted from pages restricted to admin users.
|
||||
* The web server setup must be done so that only the documents directory is in write mode. The root directory called htdocs must be read-only.
|
||||
* CSRF attacks are accepted but double check that you have set MAIN_SECURITY_CSRF_WITH_TOKEN to value 3.
|
||||
* Ability for a high level user to edit web site pages into the CMS by including HTML or Javascript is an expected feature. Vulnerabilities into the website module are validated only if HTML or Javascript injection can be done by a non allowed user.
|
||||
|
||||
Scope is the web application (back office) and the APIs.
|
||||
|
||||
|
||||
## Qualifying vulnerabilities for reporting
|
||||
|
||||
* Remote code execution (RCE)
|
||||
* Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA)
|
||||
* Code injections (HTML, JS, SQL, PHP, ...)
|
||||
* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose or into module "Web site" when permission to edit website content is allowed).
|
||||
* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose) and except into module "Web site" when permission to edit website content is allowed (injecting any data in this case is allowed too).
|
||||
* Cross-Site Requests Forgery (CSRF) with real security impact (when using GET URLs, CSRF are qualified only for creating, updating or deleting data from pages restricted to admin users)
|
||||
* Open redirect
|
||||
* Broken authentication & session management
|
||||
@@ -81,7 +78,6 @@ Scope is the web application (back office) and the APIs.
|
||||
* Software version disclosure (for non admin users only)
|
||||
* Stack traces or path disclosure (for non admin users only)
|
||||
|
||||
|
||||
## Non-qualifying vulnerabilities for reporting
|
||||
|
||||
* "Self" XSS
|
||||
@@ -90,9 +86,8 @@ Scope is the web application (back office) and the APIs.
|
||||
* Clickjacking/UI redressing
|
||||
* Physical or social engineering attempts or issues that require physical access to a victim’s computer/device
|
||||
* Presence of autocomplete attribute on web forms
|
||||
* Vulnerabilities affecting outdated browsers or platforms
|
||||
* Vulnerabilities affecting outdated browsers or platforms, or vulnerabilities inside browsers themself.
|
||||
* Logout and other instances of low-severity Cross-Site Request Forgery
|
||||
* Missing cookie flags
|
||||
* Missing security-related HTTP headers which do not lead directly to a vulnerability
|
||||
* Reports from automated web vulnerability scanners (Acunetix, Vega, etc.) that have not been validated
|
||||
* Invalid or missing SPF (Sender Policy Framework) records (Incomplete or missing SPF/DKIM/DMARC)
|
||||
@@ -100,4 +95,3 @@ Scope is the web application (back office) and the APIs.
|
||||
* Software version or private IP disclosure when logged user is admin
|
||||
* Stack traces or path disclosure when logged user is admin
|
||||
* Any vulnerabilities due to a configuration different than the one defined into chapter "Scope for qualified vulnerabilities".
|
||||
|
||||
|
||||
@@ -39,15 +39,13 @@ RUN chmod +x /usr/local/bin/docker-run.sh
|
||||
|
||||
RUN pecl install xdebug && docker-php-ext-enable xdebug
|
||||
RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so"' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.remote_autostart=1' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.remote_enable=1' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.default_enable=1' >> ${PHP_INI_DIR}/php.ini
|
||||
#RUN echo 'xdebug.remote_host=docker.host' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.remote_port=9000' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.remote_connect_back=1' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.profiler_enable=0' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.remote_log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
|
||||
#RUN echo 'localhost docker.host' >> /etc/hosts
|
||||
RUN echo 'xdebug.mode=debug' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.start_with_request=yes' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.client_host=host.docker.internal' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.client_port=9003' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.discover_client_host=true' >> ${PHP_INI_DIR}/php.ini
|
||||
#RUN echo 'xdebug.log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
|
||||
RUN echo 'xdebug.idekey="netbeans-xdebug"' >> ${PHP_INI_DIR}/php.ini
|
||||
|
||||
# set up sendmail config, to use maildev
|
||||
RUN echo "account default" > /etc/msmtprc
|
||||
@@ -57,7 +55,6 @@ RUN echo "host mail" >> /etc/msmtprc
|
||||
RUN echo "from local@localdomain.com" >> /etc/msmtprc
|
||||
RUN echo "domain localhost.localdomain" >> /etc/msmtprc
|
||||
RUN echo "sendmail_path=/usr/bin/msmtp -t" >> /usr/local/etc/php/conf.d/php-sendmail.ini
|
||||
RUN echo "localhost localhost.localdomain" >> /etc/hosts
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ services:
|
||||
networks:
|
||||
- internal-pod
|
||||
- external-pod
|
||||
extra_hosts:
|
||||
- "localhost.localdomain:127.0.0.1"
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
mail:
|
||||
image: maildev/maildev
|
||||
|
||||
@@ -239,10 +239,18 @@ fclose($fp);
|
||||
if (empty($buildzip)) {
|
||||
print "File ".$outputfile." generated\n";
|
||||
} else {
|
||||
$result = dol_compress_file($outputfile, $outputfile.'.zip');
|
||||
if ($result > 0) {
|
||||
dol_delete_file($outputfile);
|
||||
print "File ".$outputfile.".zip generated\n";
|
||||
if ($buildzip == '1' || $buildzip == 'zip') {
|
||||
$result = dol_compress_file($outputfile, $outputfile.'.zip', 'zip');
|
||||
if ($result > 0) {
|
||||
dol_delete_file($outputfile);
|
||||
print "File ".$outputfile.".zip generated\n";
|
||||
}
|
||||
} elseif ($buildzip == '2' || $buildzip == 'gz') {
|
||||
$result = dol_compress_file($outputfile, $outputfile.'.gz', 'gz');
|
||||
if ($result > 0) {
|
||||
dol_delete_file($outputfile);
|
||||
print "File ".$outputfile.".gz generated\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,13 @@ This files describe steps made by Dolibarr packaging team to make a
|
||||
beta version of Dolibarr, step by step.
|
||||
|
||||
- Check all files are commited.
|
||||
- Update version/info in ChangeLog.
|
||||
To generate a changelog of a major new version x.y.0 (from develop repo), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a major new version x.y.0 (from x.y repo), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
- Update version/info in ChangeLog, for this you can:
|
||||
To generate a changelog of a major new version x.y.0 (from a repo on branch develop), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a major new version x.y.0 (from a repo on branch x.y repo), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
- To know number of lines changes: git diff --shortstat A B
|
||||
- Update version number with x.y.z-w in htdocs/filefunc.inc.php
|
||||
Recopy the content of the output file into the file ChangeLog.
|
||||
- Note: To know number of lines changes: git diff --shortstat A B
|
||||
- Update version number with x.y.z-w in file htdocs/filefunc.inc.php
|
||||
- Commit all changes.
|
||||
|
||||
- Run makepack-dolibarr.pl to generate all packages.
|
||||
@@ -24,7 +25,6 @@ To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dol
|
||||
(/home/dolibarr/wwwroot/files/lastbuild).
|
||||
|
||||
- Post a news on dolibarr.org/dolibarr.fr + social networks
|
||||
- Send mail on mailings-list
|
||||
|
||||
|
||||
***** Actions to do a RELEASE *****
|
||||
@@ -32,12 +32,13 @@ This files describe steps made by Dolibarr packaging team to make a
|
||||
complete release of Dolibarr, step by step.
|
||||
|
||||
- Check all files are commited.
|
||||
- Update version/info in ChangeLog.
|
||||
To generate a changelog of a major new version x.y.0 (from develop repo), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a major new version x.y.0 (from x.y repo), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
- Update version/info in ChangeLog, for this you can:
|
||||
To generate a changelog of a major new version x.y.0 (from a repo on branch develop), you can do "cd ~/git/dolibarr; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent develop) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a major new version x.y.0 (from a repo pn branch x.y), you can do "cd ~/git/dolibarr_x.y; git log `diff -u <(git rev-list --first-parent x.(y-1).0) <(git rev-list --first-parent x.y.0) | sed -ne 's/^ //p' | head -1`.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dolibarr_x.y; git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //" | grep -e '^FIX\|NEW' | sort -u | sed 's/FIXED:/FIX:/g' | sed 's/FIXED :/FIX:/g' | sed 's/FIX :/FIX:/g' | sed 's/FIX /FIX: /g' | sed 's/NEW :/NEW:/g' | sed 's/NEW /NEW: /g' > /tmp/aaa"
|
||||
- To know number of lines changes: git diff --shortstat A B
|
||||
- Update version number with x.y.z in htdocs/filefunc.inc.php
|
||||
Recopy the content of the output file into the file ChangeLog.
|
||||
- Note: To know the number of lines changes: git diff --shortstat A B
|
||||
- Update version number with x.y.z in file htdocs/filefunc.inc.php
|
||||
- Commit all changes.
|
||||
|
||||
- Run makepack-dolibarr.pl to generate all packages.
|
||||
@@ -52,4 +53,3 @@ To generate a changelog of a maintenance version x.y.z, you can do "cd ~/git/dol
|
||||
on server to point to new files (used by some web sites).
|
||||
|
||||
- Post a news on dolibarr.org/dolibarr.fr + social networks
|
||||
- Send mail on mailings-list
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
README (English)
|
||||
##################################################
|
||||
Building PAD files
|
||||
http://pad.asp-software.org/padgen.php
|
||||
##################################################
|
||||
|
||||
This directory contains files and docs used to build
|
||||
|
||||
@@ -30,7 +30,7 @@ return "Regis Houssin";
|
||||
# script_dolibarr_versions()
|
||||
sub script_dolibarr_versions
|
||||
{
|
||||
return ( "12.0.3", "11.0.5", "10.0.7", "9.0.4", "8.0.6", "7.0.5" );
|
||||
return ( "14.0.5", "13.0.5", "12.0.5", "11.0.5", "10.0.7", "9.0.4", "8.0.6", "7.0.5" );
|
||||
}
|
||||
|
||||
sub script_dolibarr_release
|
||||
@@ -400,6 +400,8 @@ sub script_dolibarr_check_latest
|
||||
{
|
||||
local ($ver) = @_;
|
||||
local @vers = &osdn_package_versions("dolibarr",
|
||||
$ver >= 14.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
|
||||
$ver >= 13.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
|
||||
$ver >= 12.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
|
||||
$ver >= 11.0 ? "dolibarr\\-(11\\.0\\.[0-9\\.]+)\\.tgz" :
|
||||
$ver >= 10.0 ? "dolibarr\\-(10\\.0\\.[0-9\\.]+)\\.tgz" :
|
||||
|
||||
@@ -166,7 +166,6 @@ done >>%{name}.lang
|
||||
%_datadir/dolibarr/htdocs/blockedlog
|
||||
%_datadir/dolibarr/htdocs/bookmarks
|
||||
%_datadir/dolibarr/htdocs/bom
|
||||
%_datadir/dolibarr/htdocs/cashdesk
|
||||
%_datadir/dolibarr/htdocs/categories
|
||||
%_datadir/dolibarr/htdocs/collab
|
||||
%_datadir/dolibarr/htdocs/comm
|
||||
|
||||
@@ -247,7 +247,6 @@ done >>%{name}.lang
|
||||
%_datadir/dolibarr/htdocs/blockedlog
|
||||
%_datadir/dolibarr/htdocs/bookmarks
|
||||
%_datadir/dolibarr/htdocs/bom
|
||||
%_datadir/dolibarr/htdocs/cashdesk
|
||||
%_datadir/dolibarr/htdocs/categories
|
||||
%_datadir/dolibarr/htdocs/collab
|
||||
%_datadir/dolibarr/htdocs/comm
|
||||
|
||||
@@ -163,7 +163,6 @@ done >>%{name}.lang
|
||||
%_datadir/dolibarr/htdocs/blockedlog
|
||||
%_datadir/dolibarr/htdocs/bookmarks
|
||||
%_datadir/dolibarr/htdocs/bom
|
||||
%_datadir/dolibarr/htdocs/cashdesk
|
||||
%_datadir/dolibarr/htdocs/categories
|
||||
%_datadir/dolibarr/htdocs/collab
|
||||
%_datadir/dolibarr/htdocs/comm
|
||||
|
||||
@@ -174,7 +174,6 @@ done >>%{name}.lang
|
||||
%_datadir/dolibarr/htdocs/blockedlog
|
||||
%_datadir/dolibarr/htdocs/bookmarks
|
||||
%_datadir/dolibarr/htdocs/bom
|
||||
%_datadir/dolibarr/htdocs/cashdesk
|
||||
%_datadir/dolibarr/htdocs/categories
|
||||
%_datadir/dolibarr/htdocs/collab
|
||||
%_datadir/dolibarr/htdocs/comm
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
"ext-curl" : "*",
|
||||
"ckeditor/ckeditor" : "4.12.1",
|
||||
"mike42/escpos-php" : "2.2",
|
||||
"mobiledetect/mobiledetectlib" : "2.8.34",
|
||||
"mobiledetect/mobiledetectlib" : "2.8.39",
|
||||
"phpoffice/phpexcel" : "1.8.2",
|
||||
"restler/framework" : "3.0.0-RC6",
|
||||
"tecnickcom/tcpdf" : "6.3.2",
|
||||
"nnnick/chartjs" : "^2.9",
|
||||
"stripe/stripe-php" : "6.43.1",
|
||||
"maximebf/debugbar" : "1.15.1",
|
||||
"symfony/var-dumper" : "3"
|
||||
"symfony/var-dumper" : "3.2"
|
||||
},
|
||||
"require-dev" : {
|
||||
"php-parallel-lint/php-parallel-lint" : "^0",
|
||||
@@ -59,4 +59,4 @@
|
||||
"ext-zip" : "ODT, Excel and file compression support",
|
||||
"ext-xml" : "Excel support"
|
||||
}
|
||||
}
|
||||
}
|
||||
2349
composer.lock
generated
@@ -111,6 +111,10 @@ with
|
||||
// DOL CHANGE If we keep this, the image is not visible on pages after the first one.
|
||||
//var_dump($file.' '.(!@TCPDF_STATIC::file_exists($file)));
|
||||
//return false;
|
||||
$tfile = str_replace(' ', '%20', $file);
|
||||
if (@TCPDF_STATIC::file_exists($tfile)) {
|
||||
$file = $tfile;
|
||||
}
|
||||
}
|
||||
|
||||
* Replace in tcpdf.php
|
||||
@@ -168,6 +172,18 @@ In htdocs/includes/tecnickcom/tcpdf/tcpdf.php
|
||||
- protected $default_monospaced_font = 'courier';
|
||||
+ protected $default_monospaced_font = 'freemono';
|
||||
|
||||
* In tecnickcom/tcpdf/include/tcpdf_static, in function intToRoman, right at the beginning
|
||||
of the function, replace:
|
||||
|
||||
$roman = '';
|
||||
|
||||
with:
|
||||
|
||||
$roman = '';
|
||||
if ($number >= 4000) {
|
||||
// do not represent numbers above 4000 in Roman numerals
|
||||
return strval($number);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -188,6 +204,11 @@ with:
|
||||
with
|
||||
} elseif (($key == '/Index') AND ($v[0] == PDF_TYPE_ARRAY AND count($v[1]) >= 2)) {
|
||||
|
||||
* Fix php fatal error on php 8.0 on tcpdi.php
|
||||
while (list($k, $v) = each($value[1])) {
|
||||
with
|
||||
foreach ($value[1] as $k => $v) {
|
||||
|
||||
|
||||
|
||||
JSGANTT:
|
||||
@@ -218,11 +239,13 @@ JCROP:
|
||||
* Remove analytics tag into file index.html
|
||||
|
||||
|
||||
|
||||
JQUERYFILETREE:
|
||||
---------------
|
||||
* Remove directory htdocs/includes/jquery/plugins/jqueryFileTree/connectors
|
||||
|
||||
|
||||
|
||||
RESTLER:
|
||||
--------
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ This directory contains samples of code to use Dolibarr business classes to buil
|
||||
external interfaces that need to read/update data from/into Dolibarr.
|
||||
|
||||
You can also have a look at the Dolibarr doxygen doc that describes all files and classes:
|
||||
http://www.dolibarr.org/html_doxygen/index.html
|
||||
https://doxygen.dolibarr.org/
|
||||
|
||||
@@ -3,11 +3,26 @@
|
||||
#
|
||||
# Use this sample to search into a ldap
|
||||
#
|
||||
# ldapsearch -h hostname -x
|
||||
# ldapsearch -h hostname -x -b "ou=people,dc=teclib,dc=infra"
|
||||
# ldapsearch -h hostname -x -z 0 -b "o=somecompany.com" -D "cn=manager,o=somecompany.com" -w password "(objectclass=*)"
|
||||
# ldapsearch -h hostname -x -b "o=somecompany.com" -D "cn=manager,o=somecompany.com" -w password "(objectclass=*)"
|
||||
|
||||
# Anonymous access
|
||||
# ldapsearch -h hostname -p 389
|
||||
#
|
||||
# Login access (using a Bind DN)
|
||||
# ldapsearch -h hostname -p 389 -z 0 -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password
|
||||
# ldapsearch -H ldap://hostname:389 -z 0 -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password
|
||||
# ldapsearch -d1 -H ldap://hostname:389 -x -z 0 -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password
|
||||
# ldapsearch -H ldap://hostname:389 -z 0 -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password
|
||||
#
|
||||
# Login access in SSL (using a Bind DN)
|
||||
# ldapsearch -H ldaps://hostnamme:636 -z 0 -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password -b "cn=users,dc=ldap,dc=test,dc=local
|
||||
# If it fails, you may try to use "hostname" that is real name of certificate.
|
||||
# You must also check that /etc/ldap/ldap.conf contains the line TLS_CACERT /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# What to search
|
||||
# ldapsearch -h hostname -p 389 -x -D "uid=root,cn=users,dc=ldap,dc=test,dc=local" -w password -b "cn=users,dc=ldap,dc=test,dc=local"
|
||||
# ldapsearch -h hostname -p 389 -x -D "cn=manager,o=somecompany.com" -w password -b "ou=people,dc=teclib,dc=infra"
|
||||
# ldapsearch -h hostname -p 389 -x -D "cn=manager,o=somecompany.com" -w password -b "o=somecompany.com" "(objectclass=*)"
|
||||
#
|
||||
# Example to test a ldap search:
|
||||
# ldapsearch -h hostname -x -z 5 -b 'OU=Collaborateurs,OU=Utilisateurs,OU=MyCompany,DC=bocal,DC=lan' -D 'CN=UserAdmin,OU=Informatique,OU=Utilisateurs,OU=MyCompany,DC=bocal,DC=lan' -w password
|
||||
# ldapsearch -h hostname -p 389 -x -z 5 -b 'OU=Collaborateurs,OU=Utilisateurs,OU=MyCompany,DC=bocal,DC=lan' -D 'CN=UserAdmin,OU=Informatique,OU=Utilisateurs,OU=MyCompany,DC=bocal,DC=lan' -w password
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"npm": ">=5.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"zapier-platform-core": "11.0.1"
|
||||
"zapier-platform-core": "11.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^5.2.0",
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* WARNING, THIS WILL LOAD MASS DATA ON YOUR INSTANCE
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file dev/initdata/import-dbf.php
|
||||
* \brief Script example to create a table from a large DBF file (openoffice)
|
||||
* To purge data, you can have a look at purge-data.php
|
||||
*/
|
||||
// Test si mode batch
|
||||
$sapi_type = php_sapi_name();
|
||||
$script_file = basename(__FILE__);
|
||||
|
||||
$path = dirname(__FILE__) . '/';
|
||||
if (substr($sapi_type, 0, 3) == 'cgi') {
|
||||
echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Recupere root dolibarr
|
||||
$path = dirname($_SERVER["PHP_SELF"]);
|
||||
require $path . "./../htdocs/master.inc.php";
|
||||
require $path . "/includes/dbase.class.php";
|
||||
|
||||
// Global variables
|
||||
$version = DOL_VERSION;
|
||||
$confirmed = 1;
|
||||
$error = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
|
||||
@set_time_limit(0);
|
||||
print "***** " . $script_file . " (" . $version . ") pid=" . dol_getmypid() . " *****\n";
|
||||
dol_syslog($script_file . " launched with arg " . implode(',', $argv));
|
||||
|
||||
|
||||
$filepath = $argv[1];
|
||||
$filepatherr = $filepath . '.err';
|
||||
$startchar = empty($argv[2]) ? 0 : (int) $argv[2];
|
||||
$deleteTable = empty($argv[3]) ? 1 : 0;
|
||||
$startlinenb = empty($argv[3]) ? 1 : (int) $argv[3];
|
||||
$endlinenb = empty($argv[4]) ? 0 : (int) $argv[4];
|
||||
|
||||
if (empty($filepath)) {
|
||||
print "Usage: php $script_file myfilepath.dbf [removeChatColumnName] [startlinenb] [endlinenb]\n";
|
||||
print "Example: php $script_file myfilepath.dbf 0 2 1002\n";
|
||||
print "\n";
|
||||
exit(-1);
|
||||
}
|
||||
if (!file_exists($filepath)) {
|
||||
print "Error: File " . $filepath . " not found.\n";
|
||||
print "\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$ret = $user->fetch('', 'admin');
|
||||
if (!$ret > 0) {
|
||||
print 'A user with login "admin" and all permissions must be created to use this script.' . "\n";
|
||||
exit;
|
||||
}
|
||||
$user->getrights();
|
||||
|
||||
// Ask confirmation
|
||||
if (!$confirmed) {
|
||||
print "Hit Enter to continue or CTRL+C to stop...\n";
|
||||
$input = trim(fgets(STDIN));
|
||||
}
|
||||
|
||||
// Open input and output files
|
||||
$fhandle = dbase_open($filepath, 0);
|
||||
if (!$fhandle) {
|
||||
print 'Error: Failed to open file ' . $filepath . "\n";
|
||||
exit(1);
|
||||
}
|
||||
$fhandleerr = fopen($filepatherr, 'w');
|
||||
if (!$fhandleerr) {
|
||||
print 'Error: Failed to open file ' . $filepatherr . "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$langs->setDefaultLang($defaultlang);
|
||||
|
||||
$record_numbers = dbase_numrecords($fhandle);
|
||||
$table_name = substr(basename($filepath), 0, strpos(basename($filepath), '.'));
|
||||
print 'Info: ' . $record_numbers . " lines in file \n";
|
||||
$header = dbase_get_header_info($fhandle);
|
||||
if ($deleteTable) {
|
||||
$db->query("DROP TABLE IF EXISTS `$table_name`");
|
||||
}
|
||||
$sqlCreate = "CREATE TABLE IF NOT EXISTS `$table_name` ( `id` INT(11) NOT NULL AUTO_INCREMENT ";
|
||||
$fieldArray = array("`id`");
|
||||
foreach ($header as $value) {
|
||||
$fieldName = substr(str_replace('_', '', $value['name']), $startchar);
|
||||
$fieldArray[] = "`$fieldName`";
|
||||
$sqlCreate .= ", `" . $fieldName . "` VARCHAR({$value['length']}) NULL DEFAULT NULL ";
|
||||
}
|
||||
$sqlCreate .= ", PRIMARY KEY (`id`)) ENGINE = InnoDB";
|
||||
$resql = $db->query($sqlCreate);
|
||||
if ($resql !== false) {
|
||||
print "Table $table_name created\n";
|
||||
} else {
|
||||
var_dump($db->errno());
|
||||
print "Impossible : " . $sqlCreate . "\n";
|
||||
die();
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$nboflines++;
|
||||
|
||||
$fields = implode(',', $fieldArray);
|
||||
//var_dump($fieldArray);die();
|
||||
$maxLength = 0;
|
||||
for ($i = 1; $i <= $record_numbers; $i++) {
|
||||
if ($startlinenb && $i < $startlinenb) {
|
||||
continue;
|
||||
}
|
||||
if ($endlinenb && $i > $endlinenb) {
|
||||
continue;
|
||||
}
|
||||
$row = dbase_get_record_with_names($fhandle, $i);
|
||||
if ($row === false || (isset($row["deleted"]) && $row["deleted"] == '1')) {
|
||||
continue;
|
||||
}
|
||||
$sqlInsert = "INSERT INTO `$table_name`($fields) VALUES (null,";
|
||||
array_shift($row); // remove delete column
|
||||
foreach ($row as $value) {
|
||||
$sqlInsert .= "'" . $db->escape(utf8_encode($value)) . "', ";
|
||||
}
|
||||
replaceable_echo(implode("\t", $row));
|
||||
$sqlInsert = rtrim($sqlInsert, ', ');
|
||||
$sqlInsert .= ")";
|
||||
$resql = $db->query($sqlInsert);
|
||||
if ($resql === false) {
|
||||
print "Impossible : " . $sqlInsert . "\n";
|
||||
var_dump($row, $db->errno());
|
||||
die();
|
||||
}
|
||||
// $fields = (object) $row;
|
||||
// var_dump($fields);
|
||||
continue;
|
||||
}
|
||||
die();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// commit or rollback
|
||||
print "Nb of lines qualified: " . $nboflines . "\n";
|
||||
print "Nb of errors: " . $error . "\n";
|
||||
if ($mode != 'confirmforced' && ($error || $mode != 'confirm')) {
|
||||
print "Rollback any changes.\n";
|
||||
$db->rollback();
|
||||
} else {
|
||||
print "Commit all changes.\n";
|
||||
$db->commit();
|
||||
}
|
||||
|
||||
$db->close();
|
||||
fclose($fhandle);
|
||||
fclose($fhandleerr);
|
||||
|
||||
exit($error);
|
||||
|
||||
|
||||
/**
|
||||
* replaceable_echo
|
||||
*
|
||||
* @param string $message Message
|
||||
* @param int $force_clear_lines Force clear messages
|
||||
* @return void
|
||||
*/
|
||||
function replaceable_echo($message, $force_clear_lines = null)
|
||||
{
|
||||
static $last_lines = 0;
|
||||
|
||||
if (!is_null($force_clear_lines)) {
|
||||
$last_lines = $force_clear_lines;
|
||||
}
|
||||
|
||||
$toss = array();
|
||||
$status = 0;
|
||||
$term_width = exec('tput cols', $toss, $status);
|
||||
if ($status) {
|
||||
$term_width = 64; // Arbitrary fall-back term width.
|
||||
}
|
||||
|
||||
$line_count = 0;
|
||||
foreach (explode("\n", $message) as $line) {
|
||||
$line_count += count(str_split($line, $term_width));
|
||||
}
|
||||
|
||||
// Erasure MAGIC: Clear as many lines as the last output had.
|
||||
for ($i = 0; $i < $last_lines; $i++) {
|
||||
// Return to the beginning of the line
|
||||
echo "\r";
|
||||
// Erase to the end of the line
|
||||
echo "\033[K";
|
||||
// Move cursor Up a line
|
||||
echo "\033[1A";
|
||||
// Return to the beginning of the line
|
||||
echo "\r";
|
||||
// Erase to the end of the line
|
||||
echo "\033[K";
|
||||
// Return to the beginning of the line
|
||||
echo "\r";
|
||||
// Can be consolodated into
|
||||
// echo "\r\033[K\033[1A\r\033[K\r";
|
||||
}
|
||||
|
||||
$last_lines = $line_count;
|
||||
|
||||
echo $message . "\n";
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* WARNING, THIS WILL LOAD MASS DATA ON YOUR INSTANCE
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file dev/initdata/import-product.php
|
||||
* \brief Script example to insert products from a csv file.
|
||||
* To purge data, you can have a look at purge-data.php
|
||||
*/
|
||||
// Test si mode batch
|
||||
$sapi_type = php_sapi_name();
|
||||
$script_file = basename(__FILE__);
|
||||
$path = dirname(__FILE__) . '/';
|
||||
if (substr($sapi_type, 0, 3) == 'cgi') {
|
||||
echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Recupere root dolibarr
|
||||
$path = preg_replace('/importdb-products.php/i', '', $_SERVER["PHP_SELF"]);
|
||||
require $path . "../../htdocs/master.inc.php";
|
||||
require $path . "includes/dbase.class.php";
|
||||
include_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
|
||||
|
||||
//$delimiter = ',';
|
||||
//$enclosure = '"';
|
||||
//$linelength = 10000;
|
||||
//$escape = '/';
|
||||
// Global variables
|
||||
$version = DOL_VERSION;
|
||||
$confirmed = 1;
|
||||
$error = 0;
|
||||
|
||||
$tvas = [
|
||||
'1' => "20.00",
|
||||
'2' => "5.50",
|
||||
'3' => "0.00",
|
||||
'4' => "20.60",
|
||||
'5' => "19.60",
|
||||
];
|
||||
$tvasD = [
|
||||
'1' => "20",
|
||||
'2' => "5.5",
|
||||
'3' => "0",
|
||||
'4' => "20",
|
||||
'5' => "20",
|
||||
];
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
|
||||
@set_time_limit(0);
|
||||
print "***** " . $script_file . " (" . $version . ") pid=" . dol_getmypid() . " *****\n";
|
||||
dol_syslog($script_file . " launched with arg " . implode(',', $argv));
|
||||
|
||||
$table = $argv[1];
|
||||
|
||||
if (empty($argv[1])) {
|
||||
print "Error: Which table ?\n";
|
||||
print "\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$ret = $user->fetch('', 'admin');
|
||||
if (!$ret > 0) {
|
||||
print 'A user with login "admin" and all permissions must be created to use this script.' . "\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM `$table` WHERE 1";
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
while ($fields = $db->fetch_array($resql)) {
|
||||
$errorrecord = 0;
|
||||
if ($fields === false) {
|
||||
continue;
|
||||
}
|
||||
$nboflines++;
|
||||
|
||||
$produit = new Product($db);
|
||||
$produit->type = 0;
|
||||
$produit->status = 1;
|
||||
$produit->ref = trim($fields['REF']);
|
||||
if ($produit->ref == '') {
|
||||
continue;
|
||||
}
|
||||
print "Process line nb " . $j . ", ref " . $produit->ref;
|
||||
$produit->label = trim($fields['LIBELLE']);
|
||||
if ($produit->label == '') {
|
||||
$produit->label = $produit->ref;
|
||||
}
|
||||
if (empty($produit->label)) {
|
||||
continue;
|
||||
}
|
||||
//$produit->description = trim($fields[4] . "\n" . ($fields[5] ? $fields[5] . ' x ' . $fields[6] . ' x ' . $fields[7] : ''));
|
||||
// $produit->volume = price2num($fields[8]);
|
||||
// $produit->volume_unit = 0;
|
||||
$produit->weight = price2num($fields['MASSE']);
|
||||
$produit->weight_units = 0; // -3 = g
|
||||
//$produit->customcode = $fields[10];
|
||||
$produit->barcode = str_pad($fields['CODE'], 12, "0", STR_PAD_LEFT);
|
||||
$produit->barcode_type = '2';
|
||||
$produit->import_key = $fields['CODE'];
|
||||
|
||||
$produit->status = 1;
|
||||
$produit->status_buy = 1;
|
||||
|
||||
$produit->finished = 1;
|
||||
|
||||
// $produit->multiprices[0] = price2num($fields['TARIF0']);
|
||||
// $produit->multiprices[1] = price2num($fields['TARIF1']);
|
||||
// $produit->multiprices[2] = price2num($fields['TARIF2']);
|
||||
// $produit->multiprices[3] = price2num($fields['TARIF3']);
|
||||
// $produit->multiprices[4] = price2num($fields['TARIF4']);
|
||||
// $produit->multiprices[5] = price2num($fields['TARIF5']);
|
||||
// $produit->multiprices[6] = price2num($fields['TARIF6']);
|
||||
// $produit->multiprices[7] = price2num($fields['TARIF7']);
|
||||
// $produit->multiprices[8] = price2num($fields['TARIF8']);
|
||||
// $produit->multiprices[9] = price2num($fields['TARIF9']);
|
||||
// $produit->price_min = null;
|
||||
// $produit->price_min_ttc = null;
|
||||
// $produit->price = price2num($fields[11]);
|
||||
// $produit->price_ttc = price2num($fields[12]);
|
||||
// $produit->price_base_type = 'TTC';
|
||||
// $produit->tva_tx = price2num($fields[13]);
|
||||
$produit->tva_tx = (int) ($tvas[$fields['CODTVA']]);
|
||||
$produit->tva_npr = 0;
|
||||
// $produit->cost_price = price2num($fields[16]);
|
||||
//compta
|
||||
|
||||
$produit->accountancy_code_buy = trim($fields['COMACH']);
|
||||
$produit->accountancy_code_sell = trim($fields['COMVEN']);
|
||||
// $produit->accountancy_code_sell_intra=trim($fields['COMVEN']);
|
||||
// $produit->accountancy_code_sell_export=trim($fields['COMVEN']);
|
||||
// Extrafields
|
||||
// $produit->array_options['options_ecotaxdeee'] = price2num($fields[17]);
|
||||
|
||||
$produit->seuil_stock_alerte = $fields['STALERTE'];
|
||||
$ret = $produit->create($user, 0);
|
||||
if ($ret < 0) {
|
||||
print " - Error in create result code = " . $ret . " - " . $produit->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - Creation OK with ref " . $produit->ref . " - id = " . $ret;
|
||||
}
|
||||
|
||||
dol_syslog("Add prices");
|
||||
|
||||
// If we use price level, insert price for each level
|
||||
if (!$errorrecord && 1) {
|
||||
//$ret1 = $produit->updatePrice($produit->price_ttc, $produit->price_base_type, $user, $produit->tva_tx, $produit->price_min, 1, $produit->tva_npr, 0, 0, array());
|
||||
$ret1 = false;
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
if ($fields['TARIF' . ($i)] == 0) {
|
||||
continue;
|
||||
}
|
||||
$ret1 = $ret1 || $produit->updatePrice(price2num($fields['TARIF' . ($i)]), 'HT', $user, $produit->tva_tx, $produit->price_min, $i + 1, $produit->tva_npr, 0, 0, array()) < 0;
|
||||
}
|
||||
if ($ret1) {
|
||||
print " - Error in updatePrice result " . $produit->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - updatePrice OK";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dol_syslog("Add multilangs");
|
||||
// Add alternative languages
|
||||
// if (!$errorrecord && 1) {
|
||||
// $produit->multilangs['fr_FR'] = array('label' => $produit->label, 'description' => $produit->description, 'note' => $produit->note_private);
|
||||
// $produit->multilangs['en_US'] = array('label' => $fields[3], 'description' => $produit->description, 'note' => $produit->note_private);
|
||||
//
|
||||
// $ret = $produit->setMultiLangs($user);
|
||||
// if ($ret < 0) {
|
||||
// print " - Error in setMultiLangs result code = " . $ret . " - " . $produit->errorsToString();
|
||||
// $errorrecord++;
|
||||
// } else {
|
||||
// print " - setMultiLangs OK";
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
dol_syslog("Add stocks");
|
||||
// stocks
|
||||
if (!$errorrecord && $fields['STOCK'] != 0) {
|
||||
$rets = $produit->correct_stock($user, 1, $fields['STOCK'], 0, 'Stock importé');
|
||||
if ($rets < 0) {
|
||||
print " - Error in correct_stock result " . $produit->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - correct_stock OK";
|
||||
}
|
||||
}
|
||||
|
||||
//update date créa
|
||||
if (!$errorrecord) {
|
||||
$date = substr($fields['DATCREA'], 0, 4) . '-' . substr($fields['DATCREA'], 4, 2) . '-' . substr($fields['DATCREA'], 6, 2);
|
||||
$retd = $db->query("UPDATE `llx_product` SET `datec` = '$date 00:00:00' WHERE `llx_product`.`rowid` = $produit->id");
|
||||
if ($retd < 1) {
|
||||
print " - Error in update date créa result " . $produit->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - update date créa OK";
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
if ($errorrecord) {
|
||||
print( 'Error on record nb ' . $i . " - " . $produit->errorsToString() . "\n");
|
||||
var_dump($db);
|
||||
die();
|
||||
$error++; // $errorrecord will be reset
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
} else {
|
||||
die("error : $sql");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// commit or rollback
|
||||
print "Nb of lines qualified: " . $nboflines . "\n";
|
||||
print "Nb of errors: " . $error . "\n";
|
||||
$db->close();
|
||||
|
||||
exit($error);
|
||||
@@ -1,365 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* WARNING, THIS WILL LOAD MASS DATA ON YOUR INSTANCE
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file dev/initdata/import-product.php
|
||||
* \brief Script example to insert products from a csv file.
|
||||
* To purge data, you can have a look at purge-data.php
|
||||
*/
|
||||
// Test si mode batch
|
||||
$sapi_type = php_sapi_name();
|
||||
$script_file = basename(__FILE__);
|
||||
$path = dirname(__FILE__) . '/';
|
||||
if (substr($sapi_type, 0, 3) == 'cgi') {
|
||||
echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Recupere root dolibarr
|
||||
$path = preg_replace('/importdb-thirdparties.php/i', '', $_SERVER["PHP_SELF"]);
|
||||
require $path . "../../htdocs/master.inc.php";
|
||||
require $path . "includes/dbase.class.php";
|
||||
include_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
|
||||
|
||||
//$delimiter = ',';
|
||||
//$enclosure = '"';
|
||||
//$linelength = 10000;
|
||||
//$escape = '/';
|
||||
// Global variables
|
||||
$version = DOL_VERSION;
|
||||
$confirmed = 1;
|
||||
$error = 0;
|
||||
|
||||
$civilPrivate = array("MLLE",
|
||||
"MM",
|
||||
"MM/MADAME",
|
||||
"MME",
|
||||
"MME.",
|
||||
"MME²",
|
||||
"MMONSIEUR",
|
||||
"MMR",
|
||||
"MOBNSIEUR",
|
||||
"MOMSIEUR",
|
||||
"MON SIEUR",
|
||||
"MONDIAL",
|
||||
"MONIEUR",
|
||||
"MONJSIEUR",
|
||||
"MONNSIEUR",
|
||||
"MONRIEUR",
|
||||
"MONS",
|
||||
"MONSIEÕR",
|
||||
"MONSIER",
|
||||
"MONSIERU",
|
||||
"MONSIEU",
|
||||
"monsieue",
|
||||
"MONSIEUR",
|
||||
"Monsieur \"",
|
||||
"MONSIEUR \"",
|
||||
"MONSIEUR E",
|
||||
"MONSIEUR DENIS",
|
||||
"MONSIEUR ET MME",
|
||||
"MONSIEUR!",
|
||||
"MONSIEUR.",
|
||||
"MONSIEUR.MADAME",
|
||||
"MONSIEUR3",
|
||||
"MONSIEURN",
|
||||
"MONSIEURT",
|
||||
"MONSIEUR£",
|
||||
"MONSIEYR",
|
||||
"Monsigur",
|
||||
"MONSIIEUR",
|
||||
"MONSIUER",
|
||||
"MONSIZEUR",
|
||||
"MOPNSIEUR",
|
||||
"MOSIEUR",
|
||||
"MR",
|
||||
"Mr Mme",
|
||||
"Mr - MME",
|
||||
"MR BLANC",
|
||||
"MR ET MME",
|
||||
"mr mm",
|
||||
"MR OU MME",
|
||||
"Mr.",
|
||||
"MR/MME",
|
||||
"MRME",
|
||||
"MRR",
|
||||
"Mrs",
|
||||
"Mademoiselle",
|
||||
"MADAOME",
|
||||
"madamme",
|
||||
"MADAME",
|
||||
"M0NSIEUR",
|
||||
"M.et Madame",
|
||||
"M. ET MR",
|
||||
"M.",
|
||||
"M%",
|
||||
"M MME",
|
||||
"M ET MME",
|
||||
"M",
|
||||
"M CROCE",
|
||||
"M DIEVART",
|
||||
);
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
|
||||
@set_time_limit(0);
|
||||
print "***** " . $script_file . " (" . $version . ") pid=" . dol_getmypid() . " *****\n";
|
||||
dol_syslog($script_file . " launched with arg " . implode(',', $argv));
|
||||
|
||||
$table = $argv[1];
|
||||
|
||||
if (empty($argv[1])) {
|
||||
print "Error: Quelle table ?\n";
|
||||
print "\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$ret = $user->fetch('', 'admin');
|
||||
if (!$ret > 0) {
|
||||
print 'A user with login "admin" and all permissions must be created to use this script.' . "\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM `$table` WHERE 1 "; //ORDER BY REMISE DESC,`LCIVIL` DESC";
|
||||
$resql = $db->query($sql);
|
||||
//$db->begin();
|
||||
if ($resql) {
|
||||
while ($fields = $db->fetch_array($resql)) {
|
||||
$i++;
|
||||
$errorrecord = 0;
|
||||
|
||||
if ($startlinenb && $i < $startlinenb) {
|
||||
continue;
|
||||
}
|
||||
if ($endlinenb && $i > $endlinenb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nboflines++;
|
||||
|
||||
$object = new Societe($db);
|
||||
$object->import_key = $fields['CODE'];
|
||||
$object->state = 1;
|
||||
$object->client = 3;
|
||||
$object->fournisseur = 0;
|
||||
|
||||
$object->name = $fields['FCIVIL'] . ' ' . $fields['FNOM'];
|
||||
//$object->name_alias = $fields[0] != $fields[13] ? trim($fields[0]) : '';
|
||||
|
||||
$date = $fields['DATCREA'] ? $fields['DATCREA'] : ($fields['DATMOD'] ? $fields['DATMOD'] : '20200101');
|
||||
$object->code_client = 'CU' . substr($date, 2, 2) . substr($date, 4, 2) . '-' . str_pad(substr($fields['CODE'], 0, 5), 5, "0", STR_PAD_LEFT);
|
||||
|
||||
|
||||
$object->address = trim($fields['FADR1']);
|
||||
if ($fields['FADR2']) {
|
||||
$object->address .= "\n" . trim($fields['FADR2']);
|
||||
}
|
||||
if ($fields['FADR3']) {
|
||||
$object->address .= "\n" . trim($fields['FADR3']);
|
||||
}
|
||||
|
||||
$object->zip = trim($fields['FPOSTE']);
|
||||
$object->town = trim($fields['FVILLE']);
|
||||
if ($fields['FPAYS']) {
|
||||
$object->country_id = dol_getIdFromCode($db, trim(ucwords(strtolower($fields['FPAYS']))), 'c_country', 'label', 'rowid');
|
||||
} else {
|
||||
$object->country_id = 1;
|
||||
}
|
||||
$object->phone = trim($fields['FTEL']) ? trim($fields['FTEL']) : trim($fields['FCONTACT']);
|
||||
$object->phone = substr($object->phone, 0, 20);
|
||||
$object->fax = trim($fields['FFAX']) ? trim($fields['FFAX']) : trim($fields['FCONTACT']);
|
||||
$object->fax = substr($object->fax, 0, 20);
|
||||
$object->email = trim($fields['FMAIL']);
|
||||
// $object->idprof2 = trim($fields[29]);
|
||||
$object->tva_intra = str_replace(['.', ' '], '', $fields['TVAINTRA']);
|
||||
$object->tva_intra = substr($object->tva_intra, 0, 20);
|
||||
$object->default_lang = 'fr_FR';
|
||||
|
||||
$object->cond_reglement_id = dol_getIdFromCode($db, 'PT_ORDER', 'c_payment_term', 'code', 'rowid', 1);
|
||||
$object->multicurrency_code = 'EUR';
|
||||
|
||||
if ($fields['REMISE'] != '0.00') {
|
||||
$object->remise_percent = abs($fields['REMISE']);
|
||||
}
|
||||
|
||||
// $object->code_client = $fields[9];
|
||||
// $object->code_fournisseur = $fields[10];
|
||||
|
||||
|
||||
if ($fields['FCIVIL']) {
|
||||
$labeltype = in_array($fields['FCIVIL'], $civilPrivate) ? 'TE_PRIVATE' : 'TE_SMALL';
|
||||
$object->typent_id = dol_getIdFromCode($db, $labeltype, 'c_typent', 'code');
|
||||
}
|
||||
|
||||
// Set price level
|
||||
$object->price_level = $fields['TARIF'] + 1;
|
||||
// if ($labeltype == 'Revendeur')
|
||||
// $object->price_level = 2;
|
||||
|
||||
print "Process line nb " . $i . ", code " . $fields['CODE'] . ", name " . $object->name;
|
||||
|
||||
|
||||
// Extrafields
|
||||
$object->array_options['options_banque'] = $fields['BANQUE'];
|
||||
$object->array_options['options_banque2'] = $fields['BANQUE2'];
|
||||
$object->array_options['options_banquevalid'] = $fields['VALID'];
|
||||
|
||||
if (!$errorrecord) {
|
||||
$ret = $object->create($user);
|
||||
if ($ret < 0) {
|
||||
print " - Error in create result code = " . $ret . " - " . $object->errorsToString();
|
||||
$errorrecord++;
|
||||
var_dump($object->code_client, $db);
|
||||
die();
|
||||
} else {
|
||||
print " - Creation OK with name " . $object->name . " - id = " . $ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errorrecord) {
|
||||
dol_syslog("Set price level");
|
||||
$object->set_price_level($object->price_level, $user);
|
||||
}
|
||||
if (!$errorrecord && @$object->remise_percent) {
|
||||
dol_syslog("Set remise client");
|
||||
$object->set_remise_client($object->remise_percent, 'Importé', $user);
|
||||
}
|
||||
|
||||
dol_syslog("Add contact");
|
||||
// Insert an invoice contact if there is an invoice email != standard email
|
||||
if (!$errorrecord && ($fields['LCIVIL'] || $fields['LNOM'])) {
|
||||
$madame = array("MADAME",
|
||||
"MADEMOISELLE",
|
||||
"MELLE",
|
||||
"MLLE",
|
||||
"MM",
|
||||
"Mme",
|
||||
"MNE",
|
||||
);
|
||||
$monsieur = array("M",
|
||||
"M ET MME",
|
||||
"M MME",
|
||||
"M.",
|
||||
"M. MME",
|
||||
"M. OU Mme",
|
||||
"M.ou Madame",
|
||||
"MONSEUR",
|
||||
"MONSIER",
|
||||
"MONSIEU",
|
||||
"MONSIEUR",
|
||||
"monsieur:mme",
|
||||
"MONSIEUR¨",
|
||||
"MONSIEZUR",
|
||||
"MONSIUER",
|
||||
"MONSKIEUR",
|
||||
"MR",
|
||||
);
|
||||
$ret1 = $ret2 = 0;
|
||||
|
||||
$contact = new Contact($db);
|
||||
if (in_array($fields['LCIVIL'], $madame)) {
|
||||
// une dame
|
||||
$contact->civility_id = 'MME';
|
||||
$contact->lastname = $fields['LNOM'];
|
||||
} elseif (in_array($fields['LCIVIL'], $monsieur)) {
|
||||
// un monsieur
|
||||
$contact->civility_id = 'MR';
|
||||
$contact->lastname = $fields['LNOM'];
|
||||
} elseif (in_array($fields['LCIVIL'], ['DOCTEUR'])) {
|
||||
// un monsieur
|
||||
$contact->civility_id = 'DR';
|
||||
$contact->lastname = $fields['LNOM'];
|
||||
} else {
|
||||
// un a rattraper
|
||||
$contact->lastname = $fields['LCIVIL'] . " " . $fields['LNOM'];
|
||||
}
|
||||
$contact->address = trim($fields['LADR1']);
|
||||
if ($fields['LADR2']) {
|
||||
$contact->address .= "\n" . trim($fields['LADR2']);
|
||||
}
|
||||
if ($fields['LADR3']) {
|
||||
$contact->address .= "\n" . trim($fields['LADR3']);
|
||||
}
|
||||
|
||||
$contact->zip = trim($fields['LPOSTE']);
|
||||
$contact->town = trim($fields['LVILLE']);
|
||||
if ($fields['FPAYS']) {
|
||||
$contact->country_id = dol_getIdFromCode($db, trim(ucwords(strtolower($fields['LPAYS']))), 'c_country', 'label', 'rowid');
|
||||
} else {
|
||||
$contact->country_id = 1;
|
||||
}
|
||||
$contact->email = $fields['LMAIL'];
|
||||
$contact->phone = trim($fields['LTEL']) ? trim($fields['LTEL']) : trim($fields['LCONTACT']);
|
||||
$contact->fax = trim($fields['LFAX']) ? trim($fields['LFAX']) : trim($fields['LCONTACT']);
|
||||
$contact->socid = $object->id;
|
||||
|
||||
$ret1 = $contact->create($user);
|
||||
if ($ret1 > 0) {
|
||||
//$ret2=$contact->add_contact($object->id, 'BILLING');
|
||||
}
|
||||
if ($ret1 < 0 || $ret2 < 0) {
|
||||
print " - Error in create contact result code = " . $ret1 . " " . $ret2 . " - " . $contact->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - create contact OK";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//update date créa
|
||||
if (!$errorrecord) {
|
||||
$datec = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2);
|
||||
$retd = $db->query("UPDATE `llx_societe` SET `datec` = '$datec 00:00:00' WHERE `rowid` = $object->id");
|
||||
if ($retd < 1) {
|
||||
print " - Error in update date créa result " . $object->errorsToString();
|
||||
$errorrecord++;
|
||||
} else {
|
||||
print " - update date créa OK";
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
if ($errorrecord) {
|
||||
print( 'Error on record nb ' . $i . " - " . $object->errorsToString() . "\n");
|
||||
var_dump($db, $object, $contact);
|
||||
// $db->rollback();
|
||||
die();
|
||||
$error++; // $errorrecord will be reset
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
} else {
|
||||
die("error : $sql");
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
|
||||
|
||||
|
||||
// commit or rollback
|
||||
print "Nb of lines qualified: " . $nboflines . "\n";
|
||||
print "Nb of errors: " . $error . "\n";
|
||||
$db->close();
|
||||
|
||||
exit($error);
|
||||
@@ -1,599 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* \file dev/initdata/dbf/includes/dbase.class.php
|
||||
* \ingroup dev
|
||||
* \brief Class to manage DBF databases
|
||||
*/
|
||||
|
||||
// source : https://github.com/donfbecker/php-dbase
|
||||
|
||||
define('DBASE_RDONLY', 0);
|
||||
define('DBASE_WRONLY', 1);
|
||||
define('DBASE_RDWR', 2);
|
||||
define('DBASE_TYPE_DBASE', 0);
|
||||
define('DBASE_TYPE_FOXPRO', 1);
|
||||
|
||||
/**
|
||||
* Class for DBase
|
||||
*/
|
||||
class DBase
|
||||
{
|
||||
private $fd;
|
||||
private $headerLength = 0;
|
||||
private $fields = array();
|
||||
private $fieldCount = 0;
|
||||
private $recordLength = 0;
|
||||
private $recordCount = 0;
|
||||
|
||||
/**
|
||||
* resource dbase_open
|
||||
* @param string $filename filename
|
||||
* @param int $mode mode
|
||||
* @return DBase
|
||||
*/
|
||||
public static function open($filename, $mode)
|
||||
{
|
||||
if (!file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
$modes = array('r', 'w', 'r+');
|
||||
$mode = $modes[$mode];
|
||||
$fd = fopen($filename, $mode);
|
||||
if (!$fd) {
|
||||
return false;
|
||||
}
|
||||
return new DBase($fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* resource dbase_create
|
||||
* @param string $filename filename
|
||||
* @param array $fields fields
|
||||
* @param int $type DBASE_TYPE_DBASE
|
||||
* @return DBase
|
||||
*/
|
||||
public static function create($filename, $fields, $type = DBASE_TYPE_DBASE)
|
||||
{
|
||||
if (file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
$fd = fopen($filename, 'c+');
|
||||
if (!$fd) {
|
||||
return false;
|
||||
}
|
||||
// Byte 0 (1 byte): Valid dBASE for DOS file; bits 0-2 indicate version number, bit 3
|
||||
// indicates the presence of a dBASE for DOS memo file, bits 4-6 indicate the
|
||||
// presence of a SQL table, bit 7 indicates the presence of any memo file
|
||||
// (either dBASE m PLUS or dBASE for DOS)
|
||||
self::putChar8($fd, 5);
|
||||
// Byte 1-3 (3 bytes): Date of last update; formatted as YYMMDD
|
||||
self::putChar8($fd, date('Y') - 1900);
|
||||
self::putChar8($fd, date('m'));
|
||||
self::putChar8($fd, date('d'));
|
||||
// Byte 4-7 (32-bit number): Number of records in the database file. Currently 0
|
||||
self::putInt32($fd, 0);
|
||||
// Byte 8-9 (16-bit number): Number of bytes in the header.
|
||||
self::putInt16($fd, 32 + (32 * count($fields)) + 1);
|
||||
// Byte 10-11 (16-bit number): Number of bytes in record.
|
||||
// Make sure the include the byte for deleted flag
|
||||
$len = 1;
|
||||
foreach ($fields as &$field) {
|
||||
$len += self::length($field);
|
||||
}
|
||||
self::putInt16($fd, $len);
|
||||
// Byte 12-13 (2 bytes): Reserved, 0 filled.
|
||||
self::putInt16($fd, 0);
|
||||
// Byte 14 (1 byte): Flag indicating incomplete transaction
|
||||
// The ISMARKEDO function checks this flag. BEGIN TRANSACTION sets it to 1, END TRANSACTION and ROLLBACK reset it to 0.
|
||||
self::putChar8($fd, 0);
|
||||
// Byte 15 (1 byte): Encryption flag. If this flag is set to 1, the message Database encrypted appears. Changing this flag to 0 removes the message, but does not decrypt the file.
|
||||
self::putChar8($fd, 0);
|
||||
// Byte 16-27 (12 bytes): Reserved for dBASE for DOS in a multi-user environment
|
||||
self::putInt32($fd, 0);
|
||||
self::putInt32($fd, 0);
|
||||
self::putInt32($fd, 0);
|
||||
// Byte 28 (1 byte): Production .mdx file flag; 0x01 if there is a production .mdx file, 0x00 if not
|
||||
self::putChar8($fd, 0);
|
||||
// Byte 29 (1 byte): Language driver ID
|
||||
// (no clue what this is)
|
||||
self::putChar8($fd, 0);
|
||||
// Byte 30-31 (2 bytes): Reserved, 0 filled.
|
||||
self::putInt16($fd, 0);
|
||||
// Byte 32 - n (32 bytes each): Field descriptor array
|
||||
foreach ($fields as &$field) {
|
||||
self::putString($fd, $field[0], 11); // Byte 0 - 10 (11 bytes): Field name in ASCII (zero-filled)
|
||||
self::putString($fd, $field[1], 1); // Byte 11 (1 byte): Field type in ASCII (C, D, F, L, M, or N)
|
||||
self::putInt32($fd, 0); // Byte 12 - 15 (4 bytes): Reserved
|
||||
self::putChar8($fd, self::length($field)); // Byte 16 (1 byte): Field length in binary. The maximum length of a field is 254 (0xFE).
|
||||
self::putChar8($fd, $field[3]); // Byte 17 (1 byte): Field decimal count in binary
|
||||
self::putInt16($fd, 0); // Byte 18 - 19 (2 bytes): Work area ID
|
||||
self::putChar8($fd, 0); // Byte 20 (1 byte): Example (??)
|
||||
self::putInt32($fd, 0); // Byte 21 - 30 (10 bytes): Reserved
|
||||
self::putInt32($fd, 0);
|
||||
self::putInt16($fd, 0);
|
||||
self::putChar8($fd, 0); // Byte 31 (1 byte): Production MDX field flag; 1 if field has an index tag in the production MDX file, 0 if not
|
||||
}
|
||||
// Byte n + 1 (1 byte): 0x0D as the field descriptor array terminator
|
||||
self::putChar8($fd, 0x0D);
|
||||
return new DBase($fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create DBase instance
|
||||
* @param mixed $fd file descriptor
|
||||
* @return void
|
||||
*/
|
||||
private function __construct($fd)
|
||||
{
|
||||
$this->fd = $fd;
|
||||
// Byte 4-7 (32-bit number): Number of records in the database file. Currently 0
|
||||
fseek($this->fd, 4, SEEK_SET);
|
||||
$this->recordCount = self::getInt32($fd);
|
||||
// Byte 8-9 (16-bit number): Number of bytes in the header.
|
||||
fseek($this->fd, 8, SEEK_SET);
|
||||
$this->headerLength = self::getInt16($fd);
|
||||
// Number of fields is (headerLength - 33) / 32)
|
||||
$this->fieldCount = ($this->headerLength - 33) / 32;
|
||||
// Byte 10-11 (16-bit number): Number of bytes in record.
|
||||
fseek($this->fd, 10, SEEK_SET);
|
||||
$this->recordLength = self::getInt16($fd);
|
||||
// Byte 32 - n (32 bytes each): Field descriptor array
|
||||
fseek($fd, 32, SEEK_SET);
|
||||
for ($i = 0; $i < $this->fieldCount; $i++) {
|
||||
$data = fread($this->fd, 32);
|
||||
$field = array_map('trim', unpack('a11name/a1type/c4/c1length/c1precision/s1workid/c1example/c10/c1production', $data));
|
||||
$this->fields[] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_close
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
fclose($this->fd);
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_get_header_info
|
||||
* @return array
|
||||
*/
|
||||
public function get_header_info()
|
||||
{
|
||||
// phpcs:disable
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_numfields
|
||||
* @return int
|
||||
*/
|
||||
public function numfields()
|
||||
{
|
||||
return $this->fieldCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_numrecords
|
||||
* @return int
|
||||
*/
|
||||
public function numrecords()
|
||||
{
|
||||
return $this->recordCount;
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_add_record
|
||||
* @param array $record record
|
||||
* @return bool
|
||||
*/
|
||||
public function add_record($record)
|
||||
{
|
||||
// phpcs:enable
|
||||
if (count($record) != $this->fieldCount) {
|
||||
return false;
|
||||
}
|
||||
// Seek to end of file, minus the end of file marker
|
||||
fseek($this->fd, 0, SEEK_END);
|
||||
// Put the deleted flag
|
||||
self::putChar8($this->fd, 0x20);
|
||||
// Put the record
|
||||
if (!$this->putRecord($record)) {
|
||||
return false;
|
||||
}
|
||||
// Update the record count
|
||||
fseek($this->fd, 4);
|
||||
self::putInt32($this->fd, ++$this->recordCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_replace_record
|
||||
* @param array $record record
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
public function replace_record($record, $record_number)
|
||||
{
|
||||
// phpcs:enable
|
||||
if (count($record) != $this->fieldCount) {
|
||||
return false;
|
||||
}
|
||||
if ($record_number < 1 || $record_number > $this->recordCount) {
|
||||
return false;
|
||||
}
|
||||
// Skip to the record location, plus the 1 byte for the deleted flag
|
||||
fseek($this->fd, $this->headerLength + ($this->recordLength * ($record_number - 1)) + 1);
|
||||
return $this->putRecord($record);
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_delete_record
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_record($record_number)
|
||||
{
|
||||
// phpcs:enable
|
||||
if ($record_number < 1 || $record_number > $this->recordCount) {
|
||||
return false;
|
||||
}
|
||||
fseek($this->fd, $this->headerLength + ($this->recordLength * ($record_number - 1)));
|
||||
self::putChar8($this->fd, 0x2A);
|
||||
return true;
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_get_record
|
||||
* @param int $record_number record number
|
||||
* @return array
|
||||
*/
|
||||
public function get_record($record_number)
|
||||
{
|
||||
// phpcs:enable
|
||||
if ($record_number < 1 || $record_number > $this->recordCount) {
|
||||
return false;
|
||||
}
|
||||
fseek($this->fd, $this->headerLength + ($this->recordLength * ($record_number - 1)));
|
||||
$record = array(
|
||||
'deleted' => self::getChar8($this->fd) == 0x2A ? 1 : 0
|
||||
);
|
||||
foreach ($this->fields as $i => &$field) {
|
||||
$value = trim(fread($this->fd, $field['length']));
|
||||
if ($field['type'] == 'L') {
|
||||
$value = strtolower($value);
|
||||
if ($value == 't' || $value == 'y') {
|
||||
$value = true;
|
||||
} elseif ($value == 'f' || $value == 'n') {
|
||||
$value = false;
|
||||
} else {
|
||||
$value = null;
|
||||
}
|
||||
}
|
||||
$record[$i] = $value;
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* dbase_get_record_with_names
|
||||
* @param int $record_number record number
|
||||
* @return array
|
||||
*/
|
||||
public function get_record_with_names($record_number)
|
||||
{
|
||||
// phpcs:enable
|
||||
if ($record_number < 1 || $record_number > $this->recordCount) {
|
||||
return false;
|
||||
}
|
||||
$record = $this->get_record($record_number);
|
||||
foreach ($this->fields as $i => &$field) {
|
||||
$record[$field['name']] = $record[$i];
|
||||
unset($record[$i]);
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_pack
|
||||
* @return void
|
||||
*/
|
||||
public function pack()
|
||||
{
|
||||
$in_offset = $out_offset = $this->headerLength;
|
||||
$new_count = 0;
|
||||
$rec_count = $this->recordCount;
|
||||
while ($rec_count > 0) {
|
||||
fseek($this->fd, $in_offset, SEEK_SET);
|
||||
$record = fread($this->fd, $this->recordLength);
|
||||
$deleted = substr($record, 0, 1);
|
||||
if ($deleted != '*') {
|
||||
fseek($this->fd, $out_offset, SEEK_SET);
|
||||
fwrite($this->fd, $record);
|
||||
$out_offset += $this->recordLength;
|
||||
$new_count++;
|
||||
}
|
||||
$in_offset += $this->recordLength;
|
||||
$rec_count--;
|
||||
}
|
||||
ftruncate($this->fd, $out_offset);
|
||||
// Update the record count
|
||||
fseek($this->fd, 4);
|
||||
self::putInt32($this->fd, $new_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* A few utilitiy functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param string $field field
|
||||
* @return int
|
||||
*/
|
||||
private static function length($field)
|
||||
{
|
||||
switch ($field[1]) {
|
||||
case 'D': // Date: Numbers and a character to separate month, day, and year (stored internally as 8 digits in YYYYMMDD format)
|
||||
return 8;
|
||||
case 'T': // DateTime (YYYYMMDDhhmmss.uuu) (FoxPro)
|
||||
return 18;
|
||||
case 'M': // Memo (ignored): All ASCII characters (stored internally as 10 digits representing a .dbt block number, right justified, padded with whitespaces)
|
||||
case 'N': // Number: -.0123456789 (right justified, padded with whitespaces)
|
||||
case 'F': // Float: -.0123456789 (right justified, padded with whitespaces)
|
||||
case 'C': // String: All ASCII characters (padded with whitespaces up to the field's length)
|
||||
return $field[2];
|
||||
case 'L': // Boolean: YyNnTtFf? (? when not initialized)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for reading and writing bytes
|
||||
*/
|
||||
|
||||
/**
|
||||
* getChar8
|
||||
* @param mixed $fd file descriptor
|
||||
* @return int
|
||||
*/
|
||||
private static function getChar8($fd)
|
||||
{
|
||||
return ord(fread($fd, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* putChar8
|
||||
* @param mixed $fd file descriptor
|
||||
* @param mixed $value value
|
||||
* @return bool
|
||||
*/
|
||||
private static function putChar8($fd, $value)
|
||||
{
|
||||
return fwrite($fd, chr($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* getInt16
|
||||
* @param mixed $fd file descriptor
|
||||
* @param int $n n
|
||||
* @return bool
|
||||
*/
|
||||
private static function getInt16($fd, $n = 1)
|
||||
{
|
||||
$data = fread($fd, 2 * $n);
|
||||
$i = unpack("S$n", $data);
|
||||
if ($n == 1) {
|
||||
return (int) $i[1];
|
||||
} else {
|
||||
return array_merge($i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* putInt16
|
||||
* @param mixed $fd file descriptor
|
||||
* @param mixed $value value
|
||||
* @return bool
|
||||
*/
|
||||
private static function putInt16($fd, $value)
|
||||
{
|
||||
return fwrite($fd, pack('S', $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* getInt32
|
||||
* @param mixed $fd file descriptor
|
||||
* @param int $n n
|
||||
* @return bool
|
||||
*/
|
||||
private static function getInt32($fd, $n = 1)
|
||||
{
|
||||
$data = fread($fd, 4 * $n);
|
||||
$i = unpack("L$n", $data);
|
||||
if ($n == 1) {
|
||||
return (int) $i[1];
|
||||
} else {
|
||||
return array_merge($i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* putint32
|
||||
* @param mixed $fd file descriptor
|
||||
* @param mixed $value value
|
||||
* @return bool
|
||||
*/
|
||||
private static function putInt32($fd, $value)
|
||||
{
|
||||
return fwrite($fd, pack('L', $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* putString
|
||||
* @param mixed $fd file descriptor
|
||||
* @param mixed $value value
|
||||
* @param int $length length
|
||||
* @return bool
|
||||
*/
|
||||
private static function putString($fd, $value, $length = 254)
|
||||
{
|
||||
$ret = fwrite($fd, pack('A' . $length, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* putRecord
|
||||
* @param mixed $record record
|
||||
* @return bool
|
||||
*/
|
||||
private function putRecord($record)
|
||||
{
|
||||
foreach ($this->fields as $i => &$field) {
|
||||
$value = $record[$i];
|
||||
// Number types are right aligned with spaces
|
||||
if ($field['type'] == 'N' || $field['type'] == 'F' && strlen($value) < $field['length']) {
|
||||
$value = str_repeat(' ', $field['length'] - strlen($value)) . $value;
|
||||
}
|
||||
self::putString($this->fd, $value, $field['length']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('dbase_open')) {
|
||||
/**
|
||||
* dbase_open
|
||||
* @param string $filename filename
|
||||
* @param int $mode mode
|
||||
* @return DBase
|
||||
*/
|
||||
function dbase_open($filename, $mode)
|
||||
{
|
||||
return DBase::open($filename, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_create
|
||||
* @param string $filename filename
|
||||
* @param array $fields fields
|
||||
* @param int $type type
|
||||
* @return DBase
|
||||
*/
|
||||
function dbase_create($filename, $fields, $type = DBASE_TYPE_DBASE)
|
||||
{
|
||||
return DBase::create($filename, $fields, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_close
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_close($dbase_identifier)
|
||||
{
|
||||
return $dbase_identifier->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_get_header_info
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @return string
|
||||
*/
|
||||
function dbase_get_header_info($dbase_identifier)
|
||||
{
|
||||
return $dbase_identifier->get_header_info();
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_numfields
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @return int
|
||||
*/
|
||||
function dbase_numfields($dbase_identifier)
|
||||
{
|
||||
$dbase_identifier->numfields();
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_numrecords
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @return int
|
||||
*/
|
||||
function dbase_numrecords($dbase_identifier)
|
||||
{
|
||||
return $dbase_identifier->numrecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_add_record
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @param array $record record
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_add_record($dbase_identifier, $record)
|
||||
{
|
||||
return $dbase_identifier->add_record($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_delete_record
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_delete_record($dbase_identifier, $record_number)
|
||||
{
|
||||
return $dbase_identifier->delete_record($record_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_replace_record
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @param array $record record
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_replace_record($dbase_identifier, $record, $record_number)
|
||||
{
|
||||
return $dbase_identifier->replace_record($record, $record_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_get_record
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_get_record($dbase_identifier, $record_number)
|
||||
{
|
||||
return $dbase_identifier->get_record($record_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_get_record_with_names
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @param int $record_number record number
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_get_record_with_names($dbase_identifier, $record_number)
|
||||
{
|
||||
return $dbase_identifier->get_record_with_names($record_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* dbase_pack
|
||||
* @param Resource $dbase_identifier dbase identifier
|
||||
* @return bool
|
||||
*/
|
||||
function dbase_pack($dbase_identifier)
|
||||
{
|
||||
return $dbase_identifier->pack();
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ then
|
||||
fichtemp=`tempfile 2>/dev/null` || fichtemp=/tmp/test$$
|
||||
trap "rm -f $fichtemp" 0 1 2 5 15
|
||||
$DIALOG --title "Init Dolibarr with demo values" --clear \
|
||||
--inputbox "Password for Mysql user login :" 16 55 2> $fichtemp
|
||||
--passwordbox "Password for Mysql user login :" 16 55 2> $fichtemp
|
||||
|
||||
valret=$?
|
||||
|
||||
@@ -153,7 +153,7 @@ then
|
||||
# ---------------------------- confirmation
|
||||
DIALOG=${DIALOG=dialog}
|
||||
$DIALOG --title "Init Dolibarr with demo values" --clear \
|
||||
--yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Document dir : '$documentdir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : '$passwd'" 15 55
|
||||
--yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Document dir : '$documentdir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : --hidden--" 15 55
|
||||
|
||||
case $? in
|
||||
0) echo "Ok, start process...";;
|
||||
|
||||
@@ -171,7 +171,10 @@ if [ $res -ne 0 ]; then
|
||||
fi
|
||||
|
||||
if [ -s "$mydir/initdemopostsql.sql" ]; then
|
||||
echo A file initdemopostsql.sql was found, we execute it.
|
||||
mysql -P$port $base < "$mydir/initdemopostsql.sql"
|
||||
else
|
||||
echo No file initdemopostsql.sql found, we extra sql action done.
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ then
|
||||
fichtemp=`tempfile 2>/dev/null` || fichtemp=/tmp/test$$
|
||||
trap "rm -f $fichtemp" 0 1 2 5 15
|
||||
$DIALOG --title "Save Dolibarr with demo values" --clear \
|
||||
--inputbox "Password for Mysql root login :" 16 55 2> $fichtemp
|
||||
--passwordbox "Password for Mysql root login :" 16 55 2> $fichtemp
|
||||
|
||||
valret=$?
|
||||
|
||||
@@ -150,7 +150,7 @@ then
|
||||
# ---------------------------- confirmation
|
||||
DIALOG=${DIALOG=dialog}
|
||||
$DIALOG --title "Save Dolibarr with demo values" --clear \
|
||||
--yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : '$passwd'" 15 55
|
||||
--yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : --hidden--" 15 55
|
||||
|
||||
case $? in
|
||||
0) echo "Ok, start process...";;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
Gestion escompte:
|
||||
|
||||
Sur une facture de 120 € TTC :
|
||||
707xxx 100 € HT
|
||||
44571x 20 € TVA
|
||||
411xxx 120 € TTC
|
||||
|
||||
707xxx 100 € HT
|
||||
44571x 20 € TVA
|
||||
411xxx 120 € TTC
|
||||
|
||||
Le client règle rapidement et on lui accorde un escompte de 3% (120 € * 3% = 3.6 € TTC), on aura donc :
|
||||
665000 3,00 € HT
|
||||
44571x 0,60 € TVA
|
||||
411xxx 3.60 € TVA
|
||||
|
||||
665000 3,00 € HT
|
||||
44571x 0,60 € TVA
|
||||
411xxx 3,60 € TTC
|
||||
|
||||
Et ça marche à l’inverse avec un fournisseur sauf que l’on est en 775000 au lieu de 665000 pour escompte obtenus.
|
||||
@@ -1,3 +1,5 @@
|
||||
Address format
|
||||
|
||||
https://bitboost.com/ref/international-address-formats.html#Formats
|
||||
|
||||
https://www.upu.int/en/Postal-Solutions/Programmes-Services/Addressing-Solutions
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
Barcode EAN 13
|
||||
|
||||
FR
|
||||
==
|
||||
Signification des chiffres.
|
||||
|
||||
- 2 chiffres pour le code pays ou code systeme
|
||||
- 5 chiffres pour l'identificateur de societe
|
||||
- 5 chiffres pour l'identificateur d'article
|
||||
- 1 chiffre pour la somme de controle
|
||||
|
||||
Cette regle subit de nombreuses entorses pour ameliorer l'usage des chiffres disponibles.
|
||||
Voici la liste des codes pays ou systeme :
|
||||
|
||||
|
||||
|
||||
EN
|
||||
==
|
||||
Meaning of the numbers.
|
||||
|
||||
- 2 digits for the country code or system code
|
||||
- 5 digits for the company identifier
|
||||
- 5 digits for item identifier
|
||||
- 1 digit for checksum
|
||||
|
||||
This rule has been twisted many times to improve the use of the available numbers.
|
||||
Here is the list of country codes or system:
|
||||
|
||||
|
||||
|
||||
List
|
||||
====
|
||||
|
||||
00 <20> 13 UCC (Etats-Unis et Canada)
|
||||
20 <20> 29 Codification interne en magasin
|
||||
30 <20> 37 GENCOD-EAN France
|
||||
380 BCCI (Bulgarie)
|
||||
383 SANA (Slovenie)
|
||||
385 CRO-EAN (Croatie)
|
||||
387 EAN-BIH (Bosnie-Herzegovine)
|
||||
400 <20> 440 CCG (Allemagne)
|
||||
45 + 49 Distribution Code Center <20> DCC (Japon)
|
||||
460 <20> 469 UNISCAN - EAN Russie (Federation de Russie)
|
||||
471 CAN (Taiwan)
|
||||
474 EAN Estonie
|
||||
475 EAN Lettonie
|
||||
476 EAN Azerba<62> djan
|
||||
477 EAN Lituanie
|
||||
478 EAN Ouzbekistan
|
||||
479 EAN Sri Lanka
|
||||
480 PANC (Philippines)
|
||||
481 EAN Bielorussie
|
||||
482 EAN Ukraine
|
||||
484 EAN Moldavie
|
||||
485 EAN Armenie
|
||||
486 EAN Georgie
|
||||
487 EAN Kazakhstan
|
||||
489 HKANA (Hong Kong)
|
||||
50 E Centre UK
|
||||
520 HELLCAN-EAN HELLAS (Grece)
|
||||
528 EAN Liban
|
||||
529 EAN Chypre
|
||||
531 EAN-MAC (FYR Mac<61>donie)
|
||||
535 EAN Malte
|
||||
539 EAN Irlande
|
||||
54 ICODIF/EAN Belgique. Luxembourg
|
||||
560 CODIPOR (Portugal)
|
||||
569 EAN Islande
|
||||
57 EAN Danemark
|
||||
590 EAN Pologne
|
||||
594 EAN Roumanie
|
||||
599 H.A.P.M.H. (Hongrie)
|
||||
600 - 601 EAN Afrique du Sud
|
||||
609 EAN Ile Maurice
|
||||
611 EAN Maroc
|
||||
613 EAN Algerie
|
||||
619 Tunicode (Tunisie)
|
||||
621 EAN Syrie
|
||||
622 EAN Egypte
|
||||
625 EAN Jordanie
|
||||
626 EAN Iran
|
||||
628 EAN Arabie Saoudite
|
||||
64 EAN Finlande
|
||||
690 - 693 Article Numbering Centre of China - ANCC (Chine)
|
||||
70 EAN Norge (Norvege)
|
||||
729 Israeli Bar Code Association <20> EAN Israel
|
||||
73 EAN Suede
|
||||
740 EAN Guatemala
|
||||
741 EAN El Salvador
|
||||
742 ICCC (Honduras)
|
||||
743 EAN Nicaragua
|
||||
744 EAN Costa Rica Panama
|
||||
746 746 EAN Republique Dominicaine
|
||||
750 AMECE (Mexique)
|
||||
759 EAN Venezuela
|
||||
76 EAN (Schweiz, Suisse, Svizzera)
|
||||
770 IAC (Colombie)
|
||||
773 EAN Uruguay
|
||||
775 APC - EAN Peru (Perou)
|
||||
777 EAN Bolivie
|
||||
779 CODIGO - EAN Argentine
|
||||
780 EAN Chili
|
||||
784 EAN Paraguay
|
||||
786 ECOP (Equateur)
|
||||
789 EAN Bresil
|
||||
80 <20> 83 INDICOD (Italie)
|
||||
84 AECOC (Espagne)
|
||||
850 Camera de Comercio de la Republica de Cuba (Cuba)
|
||||
858 EAN Slovaquie
|
||||
859 EAN Republique Tcheque
|
||||
860 EAN YU (Yougoslavie)
|
||||
867 EAN DPR Korea (Coree du Nord)
|
||||
869 Union of Chambers of Commerce of Turkey (Turquie)
|
||||
87 EAN Nederland (Hollande)
|
||||
880 EAN Korea (Coree du Sud)
|
||||
885 EAN Thailande
|
||||
888 SANC (Singapour)
|
||||
890 EAN Inde
|
||||
893 EAN Vietnam
|
||||
899 EAN Indonesie
|
||||
90 - 91 EAN Autriche
|
||||
93 EAN Australie
|
||||
94 EAN Nouvelle Zelande
|
||||
955 Malaysian Article Numbering Council (MANC) - Malaisie
|
||||
977 Publications sirielles (ISSN)
|
||||
978 - 979 Livres (ISBN)
|
||||
980 Refus de remboursement
|
||||
981 - 982 Coupons (monnaie courante)
|
||||
99 Coupons
|
||||
22
dev/resources/iso-normes/barcodes/QR code for invoices.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
QR-Code = Quick Response Code - is a two-dimensional / 2D- / Matrix-Barcode
|
||||
|
||||
ISO/IEC 18004
|
||||
|
||||
|
||||
List of QR Code format we found on some invoices
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
* For SEPA QR payment Code format (Europe)
|
||||
------------------------------------------
|
||||
https://en.wikipedia.org/wiki/EPC_QR_code#Generators
|
||||
|
||||
|
||||
|
||||
* For ZATCA QR Code format (Saudi Arabia). Used when INVOICE_ADD_ZATCA_QR_CODE is set
|
||||
-------------------------------------------------------------------------------------
|
||||
https://www.pwc.com/m1/en/services/tax/me-tax-legal-news/2021/saudi-arabia-guide-to-develop-compliant-qr-code-for-simplified-einvoices.html
|
||||
|
||||
https://www.tecklenborgh.com/post/ksa-zatca-publishes-guide-on-how-to-develop-a-fatoora-compliant-qr-code
|
||||
|
||||
Method to encode/decode ZATCA string is available in test/phpunit/BarcodeTest.php
|
||||
129
dev/resources/iso-normes/barcodes/barcode_EAN13.txt
Normal file
@@ -0,0 +1,129 @@
|
||||
Barcode EAN 13
|
||||
|
||||
FR
|
||||
==
|
||||
Signification des chiffres.
|
||||
|
||||
- 2 chiffres pour le code pays ou code systeme
|
||||
- 5 chiffres pour l'identificateur de societe
|
||||
- 5 chiffres pour l'identificateur d'article
|
||||
- 1 chiffre pour la somme de controle
|
||||
|
||||
Cette regle subit de nombreuses entorses pour ameliorer l'usage des chiffres disponibles.
|
||||
Voici la liste des codes pays ou systeme :
|
||||
|
||||
|
||||
|
||||
EN
|
||||
==
|
||||
Meaning of the numbers:
|
||||
|
||||
- first 2-3 digits for the country code or system code
|
||||
- 5 digits for the company identifier
|
||||
- 5 digits for item identifier
|
||||
- 1 digit for checksum
|
||||
|
||||
This rule has been twisted many times to improve the use of the available numbers.
|
||||
|
||||
Here is the list of country codes or system:
|
||||
|
||||
|
||||
List
|
||||
====
|
||||
|
||||
00 - 13 UCC (U.S.A / États-Unis & Canada)
|
||||
20 - 29 Flag for internal numbering / Codification interne en magasin
|
||||
30 - 37 GENCOD-EAN France
|
||||
380 BCCI (Bulgaria)
|
||||
383 SANA (Slovenia)
|
||||
385 CRO-EAN (Croatia)
|
||||
387 EAN-BIH (Bosnia-Herzegovina)
|
||||
400-440 CCG (DE/Germany/Allemagne)
|
||||
45 + 49 Distribution Code Center - DCC (Japan)
|
||||
460-469 UNISCAN - EAN Russia (Federation de Russie)
|
||||
471 CAN Taiwan
|
||||
474 EAN Estonia
|
||||
475 EAN Latvia
|
||||
476 EAN Azerbaijan
|
||||
477 EAN Lithuania
|
||||
478 EAN Uzbekistan
|
||||
479 EAN Sri Lanka
|
||||
480 PANC Philippines
|
||||
481 EAN Belarus
|
||||
482 EAN Ukraine
|
||||
484 EAN Moldova
|
||||
485 EAN Armenia
|
||||
486 EAN Georgia
|
||||
487 EAN Kazakhstan
|
||||
489 HKANA Hong Kong
|
||||
50 E Centre UK - United Kingdom
|
||||
520 HELLCAN-EAN HELLAS - Greece
|
||||
528 EAN Lebanon
|
||||
529 EAN Cyprus
|
||||
531 EAN-MAC (FYR Macedonia)
|
||||
535 EAN Malta
|
||||
539 EAN Ireland
|
||||
54 ICODIF/EAN Belgium & Luxembourg
|
||||
560 CODIPOR (Portugal)
|
||||
569 EAN Iceland/Islande
|
||||
57 EAN Denmark
|
||||
590 EAN Poland
|
||||
594 EAN Romania
|
||||
599 H.A.P.M.H. (Hungary)
|
||||
600-601 EAN South Africa
|
||||
609 EAN Mauritius Island
|
||||
611 EAN Morocco
|
||||
613 EAN Algeria
|
||||
619 Tunicode (Tunisia)
|
||||
621 EAN Syria
|
||||
622 EAN Egypt
|
||||
625 EAN Jordan/Jordanie
|
||||
626 EAN Iran
|
||||
628 EAN Saudi Arabia
|
||||
64 EAN Finland
|
||||
690-693 ANCC - Article Numbering Centre of China
|
||||
70 EAN Norge (Norvege)
|
||||
729 Israeli Bar Code Association - EAN Israel
|
||||
73 EAN Suede
|
||||
740 EAN Guatemala
|
||||
741 EAN El Salvador
|
||||
742 ICCC (Honduras)
|
||||
743 EAN Nicaragua
|
||||
744 EAN Costa Rica Panama
|
||||
746 746 EAN Republique Dominicaine
|
||||
750 AMECE (Mexique)
|
||||
759 EAN Venezuela
|
||||
76 EAN (Schweiz, Suisse, Svizzera)
|
||||
770 IAC (Colombie)
|
||||
773 EAN Uruguay
|
||||
775 APC - EAN Peru (Perou)
|
||||
777 EAN Bolivie
|
||||
779 CODIGO - EAN Argentine
|
||||
780 EAN Chili
|
||||
784 EAN Paraguay
|
||||
786 ECOP (Equateur)
|
||||
789 EAN Bresil
|
||||
80 - 83 INDICOD (Italy)
|
||||
84 AECOC (Espagne)
|
||||
850 Camera de Comercio de la Republica de Cuba (Cuba)
|
||||
858 EAN Slovaquie
|
||||
859 EAN Republique Tcheque
|
||||
860 EAN YU (Yougoslavie)
|
||||
867 EAN DPR Korea (Coree du Nord)
|
||||
869 Union of Chambers of Commerce of Turkey (Turquie)
|
||||
87 EAN Nederland (Hollande)
|
||||
880 EAN Korea (Coree du Sud)
|
||||
885 EAN Thailande
|
||||
888 SANC (Singapour)
|
||||
890 EAN Inde
|
||||
893 EAN Vietnam
|
||||
899 EAN Indonesie
|
||||
90 - 91 EAN Autriche
|
||||
93 EAN Australie
|
||||
94 EAN Nouvelle Zelande
|
||||
955 Malaysian Article Numbering Council (MANC) - Malaisie
|
||||
977 Publications sirielles (ISSN)
|
||||
978 - 979 Livres (ISBN)
|
||||
980 Refus de remboursement
|
||||
981 - 982 Coupons (monnaie courante)
|
||||
99 Coupons
|
||||
@@ -1,8 +1,12 @@
|
||||
# File of all ISO-4217 currencies codes
|
||||
# http://en.wikipedia.org/wiki/ISO_4217
|
||||
# http://fx.sauder.ubc.ca/currency_table.html for symbols for 2 letter code
|
||||
#
|
||||
# Code,Name,Nb decimals
|
||||
# https://en.wikipedia.org/wiki/ISO_4217
|
||||
# https://en.wikipedia.org/wiki/Currency_symbol for symbols for 2 letter code
|
||||
#
|
||||
|
||||
|
||||
# Code, Currency Name, Nb decimals
|
||||
|
||||
AED,UAE Dirham,2
|
||||
AFN,Afghanistan Afghani,2
|
||||
ALL,Albanian Lek,2
|
||||
|
||||
BIN
dev/resources/iso-normes/format PDF - PDF A.pdf
Normal file
@@ -1,3 +1,5 @@
|
||||
Date and number format
|
||||
----------------------
|
||||
|
||||
For languages:
|
||||
https://icu4c-demos.unicode.org/icu-bin/icudemos - Locale Explorer -> Error 404
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
VAT Rates
|
||||
---------
|
||||
|
||||
http://www.taxrates.cc/index.html
|
||||
https://en.wikipedia.org/wiki/List_of_countries_by_tax_rates
|
||||
|
||||
|
||||
@@ -1,62 +1,93 @@
|
||||
<VirtualHost *:80>
|
||||
#php_admin_value sendmail_path "/usr/sbin/sendmail -t -i"
|
||||
#php_admin_value mail.force_extra_parameters "-f postmaster@mydomain.com"
|
||||
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f postmaster@mydomain.com"
|
||||
php_admin_value open_basedir /tmp/:/home/../htdocs
|
||||
#php_admin_value sendmail_path "/usr/sbin/sendmail -t -i"
|
||||
#php_admin_value mail.force_extra_parameters "-f postmaster@mydomain.com"
|
||||
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f postmaster@mydomain.com"
|
||||
php_admin_value open_basedir /tmp/:/home/.../htdocs:/home/.../dolibarr_documents:
|
||||
|
||||
ServerName myvirtualalias
|
||||
ServerAlias myvirtualalias
|
||||
|
||||
UseCanonicalName On
|
||||
|
||||
KeepAlive On
|
||||
KeepAliveTimeout 5
|
||||
MaxKeepAliveRequests 20
|
||||
|
||||
AddDefaultCharset UTF-8
|
||||
|
||||
DocumentRoot "/home/.../htdocs"
|
||||
|
||||
<Directory /home/.../htdocs/>
|
||||
AllowOverride None
|
||||
Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
|
||||
Require all granted
|
||||
|
||||
ServerName myvirtualalias
|
||||
ServerAlias myvirtualalias
|
||||
# To restrict access by a HTTP basic auth
|
||||
#AuthType Basic
|
||||
#AuthName "Authenticate to backoffice"
|
||||
#AuthUserFile /etc/apache2/.htpasswd
|
||||
#require valid-user
|
||||
</Directory>
|
||||
|
||||
# Leaving /public and /api, /dav, .well_known but also wrappers for document and viewimage accessible to everyone
|
||||
<Directory /home/admin/wwwroot/dolibarr/htdocs/public/>
|
||||
AuthType None
|
||||
Require all granted
|
||||
Satisfy any
|
||||
</Directory>
|
||||
<Directory /home/admin/wwwroot/dolibarr/htdocs/api/>
|
||||
AuthType None
|
||||
Require all granted
|
||||
Satisfy any
|
||||
</Directory>
|
||||
<Directory /home/admin/wwwroot/dolibarr/htdocs/dav/>
|
||||
AuthType None
|
||||
Require all granted
|
||||
Satisfy any
|
||||
</Directory>
|
||||
<Directory /home/admin/wwwroot/dolibarr/htdocs/.well-known/>
|
||||
AuthType None
|
||||
Require all granted
|
||||
Satisfy any
|
||||
</Directory>
|
||||
<Files ~ "(document\.php|viewimage\.php|\.js\.php|\.json\.php|\.js|\.css\.php|\.css|\.gif|\.png|\.svg|\.woff2|favicon\.ico)$">
|
||||
AuthType None
|
||||
Require all granted
|
||||
Satisfy any
|
||||
</Files>
|
||||
|
||||
UseCanonicalName On
|
||||
|
||||
AddDefaultCharset UTF-8
|
||||
|
||||
DocumentRoot "/home/.../htdocs"
|
||||
|
||||
<Directory /home/.../htdocs/>
|
||||
AllowOverride None
|
||||
Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
<Directory "/home/../htdocs/cache">
|
||||
Deny from all
|
||||
RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
|
||||
AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
|
||||
</Directory>
|
||||
|
||||
|
||||
ErrorLog /var/log/apache2/myvirtualalias_error_log
|
||||
TransferLog /var/log/apache2/myvirtualalias_access_log
|
||||
|
||||
# Compress returned resources of type php pages, text file export, css and javascript
|
||||
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript
|
||||
|
||||
AddType text/javascript .jgz
|
||||
AddEncoding gzip .jgz
|
||||
ExpiresActive On
|
||||
ExpiresByType image/x-icon A2592000
|
||||
ExpiresByType image/gif A2592000
|
||||
ExpiresByType image/png A2592000
|
||||
ExpiresByType image/jpeg A2592000
|
||||
ExpiresByType text/css A2592000
|
||||
ExpiresByType text/javascript A2592000
|
||||
ExpiresByType application/x-javascript A2592000
|
||||
ExpiresByType application/javascript A2592000
|
||||
|
||||
SSLEngine On
|
||||
|
||||
# A self-signed (snakeoil) certificate can be created by installing
|
||||
# the ssl-cert package. See
|
||||
# /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
|
||||
# If both key and certificate are stored in the same file, only the
|
||||
# SSLCertificateFile directive is needed.
|
||||
SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
|
||||
SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
|
||||
|
||||
#RewriteEngine on
|
||||
#RewriteCond %{SERVER_PORT} ^80$
|
||||
#RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
|
||||
|
||||
ErrorLog /var/log/apache2/myvirtualalias_error_log
|
||||
TransferLog /var/log/apache2/myvirtualalias_access_log
|
||||
|
||||
# Compress returned resources of type php pages, text file export, css and javascript
|
||||
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript
|
||||
|
||||
AddType text/javascript .jgz
|
||||
AddEncoding gzip .jgz
|
||||
ExpiresActive On
|
||||
ExpiresByType image/x-icon A2592000
|
||||
ExpiresByType image/gif A2592000
|
||||
ExpiresByType image/png A2592000
|
||||
ExpiresByType image/jpeg A2592000
|
||||
ExpiresByType text/css A2592000
|
||||
ExpiresByType text/javascript A2592000
|
||||
ExpiresByType application/x-javascript A2592000
|
||||
ExpiresByType application/javascript A2592000
|
||||
|
||||
SSLEngine On
|
||||
|
||||
# A self-signed (snakeoil) certificate can be created by installing
|
||||
# the ssl-cert package. See
|
||||
# /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
|
||||
# If both key and certificate are stored in the same file, only the
|
||||
# SSLCertificateFile directive is needed.
|
||||
SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
|
||||
SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
|
||||
|
||||
#RewriteEngine on
|
||||
#RewriteCond %{SERVER_PORT} ^80$
|
||||
#RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
|
||||
|
||||
</VirtualHost>
|
||||
|
||||
@@ -17,14 +17,14 @@ fi
|
||||
# To detec
|
||||
if [ "x$1" = "xlist" ]
|
||||
then
|
||||
find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" -o -iname "*.pml" \) -exec file "{}" + | grep -v 'documents\/website' | grep -v 'documents\/mdedias' | grep CRLF
|
||||
# find . \( -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep -v 'documents\/website' | grep -v 'documents\/mdedias' | grep -v 'htdocs\/includes' | grep CRLF
|
||||
find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" -o -iname "*.pml" \) -exec file "{}" + | grep -v 'custom\/' | grep -v 'documents\/website' | grep -v 'documents\/medias' | grep -v 'documents\/sellyoursaas' | grep CRLF
|
||||
# find . \( -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" \) -exec file "{}" + | grep -v 'custom\/' | grep -v 'documents\/website' | grep -v 'documents\/medias' | grep -v 'documents\/sellyoursaas' | grep -v 'htdocs\/includes' | grep CRLF
|
||||
fi
|
||||
|
||||
# To convert
|
||||
if [ "x$1" = "xfix" ]
|
||||
then
|
||||
for fic in `find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" -o -iname "*.pml" \) -exec file "{}" + | grep -v 'documents\/website' | grep -v 'documents\/mdedias' | grep CRLF | awk -F':' '{ print $1 }' `
|
||||
for fic in `find . \( -iname "functions" -o -iname "*.md" -o -iname "*.html" -o -iname "*.htm" -o -iname "*.php" -o -iname "*.sh" -o -iname "*.cml" -o -iname "*.css" -o -iname "*.js" -o -iname "*.lang" -o -iname "*.pl" -o -iname "*.sql" -o -iname "*.txt" -o -iname "*.xml" -o -iname "*.pml" \) -exec file "{}" + | grep -v 'custom\/' | grep -v 'documents\/website' | grep -v 'documents\/medias' | grep -v 'documents\/sellyoursaas' | grep CRLF | awk -F':' '{ print $1 }' `
|
||||
do
|
||||
echo "Fix file $fic"
|
||||
dos2unix "$fic"
|
||||
|
||||
@@ -14,7 +14,8 @@ max_output_size=0
|
||||
usage()
|
||||
{
|
||||
cat <<EO
|
||||
Usage: $PROGNAME [options]
|
||||
Usage: $PROGNAME (list|fix) [options]
|
||||
Example: optimize_images.sh (list|fix) -i dirtoscan
|
||||
|
||||
Script to optimize JPG and PNG images in a directory.
|
||||
|
||||
@@ -183,8 +184,8 @@ ARGS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name $PROGN
|
||||
# Syntax
|
||||
if [ "x$1" != "xlist" -a "x$1" != "xfix" ]
|
||||
then
|
||||
echo "Usage: optimize_images.sh (list|fix) -i dirtoscan"
|
||||
exit
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
eval set -- "$ARGS"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
|
||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 338 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 946 B |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.3 KiB |
BIN
doc/images/dolibarr_logo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 219 KiB After Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 281 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 54 KiB |
@@ -38,6 +38,7 @@ $cancel = GETPOST('cancel', 'alpha');
|
||||
$id = GETPOST('id', 'int');
|
||||
$rowid = GETPOST('rowid', 'int');
|
||||
$massaction = GETPOST('massaction', 'aZ09');
|
||||
$optioncss = GETPOST('optioncss', 'alpha');
|
||||
$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'accountingaccountlist'; // To manage different context of search
|
||||
|
||||
$search_account = GETPOST('search_account', 'alpha');
|
||||
@@ -51,14 +52,14 @@ $confirm = GETPOST('confirm', 'alpha');
|
||||
|
||||
$chartofaccounts = GETPOST('chartofaccounts', 'int');
|
||||
|
||||
$permissiontoadd = $user->rights->accounting->chartofaccount;
|
||||
$permissiontodelete = $user->rights->accounting->chartofaccount;
|
||||
$permissiontoadd = !empty($user->rights->accounting->chartofaccount);
|
||||
$permissiontodelete = !empty($user->rights->accounting->chartofaccount);
|
||||
|
||||
// Security check
|
||||
if ($user->socid > 0) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->chartofaccount) {
|
||||
if (empty($user->rights->accounting->chartofaccount)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
@@ -195,7 +196,7 @@ if (empty($reshook)) {
|
||||
} elseif ($action == 'enable' && $permissiontoadd) {
|
||||
if ($accounting->fetch($id)) {
|
||||
$mode = GETPOST('mode', 'int');
|
||||
$result = $accounting->account_activate($id, $mode);
|
||||
$result = $accounting->accountActivate($id, $mode);
|
||||
}
|
||||
$action = 'update';
|
||||
if ($result < 0) {
|
||||
@@ -362,7 +363,7 @@ if ($resql) {
|
||||
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans("New"), $langs->trans("Addanaccount"), 'fa fa-plus-circle', './card.php?action=create');
|
||||
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
|
||||
print_barre_liste($langs->trans('ListAccounts'), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1);
|
||||
print_barre_liste($langs->trans('ListAccounts'), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'accounting_account', 0, $newcardbutton, '', $limit, 0, 0, 1);
|
||||
|
||||
// Box to select active chart of account
|
||||
print $langs->trans("Selectchartofaccounts")." : ";
|
||||
@@ -392,7 +393,7 @@ if ($resql) {
|
||||
}
|
||||
print "</select>";
|
||||
print ajax_combobox("chartofaccounts");
|
||||
print '<input type="'.(empty($conf->use_javascript_ajax) ? 'submit' : 'button').'" class="button" name="change_chart" id="change_chart" value="'.dol_escape_htmltag($langs->trans("ChangeAndLoad")).'">';
|
||||
print '<input type="'.(empty($conf->use_javascript_ajax) ? 'submit' : 'button').'" class="button button-edit" name="change_chart" id="change_chart" value="'.dol_escape_htmltag($langs->trans("ChangeAndLoad")).'">';
|
||||
|
||||
print '<br>';
|
||||
print '<br>';
|
||||
@@ -403,6 +404,11 @@ if ($resql) {
|
||||
|
||||
$moreforfilter = '';
|
||||
|
||||
$accountstatic = new AccountingAccount($db);
|
||||
$accountparent = new AccountingAccount($db);
|
||||
$totalarray = array();
|
||||
$totalarray['nbfield'] = 0;
|
||||
|
||||
print '<div class="div-table-responsive">';
|
||||
print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
|
||||
|
||||
@@ -438,44 +444,33 @@ if ($resql) {
|
||||
print $searchpicto;
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
$totalarray = array();
|
||||
print '<tr class="liste_titre">';
|
||||
if (!empty($arrayfields['aa.account_number']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.account_number']['label'], $_SERVER["PHP_SELF"], "aa.account_number", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
if (!empty($arrayfields['aa.label']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.label']['label'], $_SERVER["PHP_SELF"], "aa.label", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
if (!empty($arrayfields['aa.labelshort']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.labelshort']['label'], $_SERVER["PHP_SELF"], "aa.labelshort", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
if (!empty($arrayfields['aa.account_parent']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.account_parent']['label'], $_SERVER["PHP_SELF"], "aa.account_parent", "", $param, '', $sortfield, $sortorder, 'left ');
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
if (!empty($arrayfields['aa.pcg_type']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.pcg_type']['label'], $_SERVER["PHP_SELF"], 'aa.pcg_type,aa.account_number', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.pcg_type']['help'], 1);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
|
||||
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.reconcilable']['label'], $_SERVER["PHP_SELF"], 'aa.reconcilable', '', $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
}
|
||||
if (!empty($arrayfields['aa.active']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['aa.active']['label'], $_SERVER["PHP_SELF"], 'aa.active', '', $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
|
||||
print "</tr>\n";
|
||||
|
||||
$accountstatic = new AccountingAccount($db);
|
||||
$accountparent = new AccountingAccount($db);
|
||||
|
||||
$i = 0;
|
||||
while ($i < min($num, $limit)) {
|
||||
$obj = $db->fetch_object($resql);
|
||||
@@ -620,8 +615,13 @@ if ($resql) {
|
||||
}
|
||||
|
||||
if ($num == 0) {
|
||||
$totalarray['nbfield']++;
|
||||
print '<tr><td colspan="'.$totalarray['nbfield'].'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
|
||||
$colspan = 1;
|
||||
foreach ($arrayfields as $key => $val) {
|
||||
if (!empty($val['checked'])) {
|
||||
$colspan++;
|
||||
}
|
||||
}
|
||||
print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
|
||||
@@ -78,7 +78,7 @@ $search_country_id = GETPOST('search_country_id', 'int');
|
||||
if ($user->socid > 0) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->chartofaccount) {
|
||||
if (empty($user->rights->accounting->chartofaccount)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
@@ -185,11 +185,6 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$ok = 0;
|
||||
setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors');
|
||||
}
|
||||
/*if (!is_numeric($_POST['code'])) // disabled, code may not be in numeric base
|
||||
{
|
||||
$ok = 0;
|
||||
$msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'<br>';
|
||||
}*/
|
||||
}
|
||||
if (GETPOSTISSET("country") && (GETPOST("country") == '0') && ($id != 2)) {
|
||||
$ok = 0;
|
||||
@@ -228,17 +223,17 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
if ($value == 'price' || preg_match('/^amount/i', $value) || $value == 'taux') {
|
||||
$_POST[$listfieldvalue[$i]] = price2num($_POST[$listfieldvalue[$i]], 'MU');
|
||||
$_POST[$listfieldvalue[$i]] = price2num(GETPOST($listfieldvalue[$i]), 'MU');
|
||||
} elseif ($value == 'entity') {
|
||||
$_POST[$listfieldvalue[$i]] = $conf->entity;
|
||||
}
|
||||
if ($i) {
|
||||
$sql .= ",";
|
||||
}
|
||||
if ($_POST[$listfieldvalue[$i]] == '') {
|
||||
if (GETPOST($listfieldvalue[$i]) == '') {
|
||||
$sql .= "null";
|
||||
} else {
|
||||
$sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'";
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@@ -276,7 +271,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$i = 0;
|
||||
foreach ($listfieldmodify as $field) {
|
||||
if ($field == 'price' || preg_match('/^amount/i', $field) || $field == 'taux') {
|
||||
$_POST[$listfieldvalue[$i]] = price2num($_POST[$listfieldvalue[$i]], 'MU');
|
||||
$_POST[$listfieldvalue[$i]] = price2num(GETPOST($listfieldvalue[$i]), 'MU');
|
||||
} elseif ($field == 'entity') {
|
||||
$_POST[$listfieldvalue[$i]] = $conf->entity;
|
||||
}
|
||||
@@ -284,10 +279,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$sql .= ",";
|
||||
}
|
||||
$sql .= $field."=";
|
||||
if ($_POST[$listfieldvalue[$i]] == '') {
|
||||
if (GETPOST($listfieldvalue[$i]) == '') {
|
||||
$sql .= "null";
|
||||
} else {
|
||||
$sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'";
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@@ -495,7 +490,7 @@ if ($id) {
|
||||
if ($valuetoshow != '') {
|
||||
print '<td class="'.$class.'">';
|
||||
if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
|
||||
print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
print '<a href="'.$tabhelp[$id][$value].'">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
} elseif (!empty($tabhelp[$id][$value])) {
|
||||
print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]);
|
||||
} else {
|
||||
@@ -535,7 +530,7 @@ if ($id) {
|
||||
}
|
||||
|
||||
print '<td colspan="3" class="right">';
|
||||
print '<input type="submit" class="button" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '</td>';
|
||||
print "</tr>";
|
||||
|
||||
@@ -553,16 +548,16 @@ if ($id) {
|
||||
$num = $db->num_rows($resql);
|
||||
$i = 0;
|
||||
|
||||
$param = '&id='.$id;
|
||||
$param = '&id='.urlencode($id);
|
||||
if ($search_country_id > 0) {
|
||||
$param .= '&search_country_id='.$search_country_id;
|
||||
$param .= '&search_country_id='.urlencode($search_country_id);
|
||||
}
|
||||
$paramwithsearch = $param;
|
||||
if ($sortorder) {
|
||||
$paramwithsearch .= '&sortorder='.$sortorder;
|
||||
$paramwithsearch .= '&sortorder='.urlencode($sortorder);
|
||||
}
|
||||
if ($sortfield) {
|
||||
$paramwithsearch .= '&sortfield='.$sortfield;
|
||||
$paramwithsearch .= '&sortfield='.urlencode($sortfield);
|
||||
}
|
||||
|
||||
// There is several pages
|
||||
@@ -631,7 +626,7 @@ if ($id) {
|
||||
fieldListAccountModel($fieldlist, $obj, $tabname[$id], 'edit');
|
||||
}
|
||||
|
||||
print '<td colspan="3" class="right"><a name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"> </a><input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print '<td colspan="3" class="right"><a name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"> </a><input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print ' <input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'"></td>';
|
||||
} else {
|
||||
$tmpaction = 'view';
|
||||
|
||||
@@ -48,7 +48,7 @@ $label = GETPOST('label', 'alpha');
|
||||
if ($user->socid > 0) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->chartofaccount) {
|
||||
if (empty($user->rights->accounting->chartofaccount)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ $object = new AccountingAccount($db);
|
||||
*/
|
||||
|
||||
if (GETPOST('cancel', 'alpha')) {
|
||||
$urltogo = $backtopage ? $backtopage : dol_buildpath('/accountancy/admin/account.php', 1);
|
||||
$urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
|
||||
header("Location: ".$urltogo);
|
||||
exit;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ if ($action == 'add' && $user->rights->accounting->chartofaccount) {
|
||||
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
|
||||
$action = 'create';
|
||||
} else {
|
||||
$sql = 'SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid='.((int) $conf->global->CHARTOFACCOUNTS);
|
||||
$sql = "SELECT pcg_version FROM " . MAIN_DB_PREFIX . "accounting_system WHERE rowid = ".((int) $conf->global->CHARTOFACCOUNTS);
|
||||
|
||||
dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
|
||||
$result = $db->query($sql);
|
||||
@@ -121,7 +121,7 @@ if ($action == 'add' && $user->rights->accounting->chartofaccount) {
|
||||
}
|
||||
if (!$error) {
|
||||
setEventMessages("RecordCreatedSuccessfully", null, 'mesgs');
|
||||
$urltogo = $backtopage ? $backtopage : dol_buildpath('/accountancy/admin/account.php', 1);
|
||||
$urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
|
||||
header("Location: " . $urltogo);
|
||||
exit;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ if ($action == 'add' && $user->rights->accounting->chartofaccount) {
|
||||
} else {
|
||||
$result = $object->fetch($id);
|
||||
|
||||
$sql = 'SELECT pcg_version FROM '.MAIN_DB_PREFIX.'accounting_system WHERE rowid='.((int) $conf->global->CHARTOFACCOUNTS);
|
||||
$sql = "SELECT pcg_version FROM ".MAIN_DB_PREFIX."accounting_system WHERE rowid=".((int) $conf->global->CHARTOFACCOUNTS);
|
||||
|
||||
dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
|
||||
$result2 = $db->query($sql);
|
||||
@@ -260,8 +260,8 @@ if ($action == 'create') {
|
||||
print '<input type="text" name="pcg_type" list="pcg_type_datalist" value="'.dol_escape_htmltag(GETPOSTISSET('pcg_type') ? GETPOST('pcg_type', 'alpha') : $object->pcg_type).'">';
|
||||
// autosuggest from existing account types if found
|
||||
print '<datalist id="pcg_type_datalist">';
|
||||
$sql = 'SELECT DISTINCT pcg_type FROM ' . MAIN_DB_PREFIX . 'accounting_account';
|
||||
$sql .= ' WHERE fk_pcg_version = "' . $db->escape($accountsystem->ref) . '"';
|
||||
$sql = "SELECT DISTINCT pcg_type FROM " . MAIN_DB_PREFIX . "accounting_account";
|
||||
$sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
|
||||
$sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
|
||||
$sql .= ' LIMIT 50000'; // just as a sanity check
|
||||
$resql = $db->query($sql);
|
||||
@@ -337,7 +337,7 @@ if ($action == 'create') {
|
||||
// autosuggest from existing account types if found
|
||||
print '<datalist id="pcg_type_datalist">';
|
||||
$sql = 'SELECT DISTINCT pcg_type FROM ' . MAIN_DB_PREFIX . 'accounting_account';
|
||||
$sql .= ' WHERE fk_pcg_version = "' . $db->escape($accountsystem->ref) . '"';
|
||||
$sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
|
||||
$sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
|
||||
$sql .= ' LIMIT 50000'; // just as a sanity check
|
||||
$resql = $db->query($sql);
|
||||
@@ -361,11 +361,7 @@ if ($action == 'create') {
|
||||
|
||||
print dol_get_fiche_end();
|
||||
|
||||
print '<div class="center">';
|
||||
print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
|
||||
print ' ';
|
||||
print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
|
||||
print '</div>';
|
||||
print $form->buttonsSaveCancel();
|
||||
|
||||
print '</form>';
|
||||
} else {
|
||||
@@ -421,13 +417,13 @@ if ($action == 'create') {
|
||||
print '<div class="tabsAction">';
|
||||
|
||||
if (!empty($user->rights->accounting->chartofaccount)) {
|
||||
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$id.'">'.$langs->trans('Modify').'</a>';
|
||||
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Modify').'</a>';
|
||||
} else {
|
||||
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Modify').'</a>';
|
||||
}
|
||||
|
||||
if (!empty($user->rights->accounting->chartofaccount)) {
|
||||
print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$id.'">'.$langs->trans('Delete').'</a>';
|
||||
print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Delete').'</a>';
|
||||
} else {
|
||||
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Delete').'</a>';
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ print '<table class="border centpercent">';
|
||||
print '<tr><td class="titlefield">'.$langs->trans("AccountingCategory").'</td>';
|
||||
print '<td>';
|
||||
$formaccounting->select_accounting_category($cat_id, 'account_category', 1, 0, 0, 1);
|
||||
print '<input class="button" type="submit" value="'.$langs->trans("Select").'">';
|
||||
print '<input type="submit" class="button" value="'.$langs->trans("Select").'">';
|
||||
print '</td></tr>';
|
||||
|
||||
// Select the accounts
|
||||
@@ -137,7 +137,7 @@ if (!empty($cat_id)) {
|
||||
print '</select><br>';
|
||||
print ajax_combobox('cpt_bk');
|
||||
*/
|
||||
print '<input class="button" type="submit" id="" class="action-delete" value="'.$langs->trans("Add").'"> ';
|
||||
print '<input type="submit" class="button button-add" id="" class="action-delete" value="'.$langs->trans("Add").'"> ';
|
||||
}
|
||||
print '</td></tr>';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2011-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2011-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -91,19 +91,19 @@ $tabsql[32] = "SELECT a.rowid as rowid, a.code as code, a.label, a.range_account
|
||||
$tabsqlsort = array();
|
||||
$tabsqlsort[32] = "position ASC";
|
||||
|
||||
// Nom des champs en resultat de select pour affichage du dictionnaire
|
||||
// Name of the fields in the result of select to display the dictionary
|
||||
$tabfield = array();
|
||||
$tabfield[32] = "code,label,range_account,category_type,formula,position,country";
|
||||
|
||||
// Nom des champs d'edition pour modification d'un enregistrement
|
||||
// Name of editing fields for record modification
|
||||
$tabfieldvalue = array();
|
||||
$tabfieldvalue[32] = "code,label,range_account,category_type,formula,position,country_id";
|
||||
|
||||
// Nom des champs dans la table pour insertion d'un enregistrement
|
||||
// Name of the fields in the table for inserting a record
|
||||
$tabfieldinsert = array();
|
||||
$tabfieldinsert[32] = "code,label,range_account,category_type,formula,position,fk_country";
|
||||
|
||||
// Nom du rowid si le champ n'est pas de type autoincrement
|
||||
// Name of the rowid if the field is not of type autoincrement
|
||||
// Example: "" if id field is "rowid" and has autoincrement on
|
||||
// "nameoffield" if id field is not "rowid" or has not autoincrement on
|
||||
$tabrowid = array();
|
||||
@@ -148,10 +148,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
if ($value == 'formula' && !GETPOST('formula')) {
|
||||
continue;
|
||||
}
|
||||
if ($value == 'range_account' && empty($_POST['range_account'])) {
|
||||
if ($value == 'range_account' && !GETPOST('range_account')) {
|
||||
continue;
|
||||
}
|
||||
if ($value == 'country' || $value == 'country_id') {
|
||||
if (($value == 'country' || $value == 'country_id') && GETPOST('country_id')) {
|
||||
continue;
|
||||
}
|
||||
if (!GETPOSTISSET($value) || GETPOST($value) == '') {
|
||||
@@ -176,6 +176,9 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
if ($fieldnamekey == 'category_type') {
|
||||
$fieldnamekey = 'Calculated';
|
||||
}
|
||||
if ($fieldnamekey == 'country') {
|
||||
$fieldnamekey = 'Country';
|
||||
}
|
||||
|
||||
setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors');
|
||||
}
|
||||
@@ -192,17 +195,6 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors');
|
||||
}
|
||||
|
||||
// Clean some parameters
|
||||
if ($_POST["accountancy_code"] <= 0) {
|
||||
$_POST["accountancy_code"] = ''; // If empty, we force to null
|
||||
}
|
||||
if ($_POST["accountancy_code_sell"] <= 0) {
|
||||
$_POST["accountancy_code_sell"] = ''; // If empty, we force to null
|
||||
}
|
||||
if ($_POST["accountancy_code_buy"] <= 0) {
|
||||
$_POST["accountancy_code_buy"] = ''; // If empty, we force to null
|
||||
}
|
||||
|
||||
// Si verif ok et action add, on ajoute la ligne
|
||||
if ($ok && GETPOST('actionadd', 'alpha')) {
|
||||
if ($tabrowid[$id]) {
|
||||
@@ -240,7 +232,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
if ($i) {
|
||||
$sql .= ",";
|
||||
}
|
||||
if ($_POST[$listfieldvalue[$i]] == '' && !$listfieldvalue[$i] == 'formula') {
|
||||
if (GETPOST($listfieldvalue[$i]) == '' && !$listfieldvalue[$i] == 'formula') {
|
||||
$sql .= "null"; // For vat, we want/accept code = ''
|
||||
} else {
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
@@ -263,7 +255,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
}
|
||||
}
|
||||
|
||||
// Si verif ok et action modify, on modifie la ligne
|
||||
// If check ok and action modify, we modify the line
|
||||
if ($ok && GETPOST('actionmodify', 'alpha')) {
|
||||
if ($tabrowid[$id]) {
|
||||
$rowidcol = $tabrowid[$id];
|
||||
@@ -280,8 +272,8 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldmodify as $field) {
|
||||
if ($field == 'fk_country' && $_POST['country'] > 0) {
|
||||
$_POST[$listfieldvalue[$i]] = $_POST['country'];
|
||||
if ($field == 'fk_country' && GETPOST('country') > 0) {
|
||||
$_POST[$listfieldvalue[$i]] = GETPOST('country');
|
||||
} elseif ($field == 'entity') {
|
||||
$_POST[$listfieldvalue[$i]] = $conf->entity;
|
||||
}
|
||||
@@ -289,10 +281,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$sql .= ",";
|
||||
}
|
||||
$sql .= $field."=";
|
||||
if ($_POST[$listfieldvalue[$i]] == '' && !$listfieldvalue[$i] == 'range_account') {
|
||||
if (GETPOST($listfieldvalue[$i]) == '' && !$listfieldvalue[$i] == 'range_account') {
|
||||
$sql .= "null"; // For range_account, we want/accept code = ''
|
||||
} else {
|
||||
$sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'";
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@@ -430,12 +422,12 @@ print load_fiche_titre($titre, $linkback, $titlepicto);
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("AccountingAccountGroupsDesc", $langs->transnoentitiesnoconv("ByPersonalizedAccountGroups")).'</span><br><br>';
|
||||
|
||||
// Confirmation de la suppression de la ligne
|
||||
// Confirmation of the deletion of the line
|
||||
if ($action == 'delete') {
|
||||
print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id.($search_country_id > 0 ? '&search_country_id='.$search_country_id : ''), $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
|
||||
}
|
||||
|
||||
// Complete requete recherche valeurs avec critere de tri
|
||||
// Complete search query with sorting criteria
|
||||
$sql = $tabsql[$id];
|
||||
|
||||
if ($search_country_id > 0) {
|
||||
@@ -517,7 +509,7 @@ if ($tabname[$id]) {
|
||||
if ($valuetoshow != '') {
|
||||
print '<td class="'.$class.'">';
|
||||
if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
|
||||
print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
print '<a href="'.$tabhelp[$id][$value].'">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
} elseif (!empty($tabhelp[$id][$value])) {
|
||||
print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]);
|
||||
} else {
|
||||
@@ -558,7 +550,7 @@ if ($tabname[$id]) {
|
||||
}
|
||||
|
||||
print '<td colspan="4" class="right">';
|
||||
print '<input type="submit" class="button" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '</td>';
|
||||
print "</tr>";
|
||||
|
||||
@@ -580,7 +572,7 @@ if ($resql) {
|
||||
|
||||
$param = '&id='.$id;
|
||||
if ($search_country_id > 0) {
|
||||
$param .= '&search_country_id='.$search_country_id;
|
||||
$param .= '&search_country_id='.urlencode($search_country_id);
|
||||
}
|
||||
$paramwithsearch = $param;
|
||||
if ($sortorder) {
|
||||
@@ -634,14 +626,14 @@ if ($resql) {
|
||||
// Title of lines
|
||||
print '<tr class="liste_titre">';
|
||||
foreach ($fieldlist as $field => $value) {
|
||||
// Determine le nom du champ par rapport aux noms possibles
|
||||
// dans les dictionnaires de donnees
|
||||
$showfield = 1; // By defaut
|
||||
// Determines the name of the field in relation to the possible names
|
||||
// in data dictionaries
|
||||
$showfield = 1; // By default
|
||||
$class = "left";
|
||||
$sortable = 1;
|
||||
$valuetoshow = '';
|
||||
|
||||
$valuetoshow = ucfirst($fieldlist[$field]); // By defaut
|
||||
$valuetoshow = ucfirst($fieldlist[$field]); // By default
|
||||
$valuetoshow = $langs->trans($valuetoshow); // try to translate
|
||||
if ($fieldlist[$field] == 'source') {
|
||||
$valuetoshow = $langs->trans("Contact");
|
||||
@@ -734,14 +726,14 @@ if ($resql) {
|
||||
print '<td class="center">';
|
||||
print '<input type="hidden" name="page" value="'.$page.'">';
|
||||
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
|
||||
print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print '<input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
|
||||
print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
|
||||
print '</td>';
|
||||
print '<td></td>';
|
||||
} else {
|
||||
$tmpaction = 'view';
|
||||
$parameters = array('var'=>$var, 'fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
|
||||
$parameters = array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
|
||||
$reshook = $hookmanager->executeHooks('viewDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
|
||||
|
||||
$error = $hookmanager->error; $errors = $hookmanager->errors;
|
||||
@@ -811,7 +803,7 @@ if ($resql) {
|
||||
|
||||
// Modify link
|
||||
if ($canbemodified) {
|
||||
print '<td class="center"><a class="reposition editfielda" href="'.$url.'action=edit">'.img_edit().'</a></td>';
|
||||
print '<td class="center"><a class="reposition editfielda" href="'.$url.'action=edit&token='.newToken().'">'.img_edit().'</a></td>';
|
||||
} else {
|
||||
print '<td> </td>';
|
||||
}
|
||||
@@ -820,7 +812,7 @@ if ($resql) {
|
||||
if ($iserasable) {
|
||||
print '<td class="center">';
|
||||
if ($user->admin) {
|
||||
print '<a href="'.$url.'action=delete">'.img_delete().'</a>';
|
||||
print '<a href="'.$url.'action=delete&token='.newToken().'">'.img_delete().'</a>';
|
||||
}
|
||||
//else print '<a href="#">'.img_delete().'</a>'; // Some dictionary can be edited by other profile than admin
|
||||
print '</td>';
|
||||
|
||||
@@ -109,7 +109,7 @@ foreach ($list_account_main as $key) {
|
||||
print '</td>';
|
||||
// Value
|
||||
print '<td>'; // 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(getDolGlobalString($key), $key, 1, '', 1, 1);
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
@@ -124,7 +124,7 @@ print '</td></tr>';
|
||||
|
||||
print "</table>\n";
|
||||
|
||||
print '<div class="center"><input type="submit" class="button" value="'.$langs->trans('Modify').'" name="button"></div>';
|
||||
print '<div class="center"><input type="submit" class="button button-edit" name="button" value="'.$langs->trans('Modify').'"></div>';
|
||||
|
||||
print '</form>';
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ $list_account_main = array(
|
||||
);
|
||||
|
||||
$list_account = array();
|
||||
|
||||
$list_account[] = '---Product---';
|
||||
$list_account[] = 'ACCOUNTING_PRODUCT_SOLD_ACCOUNT';
|
||||
if ($mysoc->isInEEC()) {
|
||||
@@ -63,6 +64,7 @@ if ($mysoc->isInEEC()) {
|
||||
$list_account[] = 'ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT';
|
||||
}
|
||||
$list_account[] = 'ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT';
|
||||
|
||||
$list_account[] = '---Service---';
|
||||
$list_account[] = 'ACCOUNTING_SERVICE_SOLD_ACCOUNT';
|
||||
if ($mysoc->isInEEC()) {
|
||||
@@ -74,11 +76,11 @@ if ($mysoc->isInEEC()) {
|
||||
$list_account[] = 'ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT';
|
||||
}
|
||||
$list_account[] = 'ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT';
|
||||
|
||||
$list_account[] = '---Others---';
|
||||
$list_account[] = 'ACCOUNTING_VAT_BUY_ACCOUNT';
|
||||
$list_account[] = 'ACCOUNTING_VAT_SOLD_ACCOUNT';
|
||||
$list_account[] = 'ACCOUNTING_VAT_PAY_ACCOUNT';
|
||||
$list_account[] = 'ACCOUNTING_ACCOUNT_SUSPENSE';
|
||||
if ($conf->banque->enabled) {
|
||||
$list_account[] = 'ACCOUNTING_ACCOUNT_TRANSFER_CASH';
|
||||
}
|
||||
@@ -96,6 +98,7 @@ if ($conf->loan->enabled) {
|
||||
if ($conf->societe->enabled) {
|
||||
$list_account[] = 'ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT';
|
||||
}
|
||||
$list_account[] = 'ACCOUNTING_ACCOUNT_SUSPENSE';
|
||||
|
||||
/*
|
||||
* Actions
|
||||
@@ -154,6 +157,7 @@ print '<input type="hidden" name="action" value="update">';
|
||||
|
||||
// Define main accounts for thirdparty
|
||||
|
||||
print '<div class="div-table-responsive-no-min">';
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre"><td>'.$langs->trans("ThirdParties").' | '.$langs->trans("Users").'</td><td></td></tr>';
|
||||
|
||||
@@ -164,17 +168,29 @@ foreach ($list_account_main as $key) {
|
||||
$keydesc = $key.'_Desc';
|
||||
|
||||
$htmltext = $langs->trans($keydesc);
|
||||
print '<td class="fieldrequired" width="50%">';
|
||||
print '<td class="fieldrequired">';
|
||||
if ($key == 'ACCOUNTING_ACCOUNT_CUSTOMER') {
|
||||
print img_picto('', 'company', 'class="pictofixedwidth"');
|
||||
} elseif ($key == 'ACCOUNTING_ACCOUNT_SUPPLIER') {
|
||||
print img_picto('', 'company', 'class="pictofixedwidth"');
|
||||
} else {
|
||||
print img_picto('', 'user', 'class="pictofixedwidth"');
|
||||
}
|
||||
print $form->textwithpicto($label, $htmltext);
|
||||
print '</td>';
|
||||
// Value
|
||||
print '<td>'; // Do not force class=right, or it align also the content of the select box
|
||||
print '<td class="right">'; // 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, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accountsmain');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
print "</table>\n";
|
||||
print "</div>\n";
|
||||
|
||||
|
||||
print '<div class="div-table-responsive-no-min">';
|
||||
print '<table class="noborder centpercent">';
|
||||
|
||||
foreach ($list_account as $key) {
|
||||
$reg = array();
|
||||
if (preg_match('/---(.*)---/', $key, $reg)) {
|
||||
@@ -183,10 +199,33 @@ foreach ($list_account as $key) {
|
||||
print '<tr class="oddeven value">';
|
||||
// Param
|
||||
$label = $langs->trans($key);
|
||||
print '<td width="50%">'.$label.'</td>';
|
||||
print '<td>';
|
||||
if (preg_match('/^ACCOUNTING_PRODUCT/', $key)) {
|
||||
print img_picto('', 'product', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_SERVICE/', $key)) {
|
||||
print img_picto('', 'service', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_VAT_PAY_ACCOUNT/', $key)) {
|
||||
print img_picto('', 'payment_vat', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_VAT/', $key)) {
|
||||
print img_picto('', 'vat', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_ACCOUNT_CUSTOMER/', $key)) {
|
||||
print img_picto('', 'bill', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^LOAN_ACCOUNTING_ACCOUNT/', $key)) {
|
||||
print img_picto('', 'loan', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^DONATION_ACCOUNTING/', $key)) {
|
||||
print img_picto('', 'donation', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ADHERENT_SUBSCRIPTION/', $key)) {
|
||||
print img_picto('', 'member', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_ACCOUNT_TRANSFER/', $key)) {
|
||||
print img_picto('', 'bank_account', 'class="pictofixedwidth"');
|
||||
} elseif (preg_match('/^ACCOUNTING_ACCOUNT_SUSPENSE/', $key)) {
|
||||
print img_picto('', 'question', 'class="pictofixedwidth"');
|
||||
}
|
||||
print $label;
|
||||
print '</td>';
|
||||
// Value
|
||||
print '<td>'; // 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, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accounts');
|
||||
print '<td class="right">'; // Do not force class=right, or it align also the content of the select box
|
||||
print $formaccounting->select_account(getDolGlobalString($key), $key, 1, '', 1, 1, 'minwidth100 maxwidth300 maxwidthonsmartphone', 'accounts');
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
@@ -194,9 +233,9 @@ foreach ($list_account as $key) {
|
||||
|
||||
|
||||
print "</table>\n";
|
||||
print "</div>\n";
|
||||
|
||||
|
||||
print '<div class="center"><input type="submit" class="button" value="'.$langs->trans('Modify').'" name="button"></div>';
|
||||
print '<div class="center"><input type="submit" class="button button-edit" name="button" value="'.$langs->trans('Modify').'"></div>';
|
||||
|
||||
print '</form>';
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/**
|
||||
* \file htdocs/accountancy/admin/export.php
|
||||
* \ingroup Accountancy (Double entries)
|
||||
* \brief Setup page to configure accounting expert module
|
||||
* \brief Setup page to configure accounting export module
|
||||
*/
|
||||
require '../../main.inc.php';
|
||||
|
||||
@@ -142,7 +142,7 @@ $linkback = '';
|
||||
print load_fiche_titre($langs->trans('ExportOptions'), $linkback, 'accountancy');
|
||||
|
||||
|
||||
print "\n".'<script type="text/javascript" language="javascript">'."\n";
|
||||
print "\n".'<script type="text/javascript">'."\n";
|
||||
print 'jQuery(document).ready(function () {'."\n";
|
||||
print ' function initfields()'."\n";
|
||||
print ' {'."\n";
|
||||
|
||||
@@ -52,7 +52,7 @@ $langs->loadLangs(array("admin", "compta"));
|
||||
if ($user->socid > 0) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->fiscalyear->write) { // If we can read accounting records, we should be able to see fiscal year.
|
||||
if (empty($user->rights->accounting->fiscalyear->write)) { // If we can read accounting records, we should be able to see fiscal year.
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
@@ -127,7 +127,6 @@ if ($result) {
|
||||
$title = $langs->trans('AccountingPeriods');
|
||||
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $params, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy', 0, $addbutton, '', $limit, 1);
|
||||
|
||||
// Load attribute_label
|
||||
print '<div class="div-table-responsive">';
|
||||
print '<table class="tagtable liste centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
|
||||
@@ -242,11 +242,7 @@ if ($action == 'create') {
|
||||
|
||||
print '</table>';
|
||||
|
||||
print '<br><div class="center">';
|
||||
print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
|
||||
print ' ';
|
||||
print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
|
||||
print '</div>';
|
||||
print $form->buttonsSaveCancel();
|
||||
|
||||
print '</form>';
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ $langs->loadLangs(array("admin", "compta"));
|
||||
if ($user->socid > 0) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->fiscalyear->write) {
|
||||
if (empty($user->rights->accounting->fiscalyear->write)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
|
||||
* Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
|
||||
* Copyright (C) 2013-2019 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2013-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2014-2015 Ari Elbaz (elarifr) <github@accedinfo.com>
|
||||
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
|
||||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
@@ -260,6 +260,22 @@ $linkback = '';
|
||||
//$linkback = '<a href="' . DOL_URL_ROOT . '/admin/modules.php?restore_lastsearch_values=1">' . $langs->trans("BackToModuleList") . '</a>';
|
||||
print load_fiche_titre($title, $linkback, 'accountancy');
|
||||
|
||||
// Show message if accountancy hidden options are activated to help to resolve some problems
|
||||
if (!$user->admin) {
|
||||
if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
|
||||
print '<div class="info">' . $langs->trans("ConstantIsOn", "FACTURE_DEPOSITS_ARE_JUST_PAYMENTS") . '</div>';
|
||||
}
|
||||
if (!empty($conf->global->ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY)) {
|
||||
print '<div class="info">' . $langs->trans("ConstantIsOn", "ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY") . '</div>';
|
||||
}
|
||||
if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
|
||||
print '<div class="info">' . $langs->trans("ConstantIsOn", "MAIN_COMPANY_PERENTITY_SHARED") . '</div>';
|
||||
}
|
||||
if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
|
||||
print '<div class="info">' . $langs->trans("ConstantIsOn", "MAIN_PRODUCT_PERENTITY_SHARED") . '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="update">';
|
||||
@@ -446,7 +462,7 @@ print '</tr>';
|
||||
|
||||
print '</table>';
|
||||
|
||||
print '<div class="center"><input type="submit" class="button" value="'.$langs->trans('Modify').'" name="button"></div>';
|
||||
print '<div class="center"><input type="submit" class="button button-edit" name="button" value="'.$langs->trans('Modify').'"></div>';
|
||||
|
||||
print '</form>';
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ $listoffset = GETPOST('listoffset', 'alpha');
|
||||
$listlimit = GETPOST('listlimit', 'int') > 0 ?GETPOST('listlimit', 'int') : 1000;
|
||||
$active = 1;
|
||||
|
||||
$sortfield = GETPOST("sortfield", 'alpha');
|
||||
$sortorder = GETPOST("sortorder", 'alpha');
|
||||
$sortfield = GETPOST('sortfield', 'aZ09comma');
|
||||
$sortorder = GETPOST('sortorder', 'aZ09comma');
|
||||
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
|
||||
if (empty($page) || $page == -1) {
|
||||
$page = 0;
|
||||
@@ -165,45 +165,19 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
|
||||
// Check that all fields are filled
|
||||
$ok = 1;
|
||||
foreach ($listfield as $f => $value) {
|
||||
if ($fieldnamekey == 'libelle' || ($fieldnamekey == 'label')) {
|
||||
$fieldnamekey = 'Label';
|
||||
}
|
||||
if ($fieldnamekey == 'code') {
|
||||
$fieldnamekey = 'Code';
|
||||
}
|
||||
if ($fieldnamekey == 'nature') {
|
||||
$fieldnamekey = 'NatureOfJournal';
|
||||
}
|
||||
}
|
||||
|
||||
// Other checks
|
||||
if (GETPOSTISSET("code")) {
|
||||
if (GETPOST("code") == '0') {
|
||||
$ok = 0;
|
||||
setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors');
|
||||
}
|
||||
/*if (!is_numeric($_POST['code'])) // disabled, code may not be in numeric base
|
||||
{
|
||||
$ok = 0;
|
||||
$msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'<br>';
|
||||
}*/
|
||||
}
|
||||
if (!GETPOST('label', 'alpha')) {
|
||||
setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors');
|
||||
$ok = 0;
|
||||
}
|
||||
|
||||
// Clean some parameters
|
||||
if ($_POST["accountancy_code"] <= 0) {
|
||||
$_POST["accountancy_code"] = ''; // If empty, we force to null
|
||||
}
|
||||
if ($_POST["accountancy_code_sell"] <= 0) {
|
||||
$_POST["accountancy_code_sell"] = ''; // If empty, we force to null
|
||||
}
|
||||
if ($_POST["accountancy_code_buy"] <= 0) {
|
||||
$_POST["accountancy_code_buy"] = ''; // If empty, we force to null
|
||||
}
|
||||
|
||||
// Si verif ok et action add, on ajoute la ligne
|
||||
if ($ok && GETPOST('actionadd', 'alpha')) {
|
||||
if ($tabrowid[$id]) {
|
||||
@@ -235,16 +209,13 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
if ($value == 'entity') {
|
||||
$_POST[$listfieldvalue[$i]] = $conf->entity;
|
||||
}
|
||||
if ($i) {
|
||||
$sql .= ",";
|
||||
}
|
||||
if ($_POST[$listfieldvalue[$i]] == '') {
|
||||
if (GETPOST($listfieldvalue[$i]) == '') {
|
||||
$sql .= "null"; // For vat, we want/accept code = ''
|
||||
} else {
|
||||
$sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'";
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@@ -254,7 +225,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
$result = $db->query($sql);
|
||||
if ($result) { // Add is ok
|
||||
setEventMessages($langs->transnoentities("RecordSaved"), null, 'mesgs');
|
||||
$_POST = array('id'=>$id); // Clean $_POST array, we keep only
|
||||
$_POST = array('id'=>$id); // Clean $_POST array, we keep only id
|
||||
} else {
|
||||
if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
|
||||
setEventMessages($langs->transnoentities("ErrorRecordAlreadyExists"), null, 'errors');
|
||||
@@ -281,24 +252,15 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldmodify as $field) {
|
||||
if ($field == 'price' || preg_match('/^amount/i', $field) || $field == 'taux') {
|
||||
$_POST[$listfieldvalue[$i]] = price2num($_POST[$listfieldvalue[$i]], 'MU');
|
||||
} elseif ($field == 'entity') {
|
||||
$_POST[$listfieldvalue[$i]] = $conf->entity;
|
||||
}
|
||||
if ($i) {
|
||||
$sql .= ",";
|
||||
}
|
||||
$sql .= $field."=";
|
||||
if ($_POST[$listfieldvalue[$i]] == '' && !($listfieldvalue[$i] == 'code' && $id == 10)) {
|
||||
$sql .= "null"; // For vat, we want/accept code = ''
|
||||
} else {
|
||||
$sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'";
|
||||
}
|
||||
$sql .= $field." = ";
|
||||
$sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'";
|
||||
$i++;
|
||||
}
|
||||
$sql .= " WHERE ".$rowidcol." = ".((int) $rowid);
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
dol_syslog("actionmodify", LOG_DEBUG);
|
||||
//print $sql;
|
||||
@@ -323,7 +285,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete
|
||||
}
|
||||
|
||||
$sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol." = ".((int) $rowid);
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
dol_syslog("delete", LOG_DEBUG);
|
||||
$result = $db->query($sql);
|
||||
@@ -410,7 +372,7 @@ if ($action == 'delete') {
|
||||
if ($id) {
|
||||
// Complete requete recherche valeurs avec critere de tri
|
||||
$sql = $tabsql[$id];
|
||||
$sql .= " WHERE a.entity = ".$conf->entity;
|
||||
$sql .= " WHERE a.entity = ".((int) $conf->entity);
|
||||
|
||||
// If sort order is "country", we use country_code instead
|
||||
if ($sortfield == 'country') {
|
||||
@@ -453,7 +415,7 @@ if ($id) {
|
||||
if ($valuetoshow != '') {
|
||||
print '<td class="'.$class.'">';
|
||||
if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
|
||||
print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
print '<a href="'.$tabhelp[$id][$value].'">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
|
||||
} elseif (!empty($tabhelp[$id][$value])) {
|
||||
print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]);
|
||||
} else {
|
||||
@@ -494,7 +456,7 @@ if ($id) {
|
||||
}
|
||||
|
||||
print '<td colspan="4" class="right">';
|
||||
print '<input type="submit" class="button" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'">';
|
||||
print '</td>';
|
||||
print "</tr>";
|
||||
|
||||
@@ -510,9 +472,9 @@ if ($id) {
|
||||
$num = $db->num_rows($resql);
|
||||
$i = 0;
|
||||
|
||||
$param = '&id='.$id;
|
||||
$param = '&id='.((int) $id);
|
||||
if ($search_country_id > 0) {
|
||||
$param .= '&search_country_id='.$search_country_id;
|
||||
$param .= '&search_country_id='.urlencode($search_country_id);
|
||||
}
|
||||
$paramwithsearch = $param;
|
||||
if ($sortorder) {
|
||||
@@ -606,13 +568,13 @@ if ($id) {
|
||||
print '<td class="center" colspan="4">';
|
||||
print '<input type="hidden" name="page" value="'.$page.'">';
|
||||
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
|
||||
print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print '<input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">';
|
||||
print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
|
||||
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
|
||||
print '</td>';
|
||||
} else {
|
||||
$tmpaction = 'view';
|
||||
$parameters = array('var'=>$var, 'fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
|
||||
$parameters = array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
|
||||
$reshook = $hookmanager->executeHooks('viewDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
|
||||
|
||||
$error = $hookmanager->error; $errors = $hookmanager->errors;
|
||||
@@ -635,7 +597,7 @@ if ($id) {
|
||||
$class = 'tddict';
|
||||
// Show value for field
|
||||
if ($showfield) {
|
||||
print '<!-- '.$fieldlist[$field].' --><td class="'.$class.'">'.$valuetoshow.'</td>';
|
||||
print '<!-- '.$fieldlist[$field].' --><td class="'.$class.'">'.dol_escape_htmltag($valuetoshow).'</td>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
|
||||
* Copyright (C) 2013-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
|
||||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
|
||||
* Copyright (C) 2013-2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
|
||||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
|
||||
* Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
|
||||
*
|
||||
* 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
|
||||
@@ -33,6 +34,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||
if (!empty($conf->categorie->enabled)) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
|
||||
}
|
||||
|
||||
// Load translation files required by the page
|
||||
$langs->loadLangs(array("companies", "compta", "accountancy", "products"));
|
||||
@@ -41,20 +45,25 @@ $langs->loadLangs(array("companies", "compta", "accountancy", "products"));
|
||||
if (empty($conf->accounting->enabled)) {
|
||||
accessforbidden();
|
||||
}
|
||||
if (!$user->rights->accounting->bind->write) {
|
||||
if (empty($user->rights->accounting->bind->write)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
// search & action GETPOST
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$massaction = GETPOST('massaction', 'alpha');
|
||||
$codeventil_buy = GETPOST('codeventil_buy', 'array');
|
||||
$codeventil_sell = GETPOST('codeventil_sell', 'array');
|
||||
$chk_prod = GETPOST('chk_prod', 'array');
|
||||
$default_account = GETPOST('default_account', 'int');
|
||||
$confirm = GETPOST('confirm', 'alpha');
|
||||
$account_number_buy = GETPOST('account_number_buy');
|
||||
$account_number_sell = GETPOST('account_number_sell');
|
||||
$changeaccount = GETPOST('changeaccount', 'array');
|
||||
$changeaccount_buy = GETPOST('changeaccount_buy', 'array');
|
||||
$changeaccount_sell = GETPOST('changeaccount_sell', 'array');
|
||||
$searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0);
|
||||
$searchCategoryProductList = GETPOST('search_category_product_list', 'array');
|
||||
$search_ref = GETPOST('search_ref', 'alpha');
|
||||
$search_label = GETPOST('search_label', 'alpha');
|
||||
$search_desc = GETPOST('search_desc', 'alpha');
|
||||
@@ -68,16 +77,16 @@ $search_onsell = GETPOST('search_onsell', 'alpha');
|
||||
$search_onpurchase = GETPOST('search_onpurchase', 'alpha');
|
||||
|
||||
$accounting_product_mode = GETPOST('accounting_product_mode', 'alpha');
|
||||
$btn_changeaccount = GETPOST('changeaccount', 'alpha');
|
||||
$btn_changetype = GETPOST('changetype', 'alpha');
|
||||
$optioncss = GETPOST('optioncss', 'alpha');
|
||||
|
||||
if (empty($accounting_product_mode)) {
|
||||
$accounting_product_mode = 'ACCOUNTANCY_SELL';
|
||||
}
|
||||
|
||||
$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION);
|
||||
$sortfield = GETPOST("sortfield", 'alpha');
|
||||
$sortorder = GETPOST("sortorder", 'alpha');
|
||||
$sortfield = GETPOST('sortfield', 'aZ09comma');
|
||||
$sortorder = GETPOST('sortorder', 'aZ09comma');
|
||||
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
|
||||
if (empty($page) || $page == -1) {
|
||||
$page = 0;
|
||||
@@ -140,6 +149,8 @@ if ($reshook < 0) {
|
||||
|
||||
// Purge search criteria
|
||||
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers
|
||||
$searchCategoryProductOperator = 0;
|
||||
$searchCategoryProductList = array();
|
||||
$search_ref = '';
|
||||
$search_label = '';
|
||||
$search_desc = '';
|
||||
@@ -164,7 +175,7 @@ if ($action == 'update') {
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($btn_changeaccount)) {
|
||||
if (!empty($chk_prod) && $massaction === 'changeaccount') {
|
||||
//$msg = '<div><span class="accountingprocessing">' . $langs->trans("Processing") . '...</span></div>';
|
||||
if (!empty($chk_prod) && in_array($accounting_product_mode, $accounting_product_modes)) {
|
||||
$accounting = new AccountingAccount($db);
|
||||
@@ -186,19 +197,38 @@ if ($action == 'update') {
|
||||
$msg .= '<div><span style="color:red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Product").' '.$productid.' '.$langs->trans("NotVentilatedinAccount").' : id='.$accounting_account_id.'<br> <pre>'.$sql.'</pre></span></div>';
|
||||
$ko++;
|
||||
} else {
|
||||
$db->begin();
|
||||
|
||||
$sql = '';
|
||||
if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product_perentity (fk_product, entity, '".$db->escape($accountancy_field_name)."')";
|
||||
$sql .= " VALUES (".((int) $productid).", ".((int) $conf->entity).", '".$db->escape($accounting->account_number)."')";
|
||||
$sql .= " ON DUPLICATE KEY UPDATE ".$accountancy_field_name." = '".$db->escape($accounting->account_number)."'";
|
||||
$sql_exists = "SELECT rowid FROM " . MAIN_DB_PREFIX . "product_perentity";
|
||||
$sql_exists .= " WHERE fk_product = " . ((int) $productid) . " AND entity = " . ((int) $conf->entity);
|
||||
$resql_exists = $db->query($sql_exists);
|
||||
if (!$resql_exists) {
|
||||
$msg .= '<div><span style="color:red">'.$langs->trans("ErrorDB").' : '.$langs->trans("Product").' '.$productid.' '.$langs->trans("NotVentilatedinAccount").' : id='.$accounting_account_id.'<br> <pre>'.$resql_exists.'</pre></span></div>';
|
||||
$ko++;
|
||||
} else {
|
||||
$nb_exists = $db->num_rows($resql_exists);
|
||||
if ($nb_exists <= 0) {
|
||||
// insert
|
||||
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_perentity (fk_product, entity, " . $db->escape($accountancy_field_name) . ")";
|
||||
$sql .= " VALUES (" . ((int) $productid) . ", " . ((int) $conf->entity) . ", '" . $db->escape($accounting->account_number) . "')";
|
||||
} else {
|
||||
$obj_exists = $db->fetch_object($resql_exists);
|
||||
// update
|
||||
$sql = "UPDATE " . MAIN_DB_PREFIX . "product_perentity";
|
||||
$sql .= " SET " . $accountancy_field_name . " = '" . $db->escape($accounting->account_number) . "'";
|
||||
$sql .= " WHERE rowid = " . ((int) $obj_exists->rowid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sql = " UPDATE ".MAIN_DB_PREFIX."product";
|
||||
$sql .= " SET ".$accountancy_field_name." = '".$db->escape($accounting->account_number)."'";
|
||||
$sql .= " WHERE rowid = ".((int) $productid);
|
||||
}
|
||||
|
||||
dol_syslog("/accountancy/admin/productaccount.php sql=".$sql, LOG_DEBUG);
|
||||
dol_syslog("/accountancy/admin/productaccount.php", LOG_DEBUG);
|
||||
|
||||
$db->begin();
|
||||
|
||||
if ($db->query($sql)) {
|
||||
$ok++;
|
||||
$db->commit();
|
||||
@@ -234,35 +264,44 @@ $form = new FormAccounting($db);
|
||||
// so we need to get those the rowid of those default value first
|
||||
$accounting = new AccountingAccount($db);
|
||||
// TODO: we should need to check if result is already exists accountaccount rowid.....
|
||||
$aarowid_servbuy = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT, 1);
|
||||
$aarowid_servbuy_intra = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT, 1);
|
||||
$aarowid_servbuy_export = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT, 1);
|
||||
$aarowid_prodbuy = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT, 1);
|
||||
$aarowid_prodbuy_intra = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT, 1);
|
||||
$aarowid_prodbuy_export = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT, 1);
|
||||
$aarowid_servsell = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT, 1);
|
||||
$aarowid_servsell_intra = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT, 1);
|
||||
$aarowid_servsell_export = $accounting->fetch('', $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT, 1);
|
||||
$aarowid_prodsell = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT, 1);
|
||||
$aarowid_prodsell_intra = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT, 1);
|
||||
$aarowid_prodsell_export = $accounting->fetch('', $conf->global->ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT, 1);
|
||||
$aarowid_servbuy = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_BUY_ACCOUNT'), 1);
|
||||
$aarowid_servbuy_intra = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT'), 1);
|
||||
$aarowid_servbuy_export = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT'), 1);
|
||||
$aarowid_prodbuy = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_BUY_ACCOUNT'), 1);
|
||||
$aarowid_prodbuy_intra = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT'), 1);
|
||||
$aarowid_prodbuy_export = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT'), 1);
|
||||
$aarowid_servsell = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT'), 1);
|
||||
$aarowid_servsell_intra = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT'), 1);
|
||||
$aarowid_servsell_export = $accounting->fetch('', getDolGlobalString('ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT'), 1);
|
||||
$aarowid_prodsell = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT'), 1);
|
||||
$aarowid_prodsell_intra = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT'), 1);
|
||||
$aarowid_prodsell_export = $accounting->fetch('', getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT'), 1);
|
||||
|
||||
$aacompta_servbuy = (!empty($conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servbuy_intra = (!empty($conf->global->ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servbuy_export = (!empty($conf->global->ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy = (!empty($conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy_intra = (!empty($conf->global->ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy_export = (!empty($conf->global->ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell_intra = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell_export = (!empty($conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell = (!empty($conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell_intra = (!empty($conf->global->ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell_export = (!empty($conf->global->ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT : $langs->trans("CodeNotDef"));
|
||||
$aacompta_servbuy = getDolGlobalString('ACCOUNTING_SERVICE_BUY_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_servbuy_intra = getDolGlobalString('ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_servbuy_export = getDolGlobalString('ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy = getDolGlobalString('ACCOUNTING_PRODUCT_BUY_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy_intra = getDolGlobalString('ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodbuy_export = getDolGlobalString('ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell_intra = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_servsell_export = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell_intra = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
$aacompta_prodsell_export = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT', $langs->trans("CodeNotDef"));
|
||||
|
||||
llxHeader('', $langs->trans("ProductsBinding"));
|
||||
|
||||
$pcgverid = $conf->global->CHARTOFACCOUNTS;
|
||||
$title = $langs->trans("ProductsBinding");
|
||||
$helpurl = '';
|
||||
|
||||
$paramsCat = '';
|
||||
foreach ($searchCategoryProductList as $searchCategoryProduct) {
|
||||
$paramsCat .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
|
||||
}
|
||||
|
||||
llxHeader('', $title, $helpurl, '', 0, 0, array(), array(), $paramsCat, '');
|
||||
|
||||
$pcgverid = getDolGlobalString('CHARTOFACCOUNTS');
|
||||
$pcgvercode = dol_getIdFromCode($db, $pcgverid, 'accounting_system', 'rowid', 'pcg_version');
|
||||
if (empty($pcgvercode)) {
|
||||
$pcgvercode = $pcgverid;
|
||||
@@ -285,6 +324,9 @@ if (!empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
|
||||
} 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) . "'";
|
||||
}
|
||||
if (!empty($searchCategoryProductList)) {
|
||||
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ
|
||||
}
|
||||
$sql .= ' WHERE p.entity IN ('.getEntity('product').')';
|
||||
if (strlen(trim($search_current_account))) {
|
||||
$sql .= natural_search((empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED) ? "p." : "ppe.") . $accountancy_field_name, $search_current_account);
|
||||
@@ -295,6 +337,30 @@ if ($search_current_account_valid == 'withoutvalidaccount') {
|
||||
if ($search_current_account_valid == 'withvalidaccount') {
|
||||
$sql .= " AND aa.account_number IS NOT NULL";
|
||||
}
|
||||
$searchCategoryProductSqlList = array();
|
||||
if ($searchCategoryProductOperator == 1) {
|
||||
foreach ($searchCategoryProductList as $searchCategoryProduct) {
|
||||
if (intval($searchCategoryProduct) == -2) {
|
||||
$searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL";
|
||||
} elseif (intval($searchCategoryProduct) > 0) {
|
||||
$searchCategoryProductSqlList[] = "cp.fk_categorie = ".$db->escape($searchCategoryProduct);
|
||||
}
|
||||
}
|
||||
if (!empty($searchCategoryProductSqlList)) {
|
||||
$sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")";
|
||||
}
|
||||
} else {
|
||||
foreach ($searchCategoryProductList as $searchCategoryProduct) {
|
||||
if (intval($searchCategoryProduct) == -2) {
|
||||
$searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL";
|
||||
} elseif (intval($searchCategoryProduct) > 0) {
|
||||
$searchCategoryProductSqlList[] = "p.rowid IN (SELECT fk_product FROM ".MAIN_DB_PREFIX."categorie_product WHERE fk_categorie = ".((int) $searchCategoryProduct).")";
|
||||
}
|
||||
}
|
||||
if (!empty($searchCategoryProductSqlList)) {
|
||||
$sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")";
|
||||
}
|
||||
}
|
||||
// Add search filter like
|
||||
if (strlen(trim($search_ref))) {
|
||||
$sql .= natural_search("p.ref", $search_ref);
|
||||
@@ -315,6 +381,15 @@ if ($search_onpurchase != '' && $search_onpurchase != '-1') {
|
||||
$sql .= natural_search('p.tobuy', $search_onpurchase, 1);
|
||||
}
|
||||
|
||||
$sql .= " GROUP BY p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.tva_tx,";
|
||||
$sql .= " p.fk_product_type,";
|
||||
$sql .= ' p.tms,';
|
||||
if (empty($conf->global->MAIN_PRODUCT_PERENTITY_SHARED)) {
|
||||
$sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export, p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export";
|
||||
} else {
|
||||
$sql .= " ppe.accountancy_code_sell, ppe.accountancy_code_sell_intra, ppe.accountancy_code_sell_export, ppe.accountancy_code_buy, ppe.accountancy_code_buy_intra, ppe.accountancy_code_buy_export";
|
||||
}
|
||||
|
||||
$sql .= $db->order($sortfield, $sortorder);
|
||||
|
||||
$nbtotalofrecords = '';
|
||||
@@ -329,7 +404,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
|
||||
|
||||
$sql .= $db->plimit($limit + 1, $offset);
|
||||
|
||||
dol_syslog("/accountancy/admin/productaccount.php:: sql=".$sql, LOG_DEBUG);
|
||||
dol_syslog("/accountancy/admin/productaccount.php", LOG_DEBUG);
|
||||
$result = $db->query($sql);
|
||||
if ($result) {
|
||||
$num = $db->num_rows($result);
|
||||
@@ -342,11 +417,17 @@ if ($result) {
|
||||
if ($limit > 0 && $limit != $conf->liste_limit) {
|
||||
$param .= '&limit='.urlencode($limit);
|
||||
}
|
||||
if ($searchCategoryProductOperator == 1) {
|
||||
$param .= "&search_category_product_operator=".urlencode($searchCategoryProductOperator);
|
||||
}
|
||||
foreach ($searchCategoryProductList as $searchCategoryProduct) {
|
||||
$param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct);
|
||||
}
|
||||
if ($search_ref > 0) {
|
||||
$param .= "&search_desc=".urlencode($search_ref);
|
||||
$param .= "&search_ref=".urlencode($search_ref);
|
||||
}
|
||||
if ($search_label > 0) {
|
||||
$param .= "&search_desc=".urlencode($search_label);
|
||||
$param .= "&search_label=".urlencode($search_label);
|
||||
}
|
||||
if ($search_desc > 0) {
|
||||
$param .= "&search_desc=".urlencode($search_desc);
|
||||
@@ -416,11 +497,61 @@ if ($result) {
|
||||
$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
|
||||
$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
|
||||
|
||||
if ($massaction !== 'set_default_account') {
|
||||
$arrayofmassactions = array(
|
||||
'changeaccount'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Save")
|
||||
,'set_default_account'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("ConfirmPreselectAccount")
|
||||
);
|
||||
$massactionbutton = $form->selectMassAction('', $arrayofmassactions, 1);
|
||||
}
|
||||
|
||||
$buttonsave = '<input type="submit" class="button button-save" id="changeaccount" name="changeaccount" value="'.$langs->trans("Save").'">';
|
||||
//print '<br><div class="center">'.$buttonsave.'</div>';
|
||||
|
||||
$texte = $langs->trans("ListOfProductsServices");
|
||||
print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $buttonsave, $num, $nbtotalofrecords, '', 0, '', '', $limit, 0, 0, 1);
|
||||
print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, '', 0, '', '', $limit, 0, 0, 1);
|
||||
|
||||
if ($massaction == 'set_default_account') {
|
||||
$formquestion[]=array('type' => 'other',
|
||||
'name' => 'set_default_account',
|
||||
'label' => $langs->trans("AccountancyCode"),
|
||||
'value' => $form->select_account('', 'default_account', 1, array(), 0, 0, 'maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone'));
|
||||
print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmPreselectAccount"), $langs->trans("ConfirmPreselectAccountQuestion", count($chk_prod)), "confirm_set_default_account", $formquestion, 1, 0, 200, 500, 1);
|
||||
}
|
||||
|
||||
// Filter on categories
|
||||
$moreforfilter = '';
|
||||
if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) {
|
||||
$moreforfilter .= '<div class="divsearchfield">';
|
||||
$moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"');
|
||||
$categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1);
|
||||
$categoriesProductArr[-2] = '- '.$langs->trans('NotCategorized').' -';
|
||||
$moreforfilter .= Form::multiselectarray('search_category_product_list', $categoriesProductArr, $searchCategoryProductList, 0, 0, 'minwidth300');
|
||||
$moreforfilter .= ' <input type="checkbox" class="valignmiddle" name="search_category_product_operator" value="1"'.($searchCategoryProductOperator == 1 ? ' checked="checked"' : '').'/> <span class="none">'.$langs->trans('UseOrOperatorForCategories').'</span>';
|
||||
$moreforfilter .= '</div>';
|
||||
}
|
||||
|
||||
//Show/hide child products. Hidden by default
|
||||
if (!empty($conf->variants->enabled) && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
|
||||
$moreforfilter .= '<div class="divsearchfield">';
|
||||
$moreforfilter .= '<input type="checkbox" id="search_show_childproducts" name="search_show_childproducts"'.($show_childproducts ? 'checked="checked"' : '').'>';
|
||||
$moreforfilter .= ' <label for="search_show_childproducts">'.$langs->trans('ShowChildProducts').'</label>';
|
||||
$moreforfilter .= '</div>';
|
||||
}
|
||||
|
||||
$parameters = array();
|
||||
$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
|
||||
if (empty($reshook)) {
|
||||
$moreforfilter .= $hookmanager->resPrint;
|
||||
} else {
|
||||
$moreforfilter = $hookmanager->resPrint;
|
||||
}
|
||||
|
||||
if ($moreforfilter) {
|
||||
print '<div class="liste_titre liste_titre_bydiv centpercent">';
|
||||
print $moreforfilter;
|
||||
print '</div>';
|
||||
}
|
||||
|
||||
print '<div class="div-table-responsive">';
|
||||
print '<table class="liste '.($moreforfilter ? "listwithfilterbefore" : "").'">';
|
||||
@@ -625,7 +756,7 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
} elseif ($accounting_product_mode == 'ACCOUNTANCY_BUY_INTRA') {
|
||||
// Accounting account buy intra (In EEC)
|
||||
@@ -639,7 +770,7 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
} elseif ($accounting_product_mode == 'ACCOUNTANCY_BUY_EXPORT') {
|
||||
// Accounting account buy export (Out of EEC)
|
||||
@@ -653,7 +784,7 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
} elseif ($accounting_product_mode == 'ACCOUNTANCY_SELL') {
|
||||
// Accounting account sell
|
||||
@@ -667,7 +798,7 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
} elseif ($accounting_product_mode == 'ACCOUNTANCY_SELL_INTRA') {
|
||||
// Accounting account sell intra (In EEC)
|
||||
@@ -681,7 +812,7 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
} else {
|
||||
// Accounting account sell export (Out of EEC)
|
||||
@@ -694,20 +825,27 @@ if ($result) {
|
||||
if (!empty($obj->aaid)) {
|
||||
$defaultvalue = ''; // Do not suggest default new value is code is already valid
|
||||
}
|
||||
print $form->select_account($defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print $form->select_account(($default_account > 0 && $confirm === 'yes' && in_array($product_static->id, $chk_prod)) ? $default_account : $defaultvalue, 'codeventil_'.$product_static->id, 1, array(), 1, 0, 'maxwidth300 maxwidthonsmartphone productforselect');
|
||||
print '</td>';
|
||||
}
|
||||
|
||||
if (!empty($chk_prod)) {
|
||||
$ischecked = 0;
|
||||
if (in_array($product_static->id, $chk_prod)) {
|
||||
$ischecked=true;
|
||||
}
|
||||
}
|
||||
|
||||
// Checkbox select
|
||||
print '<td class="center">';
|
||||
print '<input type="checkbox" class="checkforselect productforselectcodeventil_'.$product_static->id.'" name="chk_prod[]" value="'.$obj->rowid.'"/></td>';
|
||||
print '<input type="checkbox" class="checkforselect productforselectcodeventil_'.$product_static->id.'" name="chk_prod[]" '.($ischecked ? "checked" : "").' value="'.$obj->rowid.'"/></td>';
|
||||
print "</tr>";
|
||||
$i++;
|
||||
}
|
||||
print '</table>';
|
||||
print '</div>';
|
||||
|
||||
print '<script type="text/javascript" language="javascript">
|
||||
print '<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
function init_savebutton()
|
||||
{
|
||||
|
||||