Merge branch 'develop' into develop_new_accountancy_sell_journal_support_discount_on_invoice
This commit is contained in:
commit
9edf0be1ec
660 changed files with 9925 additions and 4644 deletions
|
|
@ -15,7 +15,7 @@ Every modification must respect:
|
|||
- ❌ Do not break compatibility of PHP functions and methods
|
||||
- ❌ Do not introduce external dependencies without validation
|
||||
- ❌ Separate page actions in the `/* Actions */` section of the PHP code and the rendering part in the `/* Views */` section
|
||||
- ❌ Never commit directly to `main` or `master` branch
|
||||
- ❌ Never commit directly to `develop` or version branch matching regex `^\d+\.\d+$`
|
||||
- ❌ Never use PHP native curl functions to call a GET or POST URL, but use instead the Dolibarr function getURLContent()
|
||||
- ✅ Use Dolibarr hooks whenever possible
|
||||
- ✅ Respect existing naming conventions
|
||||
|
|
@ -53,7 +53,6 @@ Before writing any code, the agent **must**:
|
|||
- PHP >= 7.3 (minimum support); PHP 8.1+ recommended for new external modules
|
||||
- ⚠️ When writing a **bug fix**, always target the lowest compatible PHP version
|
||||
of the branch being patched — do not use PHP 8.x syntax on a fix targeting v19 or v20
|
||||
- Use `declare(strict_types=1)` when targeting PHP 8.1+
|
||||
- Respect PSR-12, but **indentations must use Tabs, not Spaces**
|
||||
- Write short, readable, and testable functions
|
||||
- Avoid side effects
|
||||
|
|
@ -66,8 +65,7 @@ Before writing any code, the agent **must**:
|
|||
- Use Dolibarr database functions exclusively — never use PDO or MySQLi directly
|
||||
- In pages: use global `$db`
|
||||
- In classes: use `$this->db`
|
||||
- ✅ Always escape user inputs
|
||||
- ✅ SQL forged by PHP must escape fields with `db->escape()`, `db->sanitize()`, or by casting values to `(int)` or `(float)`
|
||||
- ✅ SQL forged by PHP must escaped fields with `db->escape()`, `db->sanitize()`, or by casting values to `(int)` or `(float)`
|
||||
- ✅ Always use `$db->query()` followed by `$db->fetch_object()` or `$db->fetch_array()` to retrieve results
|
||||
- ✅ SQL scripts for table and index creation must be placed in `htdocs/install/mysql/tables/` (see existing files for examples)
|
||||
- ❌ Never run SQL queries inside loops (avoid N+1 problem — use JOINs or batch queries instead)
|
||||
|
|
@ -94,7 +92,8 @@ Before writing any code, the agent **must**:
|
|||
|
||||
- Never hardcode user-facing strings — always use `$langs->trans('Key')`
|
||||
- Language files must be placed in `mymodule/langs/en_US/` (and other locales as needed)
|
||||
- Language key names must be in English and PascalCase (e.g., `MyModuleLabel`, not `MonLibellé`)
|
||||
- All code comments and variables or functions names must be in English.
|
||||
- Language key names must use PascalCase (e.g., `MyModuleLabel`, not `monLibelléModule`)
|
||||
- Load the language file at the top of the page: `$langs->load('mymodule@mymodule')`
|
||||
|
||||
---
|
||||
|
|
@ -103,12 +102,13 @@ Before writing any code, the agent **must**:
|
|||
|
||||
Before any modification, verify:
|
||||
- Creation / edition / deletion workflows
|
||||
- User rights enforcement (`$user->rights->module->action`)
|
||||
- Multi-entity compatibility (`$conf->entity`)
|
||||
- User rights enforcement (`$user->hasRights("module", "permission")` or `$user->hasRights("module", "objectname", "permission")`)
|
||||
- Multi-entity compatibility (add ` AND entity IN ('.getDolEntity("tablename").')`)
|
||||
|
||||
If possible:
|
||||
- Add a PHPUnit test file in `htdocs/modulebuilder/template/test/phpunit/`
|
||||
- Reference the `phpunit.xml` file at the root of the project to run the test suite
|
||||
- If doing an external module, add a PHPUnit test file in `yourmoduledir/test/phpunit/`
|
||||
- If modifying the Dolibarr code project, add a PHPUnit test file into `test/phpunit/` and add the entry into file `test/phpunit/AllTests.php`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -123,8 +123,9 @@ If possible:
|
|||
|
||||
## 🔒 Security
|
||||
|
||||
- Always validate inputs (`GET`, `POST`) via `GETPOST()` with a type parameter
|
||||
- Prevent SQL injection (use `db->escape()`) and XSS (use `dol_escape_htmltag()`)
|
||||
- Always validate user inputs (`GET`, `POST`) via `GETPOST()` with a type parameter
|
||||
- Prevent SQL injection (use `db->escape()` or cast into `(int)` or `(float)`)
|
||||
- Prevent XSS injection by escaping HTML output (use `dolPrintHTML()`, `dolPrintHTMLForAttribute()`)
|
||||
- Always include Dolibarr CSRF tokens in POST forms: `<input type="hidden" name="token" value="'.newToken().'">`
|
||||
|
||||
---
|
||||
|
|
@ -153,7 +154,7 @@ If possible:
|
|||
- `develop` branch for both fixes and new features
|
||||
- ❌ Never commit directly to `main` or `develop` without a reviewed PR
|
||||
- Commit message format: `TYPE: #issueNumber Short description`
|
||||
- Types: `NEW`, `FIX`, `CLOSE`
|
||||
- Types: `NEW`, `FIX` or `CLOSE`
|
||||
- Example: `FIX: #1234 Correct VAT calculation on credit notes`
|
||||
- Update the `ChangeLog` file with a summary of significant changes
|
||||
- When fixing a bug, apply the patch on the **oldest affected branch first**,
|
||||
|
|
@ -177,6 +178,7 @@ If possible:
|
|||
- Change the global architecture of existing modules
|
||||
- Delete code without justification and a comment explaining why
|
||||
- Add external dependencies (Composer packages, JS libraries) without prior validation
|
||||
- Modify the `ChangeLog` file (this file will be updated by the maintainer during the release process)
|
||||
|
||||
---
|
||||
|
||||
95
.agents/skills/add-unit-test/SKILL.md
Normal file
95
.agents/skills/add-unit-test/SKILL.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
name: add-unit-test
|
||||
description: Add a unit test to test functions or methods.
|
||||
license: MIT
|
||||
user-invocable: true
|
||||
allowed-tools:
|
||||
- read_file
|
||||
- write_file
|
||||
- grep
|
||||
---
|
||||
|
||||
|
||||
# Skill: Add a Unit Test for Dolibarr
|
||||
|
||||
## When to use this skill
|
||||
|
||||
Use this skill whenever the user asks to create, modify, or complete a **PHP unit test** for the Dolibarr ERP/CRM project.
|
||||
|
||||
The goal is to produce a unit test that follows Dolibarr conventions and integrates cleanly into the existing PHPUnit test suite.
|
||||
|
||||
|
||||
## Inputs
|
||||
|
||||
The user request should contain, when available:
|
||||
|
||||
- a name of the function to make the unit test for
|
||||
- or the method of the class name to make the unit test for
|
||||
|
||||
|
||||
## General Rules
|
||||
|
||||
- Follow the coding style already used in files into directory test/phpunit/
|
||||
- Modify the minimum amount of existing code.
|
||||
- Prefer adding new test methods instead of modifying existing ones.
|
||||
- Tests must be deterministic and independent.
|
||||
- Avoid dependencies on external services.
|
||||
- Clean up every object created during the test.
|
||||
|
||||
## Test Location
|
||||
|
||||
Locate the most appropriate existing PHPUnit test file in test/phpunit.
|
||||
|
||||
If no suitable test exists, create one in:
|
||||
|
||||
```
|
||||
test/phpunit/
|
||||
```
|
||||
|
||||
using the naming convention:
|
||||
|
||||
```
|
||||
FeatureTest.php
|
||||
```
|
||||
|
||||
|
||||
## Naming
|
||||
|
||||
A test method should describe the expected behavior.
|
||||
|
||||
Examples:
|
||||
|
||||
```php
|
||||
public function testCreateObject()
|
||||
public function testDeleteObject()
|
||||
public function testFetchReturnsExpectedValues()
|
||||
public function testInvalidInputThrowsException()
|
||||
```
|
||||
|
||||
## Assertions
|
||||
|
||||
Prefer specific assertions.
|
||||
|
||||
Good:
|
||||
|
||||
```php
|
||||
$this->assertTrue($result);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected, $actual);
|
||||
$this->assertCount(3, $array);
|
||||
$this->assertNull($value);
|
||||
$this->assertNotNull($value);
|
||||
```
|
||||
|
||||
Avoid generic assertions when a more precise one exists.
|
||||
|
||||
|
||||
## Output
|
||||
|
||||
When generating code:
|
||||
|
||||
- provide only the relevant PHP code
|
||||
- preserve the existing file formatting
|
||||
- do not rewrite unrelated methods
|
||||
- explain briefly what is being tested
|
||||
|
||||
51
.agents/skills/code-review/SKILL.md
Normal file
51
.agents/skills/code-review/SKILL.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
name: code-review
|
||||
description: Review code and fix bad practices
|
||||
license: MIT
|
||||
user-invocable: true
|
||||
allowed-tools:
|
||||
- read_file
|
||||
- write_file
|
||||
- grep
|
||||
---
|
||||
|
||||
|
||||
# Skill: Review code for Dolibarr practices and fix it
|
||||
|
||||
## When to use this skill
|
||||
|
||||
Use this skill whenever the user asks to review code to fix bad practices or to update code to match good practices.
|
||||
|
||||
|
||||
## Inputs
|
||||
|
||||
The user request should contain, when available:
|
||||
|
||||
- a module name
|
||||
- or a directory name
|
||||
- or a file name
|
||||
|
||||
|
||||
## General Rules
|
||||
|
||||
- Follow the coding style already used in files in module builder template in htdocs/modulebuilder/templates
|
||||
- Modify the minimum amount of existing code.
|
||||
|
||||
|
||||
## Rules
|
||||
|
||||
- Use PSR-12 coding style except tabulation that must use TAB characters and not SPACES.
|
||||
- Remove all spaces at end of lines
|
||||
- Rewrite in english all code comments that are not in english
|
||||
- Scan files for security vulnerabilities
|
||||
|
||||
|
||||
## Output
|
||||
|
||||
When generating code:
|
||||
|
||||
- provide only the relevant PHP code
|
||||
- preserve the existing file formatting
|
||||
- do not rewrite unrelated methods
|
||||
- explain briefly what is being tested
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -22,6 +22,8 @@ body:
|
|||
label: Dolibarr Version
|
||||
description: Affected Dolibarr version(s)
|
||||
placeholder: 19.0, develop, ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: environment-php
|
||||
|
|
@ -40,6 +42,8 @@ body:
|
|||
attributes:
|
||||
label: Steps to reproduce the behavior and expected behavior
|
||||
description: Verbose description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: files
|
||||
|
|
|
|||
5
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
5
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
|
|
@ -28,8 +28,3 @@ body:
|
|||
label: Suggested implementation
|
||||
description: Verbose description
|
||||
|
||||
- type: textarea
|
||||
id: suggested-steps
|
||||
attributes:
|
||||
label: Suggested steps
|
||||
description: List of tasks to achieve goal
|
||||
|
|
|
|||
37
.github/scripts/get_changed_php.sh
vendored
37
.github/scripts/get_changed_php.sh
vendored
|
|
@ -1,5 +1,7 @@
|
|||
#!/bin/bash
|
||||
# Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
# Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
|
||||
# shellcheck disable=2129,2128,2034,2016
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
|
@ -41,22 +43,33 @@ repo="${GITHUB_REPOSITORY##*/}" # Extract text after the last '/'
|
|||
page=1
|
||||
per_page=100
|
||||
changed_php_files=()
|
||||
changed_phan_files=()
|
||||
changed_lang_files=()
|
||||
|
||||
# Get phan path configuration
|
||||
phan_directory_list=$(php -r '$config = require("dev/tools/phan/config.php"); echo "^".implode("|",$config["directory_list"]);')
|
||||
phan_exclude_directory=$(php -r '$config = require("dev/tools/phan/config.php"); echo "^".implode("|",$config["exclude_analysis_directory_list"]);')
|
||||
|
||||
phan_exclude_file_regex=$(php -r '$config = require("dev/tools/phan/config.php"); echo $config["exclude_file_regex"];')
|
||||
phan_exclude_file_regex=${phan_exclude_file_regex#@}
|
||||
phan_exclude_file_regex=${phan_exclude_file_regex%@}
|
||||
|
||||
# Loop through all pages to gather changed files
|
||||
while true; do
|
||||
response=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
"https://api.github.com/repos/${owner}/${repo}/pulls/${pr_number}/files?per_page=${per_page}&page=${page}")
|
||||
|
||||
phan_exclude_file_regex=$(php -r '$config = require("dev/tools/phan/config.php"); echo $config["exclude_file_regex"];')
|
||||
|
||||
|
||||
# Filter for files ending with .php and add them to the list
|
||||
mapfile -t files < <(echo "$response" | jq -r '.[] | select((.filename | test("\\.php$")) and (.filename | test("^dev/") | not)) | .filename' | grep -vP "$phan_exclude_file_regex")
|
||||
mapfile -t files < <(echo "$response" | jq -r '.[] | select((.filename | test("\\.php$")) and (.filename | test("^dev/") | not)) | .filename')
|
||||
changed_php_files+=("${files[@]}")
|
||||
|
||||
mapfile -t files < <(echo "$response" | jq -r '.[] | select((.filename | test("\\.php$")) and (.filename | test("'"$phan_directory_list"'"))) | .filename' | grep -vP "$phan_exclude_file_regex")
|
||||
changed_phan_files+=("${files[@]}")
|
||||
|
||||
mapfile -t files < <(echo "$response" | jq -r '.[] | select(.filename | test("\\.lang$")) | .filename')
|
||||
changed_lang_files+=("${files[@]}")
|
||||
changed_lang_files+=("${files[@]}")
|
||||
|
||||
# Check if we have reached the last page (less than per_page results)
|
||||
count=$(echo "$response" | jq 'length')
|
||||
|
|
@ -69,10 +82,12 @@ done
|
|||
|
||||
# Build a space-separated string of changed PHP and lang files
|
||||
# This does not cope with files that have spaces.
|
||||
|
||||
# But such files do not exist in the project (at least not for the
|
||||
# files we are filtering).
|
||||
all_changed_files=$(IFS=" " ; echo "${changed_php_files[*]}")
|
||||
all_changed_lang=$(IFS=" " ; echo "${changed_lang_files[*]}")
|
||||
phan_changed_files=$(IFS=" " ; echo "${changed_phan_files[*]}")
|
||||
|
||||
|
||||
forbidden_files=""
|
||||
|
|
@ -85,21 +100,31 @@ forbidden_files=""
|
|||
#fi
|
||||
|
||||
|
||||
# Determine changed files flag
|
||||
if [ -z "$all_changed_files" ]; then
|
||||
# Determine changed files flags
|
||||
if [ -z "${all_changed_files}" ]; then
|
||||
any_changed="false"
|
||||
else
|
||||
any_changed="true"
|
||||
fi
|
||||
|
||||
if [ -z "${phan_changed_files}" ]; then
|
||||
phan_changed="false"
|
||||
else
|
||||
phan_changed="true"
|
||||
fi
|
||||
|
||||
# Set outputs for GitHub Actions if GITHUB_OUTPUT is available
|
||||
if [ -n "${GITHUB_OUTPUT:-}" ]; then
|
||||
echo "any_changed=${any_changed}" >> "$GITHUB_OUTPUT"
|
||||
echo "phan_changed=${phan_changed}" >> "$GITHUB_OUTPUT"
|
||||
echo "all_changed_files=${all_changed_files}" >> "$GITHUB_OUTPUT"
|
||||
echo "phan_changed_files=${phan_changed_files[*]}" >> "$GITHUB_OUTPUT"
|
||||
echo "forbidden_files=${forbidden_files}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Otherwise, print the outputs
|
||||
echo "any_changed=${any_changed}"
|
||||
echo "phan_changed=${phan_changed}"
|
||||
echo "phan_changed_files=${phan_changed_files[*]}"
|
||||
echo "all_changed_files=${all_changed_files}"
|
||||
echo "forbidden_files=${forbidden_files}"
|
||||
fi
|
||||
|
|
|
|||
5
.github/workflows/phan.yml
vendored
5
.github/workflows/phan.yml
vendored
|
|
@ -61,9 +61,10 @@ jobs:
|
|||
# - the merge from branch contains 'phan_full', or,
|
||||
# - there are changes in PHP files.
|
||||
# Note: --output-mode=github does not provide file:line, so using checkstyle and cs2pr
|
||||
if: ${{ ! cancelled() && (github.ref_name == 'develop' || github.ref_name == 'refs/heads/develop' || endsWith(github.ref_name, '.0') || contains(github.head_ref, 'phan_full') || steps.changed-php.outputs.any_changed == 'true') }}
|
||||
if: ${{ ! cancelled() && (github.ref_name == 'develop' || github.ref_name == 'refs/heads/develop' || endsWith(github.ref_name, '.0') || contains(github.head_ref, 'phan_full') || steps.changed-php.outputs.phan_changed == 'true') }}
|
||||
env:
|
||||
ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }}
|
||||
PHAN_CHANGED_FILES: ${{ steps.changed-php.outputs.phan_changed_files }}
|
||||
# shellcheck disable=2086
|
||||
FILE_CHANGED_LIST: /tmp/phan-changed.lst
|
||||
run: |
|
||||
|
|
@ -73,7 +74,7 @@ jobs:
|
|||
phan $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=checkstyle -o _phan.xml
|
||||
else
|
||||
echo -n "" > "$FILE_CHANGED_LIST"
|
||||
for f in $ALL_CHANGED_FILES; do echo "$f" >> "$FILE_CHANGED_LIST"; done
|
||||
for f in $PHAN_CHANGED_FILES; do echo "$f" >> "$FILE_CHANGED_LIST"; done
|
||||
# Must exclude same files as in phan configuration
|
||||
grep -v -E '^htdocs/(custom/|.*/canvas/.*/tpl/.*.tpl.php|admin/tools/ui/|includes/(nusoap/|restler/|stripe/)|conf/conf.php)$' "$FILE_CHANGED_LIST"> "$FILE_CHANGED_LIST".tmp || true
|
||||
mv "$FILE_CHANGED_LIST".tmp "$FILE_CHANGED_LIST"
|
||||
|
|
|
|||
3
.github/workflows/phpstan.yml
vendored
3
.github/workflows/phpstan.yml
vendored
|
|
@ -21,6 +21,7 @@ env:
|
|||
gh_event: ${{ inputs.gh_event || github.event_name }}
|
||||
CACHE_KEY_PART: ${{ ( inputs.gh_event == 'pull_request' || github.event_name == 'pull_request' ) && format('{0}-{1}', github.base_ref, github.head_ref) || github.ref_name }}
|
||||
GITHUB_JSON: ${{ toJSON(github) }} # Helps in debugging Github Action
|
||||
DUMMY_FILE: htdocs/theme/md/progress.inc.php
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job
|
||||
|
|
@ -113,7 +114,7 @@ jobs:
|
|||
fi
|
||||
|
||||
echo phpstan analyse --no-progress --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php ${ALL_CHANGED_FILES}
|
||||
phpstan analyse --no-progress --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php ${ALL_CHANGED_FILES} | tee _stan.xml | cs2pr --graceful-warnings
|
||||
phpstan analyse --no-progress --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php "${{ env.DUMMY_FILE }}" ${ALL_CHANGED_FILES} | tee _stan.xml | cs2pr --graceful-warnings
|
||||
fi
|
||||
# continue-on-error: true
|
||||
|
||||
|
|
|
|||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
|
|
@ -157,7 +157,7 @@ jobs:
|
|||
ls -l ~/.cache/pre-commit/
|
||||
|
||||
- name: Convert Raw Log to Annotations
|
||||
uses: mdeweerd/logToCheckStyle@v2025.11.2
|
||||
uses: mdeweerd/logToCheckStyle@v2026.7.1
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
in: ${{ env.RAW_LOG }}
|
||||
|
|
|
|||
2
.github/workflows/windows-ci.yml
vendored
2
.github/workflows/windows-ci.yml
vendored
|
|
@ -192,7 +192,7 @@ jobs:
|
|||
for /f "tokens=2 delims==" %%A in ('doskey /m:err') do EXIT /B %%A
|
||||
|
||||
- name: Convert Raw Log to Annotations
|
||||
uses: mdeweerd/logToCheckStyle@v2025.11.2
|
||||
uses: mdeweerd/logToCheckStyle@v2026.7.1
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
in: ${{ env.PHPUNIT_LOG }}
|
||||
|
|
|
|||
15
.mailmap
15
.mailmap
|
|
@ -4,11 +4,13 @@
|
|||
#
|
||||
# This files allows to have several profiles (the second part) matched to the same name/email (the first part).
|
||||
#
|
||||
Laurent Destailleur <eldy@destailleur.fr> Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
Laurent Destailleur <eldy@destailleur.fr> eldy <eldy@destailleur.fr>
|
||||
Laurent Destailleur <eldy@destailleur.fr> Laurent Destailleur <ldestailleur@teclib.com>
|
||||
Laurent Destailleur <eldy@destailleur.fr> eldy10 <eldy10@master8.(none)>
|
||||
Laurent Destailleur <eldy@destailleur.fr> Laurent Destailleur <eldy@destailleur.fr>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> eldy <eldy@destailleur.fr>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> Laurent Destailleur <ldestailleur@teclib.com>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> eldy10 <eldy10@master8.(none)>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> Laurent Destailleur <eldy@destailleur.fr>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> Laurent Destailleur <contact@dolicloud.com>
|
||||
Laurent Destailleur <ldestailleur@dolicloud.com> Laurent Destailleur <ldestailleur@dolicloud.com>
|
||||
Regis Houssin <regis.houssin@inodbox.com> Regis Houssin <regis@dolibarr.fr>
|
||||
Regis Houssin <regis.houssin@inodbox.com> Régis Houssin <regishoussin@device5.home>
|
||||
Juanjo Menent <jmenent@2byte.es> simnandez <jmenent@2byte.es>
|
||||
|
|
@ -18,12 +20,15 @@ Juanjo Menent <jmenent@2byte.es> juanjo <juanjo@samsung>
|
|||
Juanjo Menent <jmenent@2byte.es> juanjo <juanjo@alienware>
|
||||
Marcos García de La Fuente <marcosgdf@gmail.com> Marcos García <marcosgdf@gmail.com>
|
||||
Marcos García de La Fuente <marcosgdf@gmail.com> Marcos García <marcosgdf@gmail.com>
|
||||
Mohamed DAOUD <mdaoud@dolicloud.com> Mohamed DAOUD <daoud.mouhamed@gmail.com>
|
||||
Mohamed DAOUD <mdaoud@dolicloud.com> Mohamed DAOUD <mdaoud@dolicloud.com>
|
||||
Florian Henry <florian.henry@open-concept.pro> fhenry <florian.henry@open-concept.pro>
|
||||
Florian Henry <florian.henry@open-concept.pro> Florian HENRY <florian.henry@open-concept.pro>
|
||||
Florian Henry <florian.henry@open-concept.pro> FHenry <florian.henry.mail@gmail.com>
|
||||
Florian Henry <florian.henry@open-concept.pro> Florian HENRY <florian.henry@open-conept.pro>
|
||||
Florian Henry <florian.henry@open-concept.pro> FHenry <florian.henry@open-concept.pro>
|
||||
Florian Henry <florian.henry@open-concept.pro> HENRY Florian <florian.henry@open-concept.pro>
|
||||
Lucas Marcouiller <lmarcouiller@dolicloud.com> Hystepik <lmarcouiller@dolicloud.com>
|
||||
Alexandre Spangaro <aspangaro@open-dsi.fr> aspangaro <aspangaro@open-dsi.fr>
|
||||
Alexandre Spangaro <aspangaro@open-dsi.fr> Spangaro Alexandre <aspangaro@open-dsi.fr>
|
||||
Alexandre Spangaro <aspangaro@open-dsi.fr> Alexandre SPANGARO <aspangaro@open-dsi.fr>
|
||||
|
|
|
|||
|
|
@ -159,7 +159,6 @@ NEW: Add mass action to cancel invoices using credit notes (#37852)
|
|||
NEW: Add personal_data flag in extrafields admin UI - next step of #8612 (#38133)
|
||||
NEW: Direct installation for community and free modules on DoliStore (#38357)
|
||||
NEW: Display thirdparty name with ref in supplier orders linked objects (#36952)
|
||||
NEW: Show bom net needs treeview by line position. (#37459)
|
||||
NEW: Show name_alias in parentheses in thirdparty dropdown lists (#37997)
|
||||
NEW: Thirdparty card +tab with events where thirdparty is attendee/booth (#37743)
|
||||
NEW: Update ticket read date when status changes (#37470)
|
||||
|
|
@ -178,7 +177,6 @@ For developers:
|
|||
NEW: Use another hash algorithm v2 based on sha256/hmac for immutable logs (#37725)
|
||||
NEW: Replace MyObject MyModule occurrences (#38370)
|
||||
NEW: ModuleBuilder - Allow selecting which optional tabs (contact, note, document, agenda) are generated for an object (#38570)
|
||||
FIX: ModuleBuilder - Generated list page derives the email trackid from the object name instead of the leftover 'xxxx' placeholder (#32460)
|
||||
NEW: add hooks in reception card (#37214)
|
||||
NEW: add new hook in BonPrelevement::EnregDestinataireSEPA() function (#37419)
|
||||
NEW: Add hook selectForFormsListUrl in Form::selectForForms (#37447)
|
||||
|
|
@ -243,6 +241,7 @@ FIX: missing "blob:" in the assistant for CSP editor.
|
|||
FIX: option MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE
|
||||
FIX: product price.php: preserve default_vat_code and tva_npr when auto-creating initial product_price row (#38034)
|
||||
FIX: propagate fk_warehouse from BOM/MO to production lines in createProduction() and processBOM() (#38147)
|
||||
FIX: #39068 Product search combo: ignore supplier price warning text when filtering
|
||||
FIX: selected default value ko on select_produits_fournisseurs_list()
|
||||
FIX: Set default warehouse on order create. (#37815)
|
||||
FIX: Site root missing in $backtopage. (#37804)
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ while ($i < $argc) {
|
|||
$includeconstants[$tmp[0]][$tmp[1]] = $tmp[2];
|
||||
}
|
||||
if (!empty($result["buildzip"])) {
|
||||
$buildzip = 1;
|
||||
$buildzip = $result["buildzip"];
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ $savrelease = $release;
|
|||
$tmpver = explode('-', $release, 2);
|
||||
if ($tmpver[0] == 'auto') {
|
||||
$release = DOL_VERSION;
|
||||
if (!empty($tmpver[1]) && $tmpver[0] == 'auto') {
|
||||
if (!empty($tmpver[1])) {
|
||||
$release .= '-'.$tmpver[1];
|
||||
}
|
||||
}
|
||||
|
|
@ -419,12 +419,12 @@ foreach ($arrayofunalterablefiles as $entry) {
|
|||
exit(1);
|
||||
}
|
||||
if ($newdir != $dir) {
|
||||
if ($needtoclose) {
|
||||
if ($release) {
|
||||
fputs($fp, ' </dir>'."\n");
|
||||
}
|
||||
$needtoclose = 0;
|
||||
//if ($needtoclose) {
|
||||
if ($release) {
|
||||
fputs($fp, ' </dir>'."\n");
|
||||
}
|
||||
$needtoclose = 0;
|
||||
//}
|
||||
if ($release) {
|
||||
fputs($fp, ' <dir name="'.$newdir.'">'."\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,6 +230,8 @@ if (preg_match("/define\('DOL_VERSION',\s*'([\d\.a-z\-]+)'\)/i", $filefuncConten
|
|||
$PROJVERSION = $matches[1];
|
||||
}
|
||||
if (empty($PROJVERSION)) {
|
||||
$DOL_MAJOR_VERSION = 'notfound';
|
||||
$DOL_MINOR_VERSION = 'notfound';
|
||||
if (preg_match("/define\('DOL_MAJOR_VERSION',\s*'([\d\.a-z\-]+)'\)/i", $filefuncContent, $matches)) {
|
||||
$DOL_MAJOR_VERSION = $matches[1];
|
||||
}
|
||||
|
|
@ -269,7 +271,7 @@ if (strpos($newbuild, '-') === false) {
|
|||
$newbuild .= '-0.4'; // finale (fedora)
|
||||
}
|
||||
$REL1 = preg_replace('/-.*$/', '', $newbuild);
|
||||
if ($RPMSUBVERSION === 'auto') {
|
||||
if ($RPMSUBVERSION === 'auto') { // @phpstan-ignore-line
|
||||
$RPMSUBVERSION = preg_replace('/^.*-/', '', $newbuild);
|
||||
}
|
||||
$FILENAMETGZ2 = "$PROJECT-$MAJOR.$MINOR.$REL1";
|
||||
|
|
@ -314,10 +316,10 @@ for ($i = 1; $i < $argc; $i++) {
|
|||
}
|
||||
|
||||
// Force output dir if env vars are defined
|
||||
if ($ENVDESTIBETARC && preg_match('/[a-z]/i', $BUILD)) {
|
||||
if ($ENVDESTIBETARC && preg_match('/[a-z]/i', $BUILD)) { // @phpstan-ignore-line
|
||||
$DESTI = $ENVDESTIBETARC;
|
||||
}
|
||||
if ($ENVDESTISTABLE && preg_match('/^[0-9]+$/', $BUILD)) {
|
||||
if ($ENVDESTISTABLE && preg_match('/^[0-9]+$/', $BUILD)) { // @phpstan-ignore-line
|
||||
$DESTI = $ENVDESTISTABLE;
|
||||
}
|
||||
|
||||
|
|
@ -349,12 +351,12 @@ if ($target) {
|
|||
$targetUpper = strtoupper($target);
|
||||
if ($targetUpper === 'ALL') {
|
||||
foreach ($LISTETARGET as $key) {
|
||||
if ($key !== 'SNAPSHOT' && $key !== 'SF' && $key !== 'ASSO') {
|
||||
if ($key !== 'SNAPSHOT' && $key !== 'SF' && $key !== 'ASSO') { // @phpstan-ignore-line
|
||||
$CHOOSEDTARGET[$key] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($targetUpper !== 'ALL' && $targetUpper !== 'SF' && $targetUpper !== 'ASSO') {
|
||||
if ($targetUpper !== 'ALL' && $targetUpper !== 'SF' && $targetUpper !== 'ASSO') { // @phpstan-ignore-line
|
||||
$CHOOSEDTARGET[$targetUpper] = 1;
|
||||
}
|
||||
if ($targetUpper === 'SF') {
|
||||
|
|
@ -399,7 +401,7 @@ if ($target) {
|
|||
} elseif ($NUM_SCRIPT === '0') {
|
||||
$CHOOSEDTARGET['-CHKSUM'] = 1;
|
||||
foreach ($LISTETARGET as $key) {
|
||||
if ($key !== 'SNAPSHOT' && $key !== 'ASSO' && $key !== 'SF') {
|
||||
if ($key !== 'SNAPSHOT' && $key !== 'ASSO' && $key !== 'SF') { // @phpstan-ignore-line
|
||||
$CHOOSEDTARGET[$key] = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +497,7 @@ foreach ($CHOOSEDTARGET as $tgt => $val) {
|
|||
|
||||
ksort($CHOOSEDPUBLISH);
|
||||
foreach ($CHOOSEDPUBLISH as $tgt => $val) {
|
||||
if ($val < 0) { continue; }
|
||||
if ($val < 0) { continue; } // @phpstan-ignore-line
|
||||
if ($tgt === 'ASSO') { $nbofpublishneedchangelog++; }
|
||||
if ($tgt === 'SF') { $nbofpublishneedchangelog++; $nbofpublishneedtag++; }
|
||||
$nboftargetok++;
|
||||
|
|
@ -621,7 +623,7 @@ if ($nboftargetok) {
|
|||
// ========================================================================
|
||||
|
||||
if ($nboftargetneedbuildroot) {
|
||||
if (!$copyalreadydone) {
|
||||
if (!$copyalreadydone) { // @phpstan-ignore-line
|
||||
echo "Creation of a buildroot used for all packages\n";
|
||||
|
||||
echo "Delete directory $BUILDROOT\n";
|
||||
|
|
@ -1297,7 +1299,7 @@ if ($nboftargetok) {
|
|||
|
||||
ksort($CHOOSEDPUBLISH);
|
||||
foreach ($CHOOSEDPUBLISH as $tgt => $val) {
|
||||
if ($val < 0) { continue; }
|
||||
if ($val < 0) { continue; } // @phpstan-ignore-line
|
||||
|
||||
echo "\nList of files to publish (BUILD=$BUILD)\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ Prerequisites to build autoexe DoliWamp package from Windows:
|
|||
```
|
||||
|
||||
|
||||
## Actions to do a BETA
|
||||
## Actions to do a FREEZE / BETA
|
||||
|
||||
This section describes steps made by Dolibarr packaging team to make a beta version of Dolibarr, step by step.
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ git log x.y.z-1.. --no-merges --pretty=short --oneline | sed -e "s/^[0-9a-z]* //
|
|||
|
||||
- Recopy the content of the output file into the file ChangeLog.
|
||||
|
||||
Note: To know number of lines changes: git diff --shortstat A B
|
||||
Note: To know number of changed lines: git diff --shortstat A B
|
||||
|
||||
- Update version number with x.y.z-w in file htdocs/filefunc.inc.php
|
||||
|
||||
|
|
|
|||
|
|
@ -1230,12 +1230,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/comm/action/index.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#16 \$usergroupid of function print_actions_filter expects array\<int\>\|int, string given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: ../../../htdocs/comm/action/index.php
|
||||
|
||||
-
|
||||
message: '#^Ternary operator condition is always true\.$#'
|
||||
identifier: ternary.alwaysTrue
|
||||
|
|
@ -3216,12 +3210,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/core/class/openid.class.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$content of method SimpleOpenID\:\:HTML2OpenIDServer\(\) expects string, array\<string, int\|string\> given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: ../../../htdocs/core/class/openid.class.php
|
||||
|
||||
-
|
||||
message: '#^Call to function is_object\(\) with XMLParser will always evaluate to true\.$#'
|
||||
identifier: function.alreadyNarrowedType
|
||||
|
|
@ -5088,12 +5076,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/fourn/paiement/card.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$object might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 2
|
||||
path: ../../../htdocs/fourn/paiement/document.php
|
||||
|
||||
-
|
||||
message: '#^Ternary operator condition is always false\.$#'
|
||||
identifier: ternary.alwaysFalse
|
||||
|
|
@ -5640,12 +5622,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/loan/class/loanschedule.class.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$object might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/loan/payment/card.php
|
||||
|
||||
-
|
||||
message: '#^Negated boolean expression is always true\.$#'
|
||||
identifier: booleanNot.alwaysTrue
|
||||
|
|
@ -6222,12 +6198,6 @@ parameters:
|
|||
count: 4
|
||||
path: ../../../htdocs/multicurrency/multicurrency_rate.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$id might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/opensurvey/card.php
|
||||
|
||||
-
|
||||
message: '#^Left side of && is always true\.$#'
|
||||
identifier: booleanAnd.leftAlwaysTrue
|
||||
|
|
@ -6252,12 +6222,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/opensurvey/results.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$expiredate might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/opensurvey/results.php
|
||||
|
||||
-
|
||||
message: '#^Left side of && is always false\.$#'
|
||||
identifier: booleanAnd.leftAlwaysFalse
|
||||
|
|
@ -6378,12 +6342,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/paypal/lib/paypal.lib.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#3 \$value of function curl_setopt expects 0\|2, bool given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: ../../../htdocs/paypal/lib/paypal.lib.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#3 \$value of function curl_setopt expects bool, int given\.$#'
|
||||
identifier: argument.type
|
||||
|
|
@ -6798,12 +6756,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/product/stock/stocktransfer/stocktransfer_card.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$result might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/product/stock/stocktransfer/stocktransfer_contact.php
|
||||
|
||||
-
|
||||
message: '#^Right side of && is always true\.$#'
|
||||
identifier: booleanAnd.rightAlwaysTrue
|
||||
|
|
@ -6894,12 +6846,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/projet/card.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$morecss might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/projet/card.php
|
||||
|
||||
-
|
||||
message: '#^Call to function method_exists\(\) with \$this\(Project\) and ''getLibStatut'' will always evaluate to true\.$#'
|
||||
identifier: function.alreadyNarrowedType
|
||||
|
|
@ -7476,18 +7422,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/public/onlinesign/newonlinesign.php
|
||||
|
||||
-
|
||||
message: '#^Result of && is always false\.$#'
|
||||
identifier: booleanAnd.alwaysFalse
|
||||
count: 1
|
||||
path: ../../../htdocs/public/onlinesign/newonlinesign.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$mesg might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 2
|
||||
path: ../../../htdocs/public/onlinesign/newonlinesign.php
|
||||
|
||||
-
|
||||
message: '#^Left side of && is always true\.$#'
|
||||
identifier: booleanAnd.leftAlwaysTrue
|
||||
|
|
@ -7944,12 +7878,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/reception/card.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$reception might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/reception/card.php
|
||||
|
||||
-
|
||||
message: '#^Call to function method_exists\(\) with \$this\(Reception\) and ''getLibStatut'' will always evaluate to true\.$#'
|
||||
identifier: function.alreadyNarrowedType
|
||||
|
|
@ -8238,24 +8166,6 @@ parameters:
|
|||
count: 1
|
||||
path: ../../../htdocs/societe/canvas/company/tpl/card_view.tpl.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$objcanvas might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/societe/canvas/company/tpl/card_view.tpl.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$objcanvas might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 1
|
||||
path: ../../../htdocs/societe/canvas/individual/tpl/card_view.tpl.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$socid might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
count: 3
|
||||
path: ../../../htdocs/societe/canvas/individual/tpl/card_view.tpl.php
|
||||
|
||||
-
|
||||
message: '#^Call to function is_numeric\(\) with 0\|1\|2\|3\|4\|5\|6\|7\|8\|9 will always evaluate to true\.$#'
|
||||
identifier: function.alreadyNarrowedType
|
||||
|
|
|
|||
|
|
@ -467,3 +467,13 @@ Edit CSS to restore line removed between 4.0.5 and 4.0.6. It generates this bug:
|
|||
JS JCROP:
|
||||
----------
|
||||
* Remove analytics tag into file index.html
|
||||
|
||||
|
||||
PHP MIKE42 ESCPOS:
|
||||
------------------
|
||||
* In htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/GdEscposImage.php
|
||||
Replace:
|
||||
if (!is_resource($im)) {
|
||||
With:
|
||||
if (!($im instanceof \GdImage) && !is_resource($im)) {
|
||||
PHP 8.0+ returns GdImage objects from imagecreate*; the upstream guard with is_resource() alone fails on PHP 8 and throws 'Failed to load image' on receipts that contain an image.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
/* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -25,7 +26,7 @@ use PHP_CodeSniffer\Files\File;
|
|||
*/
|
||||
class CheckIsModEnabledArgumentSniff implements Sniff
|
||||
{
|
||||
// Nom de la fonction cible
|
||||
// Target function name
|
||||
protected $targetFunction = 'ismodenabled';
|
||||
|
||||
protected $deprecatedModulesNames = [
|
||||
|
|
@ -87,7 +88,7 @@ class CheckIsModEnabledArgumentSniff implements Sniff
|
|||
return;
|
||||
}
|
||||
|
||||
// check value of argument
|
||||
// Check argument value
|
||||
$argContent = str_replace(["'", '"'], '', $tokens[$firstArgTokenPtr]['content']);
|
||||
$argCode = $tokens[$firstArgTokenPtr]['code'];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
/* Copyright (C) 2025-2026 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace codesniffer\Sniffs\Dolibarr;
|
||||
|
||||
use PHP_CodeSniffer\Sniffs\Sniff;
|
||||
|
|
@ -108,7 +110,14 @@ class LanguageOfCommentsSniff implements Sniff
|
|||
return;
|
||||
}
|
||||
|
||||
if (strpos($content, 'Copyright') === false && preg_match('/[àâäéèêëîïôùûüçœÀÂÄÉÈÊËÎÏÔÙÛÜÇŒ]/u', $content)) {
|
||||
// Avoid matching special characters directly preceded or followed with []'"
|
||||
// Avoid matching special characters in a "word/identifier" like string with '_'.
|
||||
// Implementation:
|
||||
// - Start with word (\b);
|
||||
// - Require that this word does not contain '_'
|
||||
// - Match all word characters up to the accented character.
|
||||
// - Require that the character is not preceded or following by specific delimieters
|
||||
if (strpos($content, 'Copyright') === false && preg_match('/\b(?![\p{L}_]*_[\p{L}_]*\b)([\p{L}_]*)(?<![<>\/\'"\[])[àâäéèêëîïôùûüçœÀÂÄÉÈÊËÎÏÔÙÛÜÇŒ]+(?![\'"\[]\/)(?![<>\/\'"\[])/u', $content)) {
|
||||
$error = "The comment appears to be in French (accent detected in: '%s'). Please write in English.";
|
||||
$data = [trim($content)];
|
||||
$phpcsFile->addWarning($error, $stackPtr, 'FrenchDetected', $data);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
$objMod->dictionaries = $objMod->{"dictionnaries"}; // For backward compatibility
|
||||
if (empty($objMod->dictionaries) && !empty($objMod->{"dictionnaries"})) {
|
||||
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&id_entrepot='.$entrepotstatic->id.'&action=transfert&pdluoid='.$pdluo->id.'&token='.newToken().'">';
|
||||
$dateemail = dol_stringtotime((string) $overview[0]->udate, 'gmt');
|
||||
$reponsesadd = str_split($obj->reponses);
|
||||
$sql .= " SET reponses = '".$db->escape($reponsesadd)."'";
|
||||
$sql .= " SET reponses = '0".$db->escape($obj->reponses)."'";
|
||||
$tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.od(s|t)$', '', 'name', SORT_ASC, 0);
|
||||
dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
|
||||
print '<td class="center"><a href="'.DOL_URL_ROOT.'/product/stock/product.php?dwid='.$object->id.'&id='.$objp->rowid.'&action=transfert&token='.newToken().'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$id).'">';
|
||||
$dateemail = dol_stringtotime((string) $overview[0]->udate, 'gmt');
|
||||
$pice = '<i class="fas fa-briefcase inline-block"></i>';
|
||||
$typea = ($data[$j]->typea == 'birth') ? $picb : $pice;
|
||||
GETPOSTINT("mouvement"),
|
||||
dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
|
||||
jQuery("#mouvement option").removeAttr("selected").change();
|
||||
jQuery("#mouvement option[value=0]").attr("selected","selected").trigger("change");
|
||||
jQuery("#mouvement option[value=1]").attr("selected","selected").trigger("change");
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
$sql2 .= " SET reponses = '".$db->escape($newcar)."'";
|
||||
$this->category->childs = array();
|
||||
$tmpcrit = preg_replace('/^.*(:[!<>=\s]+:|:in:|:notin:|:like:|:notlike:)/', '\1', $tmpcrit); // the condition after the name of the field
|
||||
$user->rights->accounting->mouvements = new stdClass();
|
||||
// mise a jour des reponses utilisateurs dans la base
|
||||
if ($user->hasRight('stock', 'mouvement', 'lire')) {
|
||||
if (empty($reyear) || empty($remonth) || empty($reday)) {
|
||||
|
|
@ -66,6 +67,7 @@
|
|||
$head[$tab][1] = $langs->trans("Referers");
|
||||
$out .= "<b>".$langs->trans("Referer").":</b> ".(isset($_SERVER["HTTP_REFERER"]) ? dol_htmlentities($_SERVER["HTTP_REFERER"], ENT_COMPAT) : '')."<br>\n";
|
||||
$reday = GETPOSTINT('reday');
|
||||
$savpermexport = $user->hasRight('accounting', 'mouvements', 'export');
|
||||
$sql .= " (cs.periode IS NOT NULL AND cs.periode between '".$db->idate(dol_get_first_day($year))."' AND '".$db->idate(dol_get_last_day($year))."')";
|
||||
$sql .= " OR (cs.periode IS NULL AND cs.date_ech between '".$db->idate(dol_get_first_day($year))."' AND '".$db->idate(dol_get_last_day($year))."')";
|
||||
$sql .= ", cs.libelle as label, cs.fk_type, cs.amount, cs.fk_projet as fk_project, cs.paye, cs.periode as period, cs.import_key";
|
||||
|
|
@ -78,10 +80,14 @@
|
|||
$this->periode = $this->date_creation + 3600 * 24 * 30;
|
||||
$title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Referers');
|
||||
$title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Referers');
|
||||
$user->rights->accounting->mouvements->export = $savpermexport;
|
||||
$user->rights->accounting->mouvements->export = 0;
|
||||
$user->rights->accounting->mouvements->export = 1;
|
||||
if (!empty($arrayfields['cs.periode']['checked'])) {
|
||||
if ($newamount == 0 || empty($this->date_ech) || (empty($this->period) && empty($this->periode))) {
|
||||
if ($user->hasRight('stock', 'mouvement', 'creer')) {
|
||||
if (GETPOSTISSET("reday") && GETPOSTISSET("remonth") && GETPOSTISSET("reyear")) {
|
||||
if (empty($user->rights->accounting->mouvements)) {
|
||||
* @param float|string $selectedrate Force preselected vat rate. Can be '8.5' or '8.5 (NOO)' for example. Use '' for no forcing.
|
||||
$datepaid = dol_mktime(12, 0, 0, GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
|
||||
$datepaye = dol_mktime(12, 0, 0, GETPOSTINT("remonth"), GETPOSTINT("reday"), GETPOSTINT("reyear"));
|
||||
|
|
@ -179,3 +185,5 @@ print $langs->trans("Developpers").':';
|
|||
print_liste_field_titre("PeriodEndDate", $_SERVER["PHP_SELF"], "cs.periode", "", $param, '', $sortfield, $sortorder, 'center ');
|
||||
select#date_startday, select#date_startmonth, select#date_endday, select#date_endmonth, select#reday, select#remonth
|
||||
select#date_startday, select#date_startmonth, select#date_endday, select#date_endmonth, select#reday, select#remonth,
|
||||
if (empty($user->rights->accounting->mouvements)) {
|
||||
$user->rights->accounting->mouvements = new stdClass();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ return [
|
|||
// # Issue statistics:
|
||||
// PhanUndeclaredProperty : 370+ occurrences
|
||||
// PhanTypeMismatchArgument : 25+ occurrences
|
||||
// PhanUndeclaredGlobalVariable : 25+ occurrences
|
||||
// PhanUndeclaredGlobalVariable : 20+ occurrences
|
||||
// PhanTypeMismatchProperty : 15+ occurrences
|
||||
// PhanTypeInvalidDimOffset : 10+ occurrences
|
||||
// PhanTypeMismatchDimFetch : 10+ occurrences
|
||||
|
|
@ -103,7 +103,6 @@ return [
|
|||
'htdocs/core/tpl/objectline_view.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/core/tpl/passwordreset.tpl.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
'htdocs/core/tpl/resource_view.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/core/triggers/interface_99_modAgenda_ActionsAuto.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/delivery/class/delivery.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/emailcollector/class/emailcollector.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/eventorganization/class/conferenceorboothattendee.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'],
|
||||
|
|
@ -139,7 +138,6 @@ return [
|
|||
'htdocs/loan/payment/payment.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/mrp/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/multicurrency/class/multicurrency.class.php' => ['PhanTypeExpectedObjectPropAccess'],
|
||||
'htdocs/opensurvey/results.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
'htdocs/partnership/class/partnership.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/partnership/core/modules/partnership/mod_partnership_advanced.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/partnership/partnership_card.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
|
|
@ -161,7 +159,6 @@ return [
|
|||
'htdocs/product/stock/stocktransfer/class/stocktransferline.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/product/stock/tpl/stockcorrection.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/projet/admin/project.php' => ['PhanTypeMismatchArgumentProbablyReal'],
|
||||
'htdocs/projet/card.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
'htdocs/projet/tasks.php' => ['PhanTypeMismatchArgument'],
|
||||
'htdocs/projet/tasks/time.php' => ['PhanTypeInvalidDimOffset', 'PhanUndeclaredProperty'],
|
||||
'htdocs/projet/tasks/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
|
|
@ -171,7 +168,7 @@ return [
|
|||
'htdocs/public/project/viewandvote.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
'htdocs/public/recruitment/view.php' => ['PhanUndeclaredGlobalVariable'],
|
||||
'htdocs/public/webportal/tpl/menu.tpl.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/reception/card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
|
||||
'htdocs/reception/card.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/reception/class/reception.class.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/reception/list.php' => ['PhanUndeclaredProperty'],
|
||||
'htdocs/recruitment/class/recruitmentcandidature.class.php' => ['PhanUndeclaredProperty'],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*/
|
||||
|
||||
namespace Dolibarr\Rector\Renaming;
|
||||
|
||||
|
|
@ -230,7 +232,7 @@ class GlobalToFunction extends AbstractRector
|
|||
|
||||
// If a && b and a or b is conf->global, we replace a or/and b
|
||||
if ($node instanceof BooleanAnd) {
|
||||
// Transformation sur le nœud gauche
|
||||
// Transformation on the left node
|
||||
$changedone = 0;
|
||||
if ($this->isGlobalVar($node->left)) {
|
||||
$constName = $this->getConstName($node->left);
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ if ($useNewSystem) {
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
|
||||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = aca.fk_accounting_account";
|
||||
$sql .= " WHERE aca.fk_accounting_category = ".((int) $id);
|
||||
$sql .= " AND aa.entity = ".$conf->entity;
|
||||
$sql .= " AND aa.entity = ".((int) $conf->entity);
|
||||
|
||||
// Search filters
|
||||
if (!empty($search_account)) {
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
|||
|
||||
// List of values
|
||||
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
|
||||
$sql .= $newid.",";
|
||||
$sql .= ((int) $newid).",";
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
|||
|
||||
// List of values
|
||||
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
|
||||
$sql .= $newid.",";
|
||||
$sql .= ((int) $newid).",";
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
|
|
@ -239,7 +239,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
|||
}
|
||||
$i++;
|
||||
}
|
||||
$sql .= ",1,".$conf->entity.")";
|
||||
$sql .= ",1,".((int) $conf->entity).")";
|
||||
|
||||
dol_syslog("actionadd", LOG_DEBUG);
|
||||
$result = $db->query($sql);
|
||||
|
|
@ -326,7 +326,7 @@ if ($action == $acts[0]) {
|
|||
} elseif ($code) {
|
||||
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE code = '".$db->escape($code)."'";
|
||||
}
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$result = $db->query($sql);
|
||||
if (!$result) {
|
||||
|
|
@ -348,7 +348,7 @@ if ($action == $acts[1]) {
|
|||
} elseif ($code) {
|
||||
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE code='".$db->escape($code)."'";
|
||||
}
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$result = $db->query($sql);
|
||||
if (!$result) {
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
|
|||
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $db->sanitize($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 .= " 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))) {
|
||||
|
|
@ -483,13 +483,12 @@ if ($resql) {
|
|||
|
||||
print load_fiche_titre($langs->trans("ProductsBinding"), '', 'title_accountancy');
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("InitAccountancyDesc").'</span><br>';
|
||||
print '<br>';
|
||||
print '<div class="info">'.$langs->trans("InitAccountancyDesc").'</div><br>';
|
||||
|
||||
// Select usage
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<td>'.$langs->trans('ProductUsage').'</td><td></td>';
|
||||
print '<td>'.$langs->trans('AccountancyCodeToSet').'...</td><td></td>';
|
||||
print "</tr>\n";
|
||||
print '<tr class="oddeven"><td><input type="radio" id="accounting_product_mode1" name="accounting_product_mode" value="ACCOUNTANCY_SELL"'.($accounting_product_mode == 'ACCOUNTANCY_SELL' ? ' checked' : '').'> <label for="accounting_product_mode1">'.$langs->trans('OptionModeProductSell').'</label></td>';
|
||||
print '<td>'.$langs->trans('OptionModeProductSellDesc');
|
||||
|
|
@ -619,7 +618,7 @@ if ($resql) {
|
|||
print '<td class="liste_titre">';
|
||||
print '<input type="text" class="flat" size="6" name="search_current_account" id="search_current_account" value="'.dol_escape_htmltag($search_current_account).'">';
|
||||
$listofvals = array('withoutvalidaccount' => $langs->trans("WithoutValidAccount"), 'withvalidaccount' => $langs->trans("WithValidAccount"));
|
||||
print ' '.$langs->trans("or").' '.$form->selectarray('search_current_account_valid', $listofvals, $search_current_account_valid, 1);
|
||||
print ' <span class="opacitymedium">'.$langs->trans("or").'</span> '.$form->selectarray('search_current_account_valid', $listofvals, $search_current_account_valid, 1);
|
||||
print '</td>';
|
||||
print '<td class="liste_titre"> </td>';
|
||||
// Action column
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
|||
|
||||
// List of values
|
||||
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
|
||||
$sql .= $newid.",";
|
||||
$sql .= ((int) $newid).",";
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2016 Florian Henry <florian.henry@open-concept.pro>
|
||||
* Copyright (C) 2016-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -102,7 +102,7 @@ $form = new Form($db);
|
|||
|
||||
if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('formfilteraction')) {
|
||||
$sql = "SELECT date_start, date_end";
|
||||
$sql .=" FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
|
||||
if (getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT')) {
|
||||
$sql .= " WHERE rowid = " . getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT');
|
||||
} else {
|
||||
|
|
@ -375,7 +375,7 @@ if ($action != 'export') {
|
|||
$newcardbutton .= dolGetButtonTitle($langs->trans('ExportToPdf'), '', 'fa fa-file-pdf paddingleft', $_SERVER['PHP_SELF'] . '&token=' . newToken(), 'exportpdfbutton', $permissiontoexport, array('morecss' => 'marginleftonly'));
|
||||
|
||||
$newcardbutton .= dolGetButtonTitleSeparator();
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'.(!empty($type)?'&type=sub':'').'&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'.(!empty($type) ? '&type=sub' : '').'&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
|
||||
}
|
||||
if ($contextpage != $_SERVER["PHP_SELF"]) {
|
||||
$param .= '&contextpage='.urlencode($contextpage);
|
||||
|
|
@ -515,7 +515,7 @@ if ($action != 'export') {
|
|||
if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
|
||||
$sql = "SELECT t.numero_compte, (SUM(t.debit) - SUM(t.credit)) as opening_balance";
|
||||
$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
|
||||
$sql .= " WHERE t.entity = " . $conf->entity; // Never do sharing into accounting features
|
||||
$sql .= " WHERE t.entity = " . ((int) $conf->entity); // Never do sharing into accounting features
|
||||
$sql .= " AND t.doc_date < '" . $db->idate($search_date_start) . "'";
|
||||
$sql .= " GROUP BY t.numero_compte";
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ $hookmanager->initHooks(array('bookkeepingexport'));
|
|||
$formaccounting = new FormAccounting($db);
|
||||
$form = new Form($db);
|
||||
|
||||
if (!in_array($action, array('export_file', 'delmouv', 'delmouvconfirm')) && !GETPOSTISSET('begin') && !GETPOSTISSET('formfilteraction') && GETPOSTINT('page') == 0 && !GETPOSTINT('noreset') && $user->hasRight('accounting', 'mouvements', 'export')) {
|
||||
if (!in_array($action, array('export_file', 'export_fileconfirm', 'delmouv', 'delmouvconfirm')) && !GETPOSTISSET('begin') && !GETPOSTISSET('formfilteraction') && GETPOSTINT('page') == 0 && !GETPOSTINT('noreset') && $user->hasRight('accounting', 'mouvements', 'export')) {
|
||||
if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('restore_lastsearch_values') && !GETPOST('search_accountancy_code_start')) {
|
||||
$sql = "SELECT date_start, date_end";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
|
||||
|
|
@ -680,10 +680,10 @@ if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements
|
|||
$now = dol_now();
|
||||
|
||||
$sanitizedsetfields = '';
|
||||
if (!empty($notifiedexportdate) && empty($movement->date_export)) {
|
||||
if (!empty($notifiedexportdate) && (empty($movement->date_export) || getDolGlobalString('ACCOUNTING_REEXPORT'))) {
|
||||
$sanitizedsetfields .= ($sanitizedsetfields ? "," : "")." date_export = '".$db->idate($now)."'";
|
||||
}
|
||||
if (!empty($notifiedvalidationdate) && empty($movement->date_validation)) {
|
||||
if (!empty($notifiedvalidationdate) && (empty($movement->date_validation) || getDolGlobalString('ACCOUNTING_REEXPORT'))) {
|
||||
$sanitizedsetfields .= ($sanitizedsetfields ? "," : "")." date_validated = '".$db->idate($now)."'";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " FROM ".$this->db->prefix()."accounting_account as t";
|
||||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON t.fk_pcg_version = asy.pcg_version AND asy.rowid = ".((int) $pcgver);
|
||||
$sql .= " WHERE t.fk_accounting_category = ".((int) $id);
|
||||
$sql .= " AND t.entity = ".$conf->entity;
|
||||
$sql .= " AND t.entity = ".((int) $conf->entity);
|
||||
|
||||
$this->lines_display = array();
|
||||
|
||||
|
|
@ -483,7 +483,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " WHERE (aa.fk_accounting_category <> ".((int) $id)." OR aa.fk_accounting_category IS NULL)";
|
||||
$sql .= " AND asy.rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
|
||||
$sql .= " AND aa.active = 1";
|
||||
$sql .= " AND aa.entity = ".$conf->entity;
|
||||
$sql .= " AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " GROUP BY aa.account_number, aa.label";
|
||||
$sql .= " ORDER BY aa.account_number, aa.label";
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " INNER JOIN ".$this->db->prefix()."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
|
||||
$sql .= " AND asy.rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
|
||||
$sql .= " AND aa.active = 1";
|
||||
$sql .= " AND aa.entity = ".$conf->entity;
|
||||
$sql .= " AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " ORDER BY LENGTH(aa.account_number) DESC;"; // LENGTH is ok with mysql and postgresql
|
||||
|
||||
$this->db->begin();
|
||||
|
|
@ -623,7 +623,7 @@ class AccountancyCategory // extends CommonObject
|
|||
/**
|
||||
* Function to set the property ->sdc (and ->sdcperaccount) that is the result of an accounting account from the ledger with a direction and a period
|
||||
*
|
||||
* @param int|array<?string> $cpt Accounting account or array of accounting account
|
||||
* @param string|int|array<?string> $cpt Accounting account or array of accounting account
|
||||
* @param int $date_start Date start
|
||||
* @param int $date_end Date end
|
||||
* @param int<0,1> $sens Sens of the account: 0: credit - debit (use this by default), 1: debit - credit
|
||||
|
|
@ -734,10 +734,10 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " WHERE t.fk_accounting_category IN (SELECT c.rowid";
|
||||
$sql .= " FROM ".$this->db->prefix().$this->table_element." as c";
|
||||
$sql .= " WHERE c.active = 1";
|
||||
$sql .= " AND c.entity = ".$conf->entity;
|
||||
$sql .= " AND c.entity = ".((int) $conf->entity);
|
||||
$sql .= " AND (c.fk_country = ".((int) $mysoc->country_id)." OR c.fk_country = 0)";
|
||||
$sql .= " AND cat.rowid = t.fk_accounting_category";
|
||||
$sql .= " AND t.entity = ".$conf->entity;
|
||||
$sql .= " AND t.entity = ".((int) $conf->entity);
|
||||
if ($catid > 0) {
|
||||
$sql .= " AND cat.rowid = ".((int) $catid);
|
||||
}
|
||||
|
|
@ -796,7 +796,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " FROM ".$this->db->prefix().$this->table_element." as c";
|
||||
$sql .= " WHERE c.active = " . (int) $active;
|
||||
$sql .= " AND c.fk_report=".((int) $id_report);
|
||||
$sql .= " AND c.entity = ".$conf->entity;
|
||||
$sql .= " AND c.entity = ".((int) $conf->entity);
|
||||
if ($categorytype >= 0) {
|
||||
$sql .= " AND c.category_type = 1";
|
||||
}
|
||||
|
|
@ -868,7 +868,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql = "SELECT t.rowid, t.account_number, t.label as account_label";
|
||||
$sql .= " FROM ".$this->db->prefix()."accounting_account as t";
|
||||
$sql .= " WHERE t.fk_accounting_category = ".((int) $cat_id);
|
||||
$sql .= " AND t.entity = ".$conf->entity;
|
||||
$sql .= " AND t.entity = ".((int) $conf->entity);
|
||||
$sql .= " AND t.active = 1";
|
||||
$sql .= " AND t.fk_pcg_version = '".$this->db->escape($pcgvercode)."'";
|
||||
$sql .= " ORDER BY t.account_number";
|
||||
|
|
@ -876,7 +876,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql = "SELECT t.rowid, t.account_number, t.label as account_label";
|
||||
$sql .= " FROM ".$this->db->prefix()."accounting_account as t";
|
||||
$sql .= " WHERE ".$sanitizedpredefinedgroupwhere;
|
||||
$sql .= " AND t.entity = ".$conf->entity;
|
||||
$sql .= " AND t.entity = ".((int) $conf->entity);
|
||||
$sql .= ' AND t.active = 1';
|
||||
$sql .= " AND t.fk_pcg_version = '".$this->db->escape($pcgvercode)."'";
|
||||
$sql .= " ORDER BY t.account_number";
|
||||
|
|
@ -989,7 +989,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
|
||||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = aca.fk_accounting_account";
|
||||
$sql .= " WHERE aca.fk_accounting_category = ".((int) $this->id);
|
||||
$sql .= " AND aa.entity = ".$conf->entity;
|
||||
$sql .= " AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " ORDER BY aa.account_number ASC";
|
||||
|
||||
dol_syslog(get_class($this)."::getAccountsForCategory", LOG_DEBUG);
|
||||
|
|
@ -1033,7 +1033,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
|
||||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."c_accounting_category as ac ON ac.rowid = aca.fk_accounting_category";
|
||||
$sql .= " WHERE aca.fk_accounting_account = ".((int) $fkAccountingAccount);
|
||||
$sql .= " AND ac.entity = ".$conf->entity;
|
||||
$sql .= " AND ac.entity = ".((int) $conf->entity);
|
||||
$sql .= " ORDER BY ac.position ASC";
|
||||
|
||||
dol_syslog(get_class($this)."::getCategoriesForAccount", LOG_DEBUG);
|
||||
|
|
@ -1109,7 +1109,7 @@ class AccountancyCategory // extends CommonObject
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account";
|
||||
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
|
||||
$sql .= " )";
|
||||
$sql .= " AND aa.entity = ".$conf->entity;
|
||||
$sql .= " AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " AND aa.active = 1";
|
||||
$sql .= " AND aa.fk_pcg_version = '".$this->db->escape($pcgvercode)."'";
|
||||
$sql .= " ORDER BY aa.account_number ASC";
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
|
||||
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -195,7 +195,7 @@ class AccountingAccount extends CommonObject
|
|||
$sql .= " a.rowid = ".(int) $rowid;
|
||||
} elseif ($account_number) {
|
||||
$sql .= " a.account_number = '".$this->db->escape($account_number)."'";
|
||||
$sql .= " AND a.entity = ".$conf->entity;
|
||||
$sql .= " AND a.entity = ".((int) $conf->entity);
|
||||
}
|
||||
if (!empty($limittocurrentchart)) {
|
||||
$sql .= ' AND a.fk_pcg_version IN (SELECT pcg_version FROM '.$this->db->prefix().'accounting_system WHERE rowid = '.((int) getDolGlobalInt('CHARTOFACCOUNTS')).')';
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ class AccountingJournal extends CommonObject
|
|||
$sql .= " rowid = ".((int) $rowid);
|
||||
} elseif ($journal_code) {
|
||||
$sql .= " code = '".$this->db->escape($journal_code)."'";
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
}
|
||||
|
||||
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class Accountancy extends DolibarrApi
|
|||
* @param int $alreadyexport [=0] by default export data only if it's not yet exported or 1 already exported (always export data even if 'date_export" is set)
|
||||
* @param int $notnotifiedasexport [=0] by default notified as exported or 1 not notified as exported (when the export is done, notified or not the column 'date_export')
|
||||
*
|
||||
* @return string
|
||||
* @return array{modulepart:string,relative_path:string,filename:string,mimetype:string} Generated file metadata
|
||||
*
|
||||
* @url GET exportdata
|
||||
*
|
||||
|
|
@ -271,7 +271,24 @@ class Accountancy extends DolibarrApi
|
|||
throw new RestException(500, 'Error accountancy export : '.implode(',', $accountancyexport->errors));
|
||||
} else {
|
||||
$this->db->commit();
|
||||
exit();
|
||||
|
||||
$filedata = $accountancyexport->generatedfiledata;
|
||||
if (empty($filedata['downloadFilePath']) || empty($filedata['downloadFileFullName'])) {
|
||||
throw new RestException(500, 'Accounting export generated no downloadable file');
|
||||
}
|
||||
|
||||
$outputdir = !empty($conf->accounting->multidir_output[$conf->entity]) ? $conf->accounting->multidir_output[$conf->entity] : $conf->accounting->dir_output;
|
||||
$outputdir = rtrim($outputdir, '/').'/';
|
||||
if (strpos($filedata['downloadFilePath'], $outputdir) !== 0) {
|
||||
throw new RestException(500, 'Accounting export generated a file outside the accounting output directory');
|
||||
}
|
||||
|
||||
return array(
|
||||
'modulepart' => 'export_compta',
|
||||
'relative_path' => substr($filedata['downloadFilePath'], strlen($outputdir)),
|
||||
'filename' => basename($filedata['downloadFileFullName']),
|
||||
'mimetype' => $filedata['downloadFileMimeType'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2015-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2015-2020 Florian Henry <florian.henry@open-concept.pro>
|
||||
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
|
||||
* Copyright (C) 2025 Nicolas Barrouillet <nicolas@pragma-tech.fr>
|
||||
*
|
||||
|
|
@ -350,7 +350,7 @@ class BookKeeping extends CommonObject
|
|||
if (!empty($this->subledger_account)) {
|
||||
$sql .= " AND subledger_account = '".$this->db->escape($this->subledger_account)."'";
|
||||
}
|
||||
$sql .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
|
||||
$sql .= " AND entity = ".((int) $conf->entity); // Do not use getEntity for accounting features
|
||||
|
||||
// Allow duplicates in incomes or loss statements
|
||||
$accountProfit = getDolGlobalString('ACCOUNTING_RESULT_PROFIT');
|
||||
|
|
@ -377,7 +377,7 @@ class BookKeeping extends CommonObject
|
|||
$sqlnum .= " AND fk_docdet = ".((int) $this->fk_docdet);
|
||||
}
|
||||
$sqlnum .= " AND doc_ref = '".$this->db->escape($this->doc_ref)."'"; // ref of source object
|
||||
$sqlnum .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
|
||||
$sqlnum .= " AND entity = ".((int) $conf->entity); // Do not use getEntity for accounting features
|
||||
|
||||
dol_syslog(get_class($this).":: create sqlnum=".$sqlnum, LOG_DEBUG);
|
||||
$resqlnum = $this->db->query($sqlnum);
|
||||
|
|
@ -461,7 +461,7 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ", ".(!empty($this->journal_label) ? ("'".$this->db->escape($this->journal_label)."'") : "NULL");
|
||||
$sql .= ", ".((int) $this->piece_num);
|
||||
$sql .= ", '".$this->db->escape($this->ref)."'";
|
||||
$sql .= ", ".(!isset($this->entity) ? $conf->entity : $this->entity);
|
||||
$sql .= ", ".(!isset($this->entity) ? ((int) $conf->entity) : ((int) $this->entity));
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
|
|
@ -793,9 +793,9 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ' '.(!isset($this->numero_compte) ? 'NULL' : "'".$this->db->escape($this->numero_compte)."'").',';
|
||||
$sql .= ' '.(!isset($this->label_compte) ? 'NULL' : "'".$this->db->escape($this->label_compte)."'").',';
|
||||
$sql .= ' '.(!isset($this->label_operation) ? 'NULL' : "'".$this->db->escape($this->label_operation)."'").',';
|
||||
$sql .= ' '.(!isset($this->debit) ? 'NULL' : $this->debit).',';
|
||||
$sql .= ' '.(!isset($this->credit) ? 'NULL' : $this->credit).',';
|
||||
$sql .= ' '.(!isset($this->montant) ? 'NULL' : $this->montant).',';
|
||||
$sql .= ' '.(!isset($this->debit) ? 'NULL' : ((float) $this->debit)).',';
|
||||
$sql .= ' '.(!isset($this->credit) ? 'NULL' : ((float) $this->credit)).',';
|
||||
$sql .= ' '.(!isset($this->montant) ? 'NULL' : ((float) $this->montant)).',';
|
||||
$sql .= ' '.(!isset($this->sens) ? 'NULL' : "'".$this->db->escape($this->sens)."'").',';
|
||||
$sql .= ' '.((int) $user->id).',';
|
||||
$sql .= ' '."'".$this->db->idate($now)."',";
|
||||
|
|
@ -803,7 +803,7 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ' '.(empty($this->journal_label) ? 'NULL' : "'".$this->db->escape($this->journal_label)."'").',';
|
||||
$sql .= ' '.(empty($this->piece_num) ? 'NULL' : $this->db->escape((string) $this->piece_num)).',';
|
||||
$sql .= ' '.(empty($this->ref) ? "''" : "'".$this->db->escape($this->ref)."'").',';
|
||||
$sql .= ' '.(!isset($this->entity) ? $conf->entity : $this->entity);
|
||||
$sql .= ' '.(!isset($this->entity) ? ((int) $conf->entity) : ((int) $this->entity));
|
||||
$sql .= ')';
|
||||
|
||||
$this->db->begin();
|
||||
|
|
@ -1565,23 +1565,23 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ' doc_date = '.(isDolTms($this->doc_date) ? "'".$this->db->idate($this->doc_date)."'" : 'null').',';
|
||||
$sql .= ' doc_type = '.(isset($this->doc_type) ? "'".$this->db->escape($this->doc_type)."'" : "null").',';
|
||||
$sql .= ' doc_ref = '.(isset($this->doc_ref) ? "'".$this->db->escape($this->doc_ref)."'" : "null").',';
|
||||
$sql .= ' fk_doc = '.(isset($this->fk_doc) ? $this->fk_doc : "null").',';
|
||||
$sql .= ' fk_docdet = '.(isset($this->fk_docdet) ? $this->fk_docdet : "null").',';
|
||||
$sql .= ' fk_doc = '.(isset($this->fk_doc) ? ((int) $this->fk_doc) : "null").',';
|
||||
$sql .= ' fk_docdet = '.(isset($this->fk_docdet) ? ((int) $this->fk_docdet) : "null").',';
|
||||
$sql .= ' thirdparty_code = '.(isset($this->thirdparty_code) ? "'".$this->db->escape($this->thirdparty_code)."'" : "null").',';
|
||||
$sql .= ' subledger_account = '.(isset($this->subledger_account) ? "'".$this->db->escape($this->subledger_account)."'" : "null").',';
|
||||
$sql .= ' subledger_label = '.(isset($this->subledger_label) ? "'".$this->db->escape($this->subledger_label)."'" : "null").',';
|
||||
$sql .= ' numero_compte = '.(isset($this->numero_compte) ? "'".$this->db->escape($this->numero_compte)."'" : "null").',';
|
||||
$sql .= ' label_compte = '.(isset($this->label_compte) ? "'".$this->db->escape($this->label_compte)."'" : "null").',';
|
||||
$sql .= ' label_operation = '.(isset($this->label_operation) ? "'".$this->db->escape($this->label_operation)."'" : "null").',';
|
||||
$sql .= ' debit = '.(isset($this->debit) ? $this->debit : "null").',';
|
||||
$sql .= ' credit = '.(isset($this->credit) ? $this->credit : "null").',';
|
||||
$sql .= ' montant = '.(isset($this->montant) ? $this->montant : "null").',';
|
||||
$sql .= ' debit = '.(isset($this->debit) ? ((float) $this->debit) : "null").',';
|
||||
$sql .= ' credit = '.(isset($this->credit) ? ((float) $this->credit) : "null").',';
|
||||
$sql .= ' montant = '.(isset($this->montant) ? ((float) $this->montant) : "null").',';
|
||||
$sql .= ' sens = '.(isset($this->sens) ? "'".$this->db->escape($this->sens)."'" : "null").',';
|
||||
$sql .= ' fk_user_author = '.(isset($this->fk_user_author) ? $this->fk_user_author : "null").',';
|
||||
$sql .= ' fk_user_author = '.(isset($this->fk_user_author) ? ((int) $this->fk_user_author) : "null").',';
|
||||
$sql .= ' import_key = '.(isset($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null").',';
|
||||
$sql .= ' code_journal = '.(isset($this->code_journal) ? "'".$this->db->escape($this->code_journal)."'" : "null").',';
|
||||
$sql .= ' journal_label = '.(isset($this->journal_label) ? "'".$this->db->escape($this->journal_label)."'" : "null").',';
|
||||
$sql .= ' piece_num = '.(isset($this->piece_num) ? $this->piece_num : "null");
|
||||
$sql .= ' piece_num = '.(isset($this->piece_num) ? ((int) $this->piece_num) : "null");
|
||||
$sql .= ' WHERE rowid='.((int) $this->id);
|
||||
|
||||
$this->db->begin();
|
||||
|
|
@ -2291,7 +2291,7 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
|
||||
$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
|
||||
$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)';
|
||||
$sql .= ' SELECT doc_date, doc_type,' . "'{$ref}',";
|
||||
$sql .= ' SELECT doc_date, doc_type,' . "'".$this->db->escape($ref)."',";
|
||||
$sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
|
||||
$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
|
||||
$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'";
|
||||
|
|
@ -2328,7 +2328,7 @@ class BookKeeping extends CommonObject
|
|||
$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
|
||||
$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
|
||||
$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)';
|
||||
$sql .= ' SELECT doc_date, doc_type,' . "'{$ref}',";
|
||||
$sql .= ' SELECT doc_date, doc_type,' . "'".$this->db->escape($ref)."',";
|
||||
$sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
|
||||
$sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
|
||||
$sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num';
|
||||
|
|
@ -3651,7 +3651,7 @@ class BookKeeping extends CommonObject
|
|||
$bookKeepingInstance = new BookKeeping($this->db);
|
||||
$pieceNumNext = $bookKeepingInstance->getNextNumMvt();
|
||||
$cloneId = [];
|
||||
$sqlRowidClone = "SELECT rowid FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE piece_num = $pieceNum";
|
||||
$sqlRowidClone = "SELECT rowid FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE piece_num = ".((int) $pieceNum);
|
||||
$resqlRowidClone = $this->db->query($sqlRowidClone);
|
||||
|
||||
if ($resqlRowidClone) {
|
||||
|
|
@ -3699,7 +3699,7 @@ class BookKeeping extends CommonObject
|
|||
$sql_insert .= ", montant";
|
||||
$sql_insert .= ")";
|
||||
$sql_insert .= " VALUES (";
|
||||
$sql_insert .= $pieceNumNext;
|
||||
$sql_insert .= ((int) $pieceNumNext);
|
||||
$sql_insert .= ", '" . $this->db->escape($obj->label_operation) . "'";
|
||||
$sql_insert .= ", '" . $this->db->escape($obj->numero_compte) . "'";
|
||||
$sql_insert .= ", '" . $this->db->escape($obj->label_compte) . "'";
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class BookkeepingTemplate extends CommonObject
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDb $db Database handler
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct(DoliDB $db)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ class BookkeepingTemplateLine extends CommonObject
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDb $db Database handler
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct(DoliDB $db)
|
||||
{
|
||||
|
|
@ -247,10 +247,10 @@ class BookkeepingTemplateLine extends CommonObject
|
|||
* @param int $limit limit
|
||||
* @param int $offset Offset
|
||||
* @param array<string,mixed> $filter Filter array. Example array('mystringfield'=>'value', 'myintfield'=>4, 'customsql'=>...)
|
||||
* @param string $filtermode Filter mode (AND or OR)
|
||||
* @param 'AND'|'OR' $sqlfiltermode Filter mode (AND or OR)
|
||||
* @return BookkeepingTemplateLine[]|int Array of BookkeepingTemplateLine objects if OK, <0 if KO
|
||||
*/
|
||||
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
|
||||
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $sqlfiltermode = 'AND')
|
||||
{
|
||||
dol_syslog(__METHOD__, LOG_DEBUG);
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ class BookkeepingTemplateLine extends CommonObject
|
|||
}
|
||||
}
|
||||
if (count($sqlwhere) > 0) {
|
||||
$sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")";
|
||||
$sql .= " AND (".implode(" ".$sqlfiltermode." ", $sqlwhere).")";
|
||||
}
|
||||
|
||||
if (!empty($sortfield)) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -156,10 +156,10 @@ if ($action == 'validatehistory' && $user->hasRight('accounting', 'bind', 'write
|
|||
}
|
||||
$alias_societe_perentity = !getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED') ? "s" : "spe";
|
||||
$alias_product_perentity = !getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p" : "ppe";
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON ".$db->sanitize($alias_societe_perentity).".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON ".$db->sanitize($alias_societe_perentity).".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".((int) $conf->entity);
|
||||
$sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
|
||||
$sql .= " AND l.product_type <= 2";
|
||||
$sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy
|
||||
|
|
@ -356,8 +356,8 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((string) $j), "fd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((string) $j), "1", "0").") AS nbmonth".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "1", "0").") AS nbmonth".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(fd.total_ht) as total, COUNT(fd.rowid) as nb";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
|
||||
|
|
@ -496,7 +496,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(fd.total_ht) as total";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
|
||||
|
|
@ -599,11 +599,14 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(fd.total_ht) as total";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture";
|
||||
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet AS prev_fd ON prev_fd.rowid = fd.fk_prev_id";
|
||||
}
|
||||
$sql .= " WHERE f.datef >= '".$db->idate($search_date_start)."'";
|
||||
$sql .= " AND f.datef <= '".$db->idate($search_date_end)."'";
|
||||
// Define begin binding date
|
||||
|
|
@ -665,16 +668,16 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
"MONTH(f.datef) = ".((int) $j),
|
||||
" (".$db->ifsql(
|
||||
"fd.total_ht < 0",
|
||||
" (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", // TODO This is bugged, we must use the percent for the invoice and fd.situation_percent is cumulated percent !
|
||||
" (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))"
|
||||
" (-1 * (abs(fd.total_ht * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / fd.situation_percent)) - (fd.buy_price_ht * fd.qty * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / 100))))",
|
||||
" (fd.total_ht * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / fd.situation_percent) - (fd.buy_price_ht * fd.qty * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / 100)))"
|
||||
).")",
|
||||
'0'
|
||||
).") AS month".str_pad((string) $j, 2, '0', STR_PAD_LEFT).",";
|
||||
).") AS month".str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql(
|
||||
"fd.total_ht < 0",
|
||||
" (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", // TODO This is bugged, we must use the percent for the invoice and fd.situation_percent is cumulated percent !
|
||||
" (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))"
|
||||
" (-1 * (abs(fd.total_ht * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / fd.situation_percent)) - (fd.buy_price_ht * fd.qty * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / 100))))",
|
||||
" (fd.total_ht * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / fd.situation_percent) - (fd.buy_price_ht * fd.qty * ((fd.situation_percent - COALESCE(prev_fd.situation_percent, 0)) / 100)))"
|
||||
).") as total";
|
||||
} else {
|
||||
$sql = "SELECT '".$db->escape($langs->trans("Vide"))."' AS marge,";
|
||||
|
|
@ -691,7 +694,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
" (fd.total_ht - (fd.buy_price_ht * fd.qty))"
|
||||
).")",
|
||||
'0'
|
||||
).") AS month".str_pad((string) $j, 2, '0', STR_PAD_LEFT).",";
|
||||
).") AS month".str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql(
|
||||
"fd.total_ht < 0",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -309,10 +309,10 @@ if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
|
|||
}
|
||||
$alias_societe_perentity = !getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED') ? "s" : "spe";
|
||||
$alias_product_perentity = !getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p" : "ppe";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON " . $alias_societe_perentity . ".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON " . $alias_societe_perentity . ".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".((int) $conf->entity);
|
||||
// Add table from hooks
|
||||
$parameters = array();
|
||||
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
||||
|
|
@ -541,68 +541,68 @@ if ($result) {
|
|||
}
|
||||
// Line ID
|
||||
if (!empty($arrayfields['l.rowid']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="lineid">';
|
||||
print '<input type="text" class="flat maxwidth40" name="search_lineid" value="'.dol_escape_htmltag($search_lineid).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="lineid">';
|
||||
print '<input type="text" class="flat maxwidth40" name="search_lineid" value="'.dol_escape_htmltag($search_lineid).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Ref invoice
|
||||
if (!empty($arrayfields['f.ref']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="invoice">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_invoice" value="'.dol_escape_htmltag($search_invoice).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="invoice">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_invoice" value="'.dol_escape_htmltag($search_invoice).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Date
|
||||
if (!empty($arrayfields['f.datef']['checked'])) {
|
||||
print '<td class="liste_titre center">';
|
||||
print '<div class="nowrapfordate">';
|
||||
print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
|
||||
print '</div>';
|
||||
print '<div class="nowrapfordate">';
|
||||
print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
|
||||
print '</div>';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre center">';
|
||||
print '<div class="nowrapfordate">';
|
||||
print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
|
||||
print '</div>';
|
||||
print '<div class="nowrapfordate">';
|
||||
print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
|
||||
print '</div>';
|
||||
print '</td>';
|
||||
}
|
||||
// Product ref
|
||||
if (!empty($arrayfields['p.ref']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="ref">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="ref">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Description
|
||||
if (!empty($arrayfields['l.description']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="desc">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_desc" value="'.dol_escape_htmltag($search_desc).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="desc">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_desc" value="'.dol_escape_htmltag($search_desc).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Amount
|
||||
if (!empty($arrayfields['l.total_ht']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="amount">';
|
||||
print '<input type="text" class="right flat maxwidth50" name="search_amount" value="'.dol_escape_htmltag($search_amount).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="amount">';
|
||||
print '<input type="text" class="right flat maxwidth50" name="search_amount" value="'.dol_escape_htmltag($search_amount).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// VAT
|
||||
if (!empty($arrayfields['l.tva_tx']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="vat">';
|
||||
print '<input type="text" class="right flat maxwidth50" placeholder="%" name="search_vat" size="1" value="'.dol_escape_htmltag($search_vat).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="vat">';
|
||||
print '<input type="text" class="right flat maxwidth50" placeholder="%" name="search_vat" size="1" value="'.dol_escape_htmltag($search_vat).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Thirdparty
|
||||
if (!empty($arrayfields['s.nom']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="societe">';
|
||||
print '<input type="text" class="flat maxwidth75imp" name="search_societe" value="'.dol_escape_htmltag($search_societe).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="societe">';
|
||||
print '<input type="text" class="flat maxwidth75imp" name="search_societe" value="'.dol_escape_htmltag($search_societe).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Country
|
||||
if (!empty($arrayfields['co.label']['checked'])) {
|
||||
print '<td class="liste_titre" data-key="country">';
|
||||
print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1);
|
||||
print '</td>';
|
||||
print '<td class="liste_titre" data-key="country">';
|
||||
print $form->select_country($search_country, 'search_country', '', 0, 'maxwidth125', 'code2', 1, 0, 1);
|
||||
print '</td>';
|
||||
}
|
||||
// TVA Intracom
|
||||
if (!empty($arrayfields['s.tva_intra']['checked'])) {
|
||||
print '<td class="liste_titre">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_tvaintra" value="'.dol_escape_htmltag($search_tvaintra).'">';
|
||||
print '</td>';
|
||||
print '<td class="liste_titre">';
|
||||
print '<input type="text" class="flat maxwidth50" name="search_tvaintra" value="'.dol_escape_htmltag($search_tvaintra).'">';
|
||||
print '</td>';
|
||||
}
|
||||
// Data suggested
|
||||
if (!empty($arrayfields['aa.data_suggest']['checked'])) {
|
||||
|
|
@ -610,7 +610,7 @@ if ($result) {
|
|||
}
|
||||
// Account
|
||||
if (!empty($arrayfields['aa.account_number']['checked'])) {
|
||||
print '<td class="liste_titre"></td>';
|
||||
print '<td class="liste_titre"></td>';
|
||||
}
|
||||
// Fields from hook
|
||||
$parameters = array('arrayfields' => $arrayfields);
|
||||
|
|
@ -639,53 +639,53 @@ if ($result) {
|
|||
}
|
||||
// Line ID
|
||||
if (!empty($arrayfields['l.rowid']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['l.rowid']['label'], $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['l.rowid']['label'], $_SERVER["PHP_SELF"], "l.rowid", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Ref invoice
|
||||
if (!empty($arrayfields['f.ref']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['f.ref']['label'], $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['f.ref']['label'], $_SERVER["PHP_SELF"], "f.ref", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Date
|
||||
if (!empty($arrayfields['f.datef']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['f.datef']['label'], $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, '', $sortfield, $sortorder, 'center ');
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['f.datef']['label'], $_SERVER["PHP_SELF"], "f.datef, f.ref, l.rowid", "", $param, '', $sortfield, $sortorder, 'center ');
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Product ref
|
||||
if (!empty($arrayfields['p.ref']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// product description
|
||||
if (!empty($arrayfields['l.description']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['l.description']['label'], $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['l.description']['label'], $_SERVER["PHP_SELF"], "l.description", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Amount
|
||||
if (!empty($arrayfields['l.total_ht']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['l.total_ht']['label'], $_SERVER["PHP_SELF"], "l.total_ht", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['l.total_ht']['label'], $_SERVER["PHP_SELF"], "l.total_ht", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// VAT
|
||||
if (!empty($arrayfields['l.tva_tx']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['l.tva_tx']['label'], $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['l.tva_tx']['label'], $_SERVER["PHP_SELF"], "l.tva_tx", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Thirdparty
|
||||
if (!empty($arrayfields['s.nom']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Country
|
||||
if (!empty($arrayfields['co.label']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['co.label']['label'], $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['co.label']['label'], $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// TVA Intracom
|
||||
if (!empty($arrayfields['s.tva_intra']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['s.tva_intra']['label'], $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
print_liste_field_titre($arrayfields['s.tva_intra']['label'], $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Data suggested
|
||||
if (!empty($arrayfields['aa.data_suggest']['checked'])) {
|
||||
|
|
@ -694,8 +694,8 @@ if ($result) {
|
|||
}
|
||||
// Account
|
||||
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']++;
|
||||
print_liste_field_titre($arrayfields['aa.account_number']['label'], $_SERVER["PHP_SELF"], "aa.account_number", "", $param, '', $sortfield, $sortorder);
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
// Hook fields
|
||||
$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
|
||||
|
|
@ -703,8 +703,8 @@ if ($result) {
|
|||
print $hookmanager->resPrint;
|
||||
// Action column
|
||||
if (!$conf->main_checkbox_left_column) {
|
||||
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
|
||||
$totalarray['nbfield']++;
|
||||
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
print "</tr>\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2013-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -233,7 +233,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
$param .= '&search_month='.$tmp['mon'].'&search_year='.$tmp['year'];
|
||||
print '<a href="'.DOL_URL_ROOT.'/accountancy/expensereport/list.php?'.$param.'">';
|
||||
}
|
||||
print $langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT));
|
||||
print $langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT));
|
||||
if (!empty($tmp['mday'])) {
|
||||
print '</a>';
|
||||
}
|
||||
|
|
@ -248,8 +248,8 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((string) $j), "1", "0").") AS nbmonth".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "1", "0").") AS nbmonth".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(erd.total_ht) as total, COUNT(erd.rowid) as nb";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd";
|
||||
|
|
@ -361,7 +361,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
$param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year'];
|
||||
print '<a href="'.DOL_URL_ROOT.'/accountancy/expensereport/lines.php?'.$param.'">';
|
||||
}
|
||||
print $langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT));
|
||||
print $langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT));
|
||||
if (!empty($tmp['mday'])) {
|
||||
print '</a>';
|
||||
}
|
||||
|
|
@ -376,7 +376,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " ROUND(SUM(erd.total_ht),2) as total";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd";
|
||||
|
|
@ -450,7 +450,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
print '<td width="60" class="right">'.$langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT)).'</td>';
|
||||
print '<td width="60" class="right">'.$langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT)).'</td>';
|
||||
}
|
||||
print '<td width="60" class="right"><b>'.$langs->trans("Total").'</b></td></tr>';
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_create) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(er.date_create) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(erd.total_ht) as total";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd";
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -274,7 +274,7 @@ $sql .= " FROM ".MAIN_DB_PREFIX."expensereport as er";
|
|||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."expensereport_det as erd ON er.rowid = erd.fk_expensereport";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_type_fees as f ON f.id = erd.fk_c_type_fees";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = er.fk_user_author";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON f.accountancy_code = aa.account_number AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON f.accountancy_code = aa.account_number AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".((int) $conf->entity);
|
||||
// Add table from hooks
|
||||
$parameters = array();
|
||||
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
||||
|
|
|
|||
|
|
@ -626,7 +626,7 @@ if ($resql) {
|
|||
} else {
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=cs.rowid";
|
||||
}
|
||||
$sql .= " WHERE cs.entity = ".$conf->entity; // We don't share object for accountancy, we use source object sharing
|
||||
$sql .= " WHERE cs.entity = ".((int) $conf->entity); // We don't share object for accountancy, we use source object sharing
|
||||
// Not already in bookkeeping
|
||||
if ($in_bookkeeping == 'notyet') {
|
||||
$sql .= " AND ab.rowid IS NULL";
|
||||
|
|
@ -694,7 +694,7 @@ if ($resql) {
|
|||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=t.rowid";
|
||||
}
|
||||
$sql .= " WHERE bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
|
||||
// $sql .= " AND t.entity = " . $conf->entity; // TODO when entity is managed in tva
|
||||
// $sql .= " AND t.entity = " . ((int) $conf->entity); // TODO when entity is managed in tva
|
||||
// Not already in bookkeeping
|
||||
if ($in_bookkeeping == 'notyet') {
|
||||
$sql .= " AND ab.rowid IS NULL";
|
||||
|
|
@ -827,7 +827,7 @@ if ($resql) {
|
|||
} else {
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=l.rowid";
|
||||
}
|
||||
$sql .= " WHERE l.entity = ".$conf->entity; // We don't share object for accountancy, we use source object sharing
|
||||
$sql .= " WHERE l.entity = ".((int) $conf->entity); // We don't share object for accountancy, we use source object sharing
|
||||
// Not already in bookkeeping
|
||||
if ($in_bookkeeping == 'notyet') {
|
||||
$sql .= " AND ab.rowid IS NULL";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2013-2022 Alexandre Spangaro <aspangaro@easya.solutions>
|
||||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -155,10 +155,10 @@ if ($action == 'validatehistory' && $user->hasRight('accounting', 'bind', 'write
|
|||
}
|
||||
$alias_societe_perentity = !getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED') ? "s" : "spe";
|
||||
$alias_product_perentity = !getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p" : "ppe";
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON " . $alias_product_perentity . ".accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON " . $alias_product_perentity . ".accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".((int) $conf->entity);
|
||||
$sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0";
|
||||
$sql .= " AND l.product_type <= 2";
|
||||
$sql .= " AND f.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy
|
||||
|
|
@ -208,9 +208,9 @@ if ($action == 'validatehistory' && $user->hasRight('accounting', 'bind', 'write
|
|||
$product_static->label = $objp->product_label;
|
||||
$product_static->status = !empty($objp->status) ? $objp->status : 0;
|
||||
$product_static->status_buy = !empty($objp->status_buy) ? $objp->status_buy : 0;
|
||||
$product_static->accountancy_code_sell = !empty($objp->code_sell)? $objp->code_sell : "";
|
||||
$product_static->accountancy_code_sell_intra = !empty($objp->code_sell_intra)? $objp->code_sell_intra : "";
|
||||
$product_static->accountancy_code_sell_export = !empty($objp->code_sell_export)? $objp->code_sell_export : "";
|
||||
$product_static->accountancy_code_sell = !empty($objp->code_sell) ? $objp->code_sell : "";
|
||||
$product_static->accountancy_code_sell_intra = !empty($objp->code_sell_intra) ? $objp->code_sell_intra : "";
|
||||
$product_static->accountancy_code_sell_export = !empty($objp->code_sell_export) ? $objp->code_sell_export : "";
|
||||
$product_static->accountancy_code_buy = !empty($objp->code_buy) ? $objp->code_buy : "";
|
||||
$product_static->accountancy_code_buy_intra = !empty($objp->code_buy_intra) ? $objp->code_buy_intra : "";
|
||||
$product_static->accountancy_code_buy_export = !empty($objp->code_buy_export) ? $objp->code_buy_export : "";
|
||||
|
|
@ -342,7 +342,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
$param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year'];
|
||||
print '<a href="'.DOL_URL_ROOT.'/accountancy/supplier/list.php?'.$param.'">';
|
||||
}
|
||||
print $langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT));
|
||||
print $langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT));
|
||||
if (!empty($tmp['mday'])) {
|
||||
print '</a>';
|
||||
}
|
||||
|
|
@ -357,8 +357,8 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((string) $j), "1", "0").") AS nbmonth".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "1", "0").") AS nbmonth".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(ffd.total_ht) as total, COUNT(ffd.rowid) as nb";
|
||||
$sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd";
|
||||
|
|
@ -474,7 +474,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
$param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year'];
|
||||
print '<a href="'.DOL_URL_ROOT.'/accountancy/supplier/lines.php?'.$param.'">';
|
||||
}
|
||||
print $langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT));
|
||||
print $langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT));
|
||||
if (!empty($tmp['mday'])) {
|
||||
print '</a>';
|
||||
}
|
||||
|
|
@ -489,7 +489,7 @@ for ($i = 1; $i <= 12; $i++) {
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(ffd.total_ht) as total";
|
||||
$sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd";
|
||||
|
|
@ -573,7 +573,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
print '<td width="60" class="right">'.$langs->trans('MonthShort'.str_pad((string) $j, 2, '0', STR_PAD_LEFT)).'</td>';
|
||||
print '<td width="60" class="right">'.$langs->trans('MonthShort'.str_pad((string) ((int) $j), 2, '0', STR_PAD_LEFT)).'</td>';
|
||||
}
|
||||
print '<td width="60" class="right"><b>'.$langs->trans("Total").'</b></td></tr>';
|
||||
|
||||
|
|
@ -583,7 +583,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa
|
|||
if ($j > 12) {
|
||||
$j -= 12;
|
||||
}
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) $j, 2, "0", STR_PAD_LEFT).",";
|
||||
$sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((string) ((int) $j), 2, "0", STR_PAD_LEFT).",";
|
||||
}
|
||||
$sql .= " SUM(ffd.total_ht) as total";
|
||||
$sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>s
|
||||
* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -313,10 +313,10 @@ if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
|
|||
}
|
||||
$alias_societe_perentity = !getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED') ? "s" : "spe";
|
||||
$alias_product_perentity = !getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p" : "ppe";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON " . $alias_societe_perentity . ".accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity;
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".((int) $conf->entity);
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON " . $alias_societe_perentity . ".accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".((int) $conf->entity);
|
||||
// Add table from hooks
|
||||
$parameters = array();
|
||||
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
||||
|
|
@ -836,7 +836,8 @@ if ($result) {
|
|||
if ($conf->main_checkbox_left_column) {
|
||||
print '<td class="nowrap center actioncolumn">';
|
||||
$selected = in_array($objp->rowid."_".$i, $toselect);
|
||||
print '<input type="checkbox" class="flat checkforselect checkforselect'.$facturefourn_static_det->id.'" name="toselect[]" value="'.$facturefourn_static_det->id."_".$i.'"'.($selected ? " checked" : "").'/>'; print '</td>';
|
||||
print '<input type="checkbox" class="flat checkforselect checkforselect'.$facturefourn_static_det->id.'" name="toselect[]" value="'.$facturefourn_static_det->id."_".$i.'"'.($selected ? " checked" : "").'/>';
|
||||
print '</td>';
|
||||
if (!$i) {
|
||||
$totalarray['nbfield']++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,17 @@ if ((substr($accountancyexport->getFormatCode($formatexportset), 0, 3) == 'fec')
|
|||
|
||||
$endaccountingperiod = dol_print_date(dol_get_last_day($tmparray['year'], $tmparray['mon']), 'dayxcard');
|
||||
$siren = str_replace(" ", "", $siren);
|
||||
$completefilename = $siren."FEC".$endaccountingperiod.".txt";
|
||||
$completefilename = $siren."FEC".$endaccountingperiod;
|
||||
|
||||
// Option: append a timestamp suffix to avoid overwriting a previous export of the same fiscal period.
|
||||
// The strict FEC naming convention (SIRENFECAAAAMMJJ.txt) is still respected by default;
|
||||
// this suffix is only added if the admin explicitly enables it, since some import software
|
||||
// requires strict compliance with the official filename.
|
||||
if (getDolGlobalInt('ACCOUNTING_EXPORT_FEC_ADD_TIMESTAMP')) {
|
||||
$completefilename .= "_".dol_print_date(dol_now(), '%Y%m%d%H%M%S');
|
||||
}
|
||||
|
||||
$completefilename .= ".txt";
|
||||
} elseif ($accountancyexport->getFormatCode($formatexportset) == 'ciel' && $type_export == "general_ledger" && getDolGlobalString('ACCOUNTING_EXPORT_XIMPORT_FORCE_FILENAME')) {
|
||||
$completefilename = "XIMPORT.TXT";
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -51,7 +52,7 @@ if (!$user->admin) {
|
|||
}
|
||||
|
||||
|
||||
$oldtypetonewone = array('texte'=>'text', 'chaine'=>'string'); // old type to new ones
|
||||
$oldtypetonewone = array('texte' => 'text', 'chaine' => 'string'); // old type to new ones
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
|
||||
|
|
@ -64,17 +65,17 @@ $helptext .= '__COMPANY__, __ADDRESS__, __ZIP__, __TOWN__, __COUNTRY__, __EMAIL_
|
|||
|
||||
// Editing global variables not related to a specific theme
|
||||
$constantes = array(
|
||||
'MEMBER_REMINDER_EMAIL' => array('type'=>'yesno', 'label' => $langs->trans('MEMBER_REMINDER_EMAIL', $langs->transnoentities("Module2300Name")), 'help' => $langs->trans('MEMBER_REMINDER_EMAILHelp', $langs->transnoentities("Module2300Name"))),
|
||||
'ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_AUTOREGISTER' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_CANCELATION' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_EXCLUSION' => array('type'=>'emailtemplate:member', 'label'=>''),
|
||||
'ADHERENT_MAIL_FROM' => array('type'=>'string', 'label'=>''),
|
||||
'ADHERENT_CC_MAIL_FROM' => array('type'=>'string', 'label'=>''),
|
||||
'ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT' => array('type'=>'string', 'label'=>''),
|
||||
'ADHERENT_AUTOREGISTER_NOTIF_MAIL' => array('type'=>'html', 'tooltip' => $helptext, 'label' => '')
|
||||
'MEMBER_REMINDER_EMAIL' => array('type' => 'yesno', 'label' => $langs->trans('MEMBER_REMINDER_EMAIL', $langs->transnoentities("Module2300Name")), 'help' => $langs->trans('MEMBER_REMINDER_EMAILHelp', $langs->transnoentities("Module2300Name"))),
|
||||
'ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_AUTOREGISTER' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_CANCELATION' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_EMAIL_TEMPLATE_EXCLUSION' => array('type' => 'emailtemplate:member', 'label' => ''),
|
||||
'ADHERENT_MAIL_FROM' => array('type' => 'string', 'label' => ''),
|
||||
'ADHERENT_CC_MAIL_FROM' => array('type' => 'string', 'label' => ''),
|
||||
'ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT' => array('type' => 'string', 'label' => ''),
|
||||
'ADHERENT_AUTOREGISTER_NOTIF_MAIL' => array('type' => 'html', 'tooltip' => $helptext, 'label' => '')
|
||||
);
|
||||
|
||||
|
||||
|
|
@ -186,7 +187,7 @@ foreach ($tableau as $key => $const) { // Loop on each param
|
|||
$sql = "SELECT rowid, ".$db->decrypt('name')." as name, ".$db->decrypt('value')." as value, type, note";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."const";
|
||||
$sql .= " WHERE ".$db->decrypt('name')." = '".$db->escape($const)."'";
|
||||
$sql .= " AND entity IN (0, ".$conf->entity.")";
|
||||
$sql .= " AND entity IN (0, ".((int) $conf->entity).")";
|
||||
$sql .= " ORDER BY name ASC, entity DESC";
|
||||
$resql = $db->query($sql);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* Copyright (C) 2015-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
|
||||
* Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2021 Waël Almoman <info@almoman.com>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -206,7 +206,7 @@ if (empty($reshook)) {
|
|||
if ($socid != $object->socid) { // If link differs from currently in database
|
||||
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
|
||||
$sql .= " WHERE socid = ".((int) $socid);
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
$obj = $db->fetch_object($resql);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* Copyright (C) 2020 Josep Lluís Amador <joseplluis@lliuretic.cat>
|
||||
* Copyright (C) 2021 Waël Almoman <info@almoman.com>
|
||||
* Copyright (C) 2021 Philippe Grand <philippe.grand@atoo-net.com>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -505,17 +505,17 @@ class Adherent extends CommonObject
|
|||
}
|
||||
|
||||
// Send mail confirmation
|
||||
$from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
|
||||
$email_from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
|
||||
|
||||
$trackid = 'mem'.$this->id;
|
||||
|
||||
// Send email (substitutionarray must be done just before this)
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
||||
$mailfile = new CMailFile($subjecttosend, (string) $this->email, $from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
|
||||
$mailfile = new CMailFile($subjecttosend, (string) $this->email, $email_from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
|
||||
if ($mailfile->sendfile()) {
|
||||
return 1;
|
||||
} else {
|
||||
$this->error = $langs->trans("ErrorFailedToSendMail", $from, (string) $this->email).'. '.$mailfile->error;
|
||||
$this->error = $langs->trans("ErrorFailedToSendMail", $email_from, (string) $this->email).'. '.$mailfile->error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -697,7 +697,7 @@ class Adherent extends CommonObject
|
|||
$sql .= " '(PROV)'";
|
||||
$sql .= ", '".$this->db->idate($this->datec)."'";
|
||||
$sql .= ", ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
|
||||
$sql .= ", ".($user->id > 0 ? $user->id : "null"); // Can be null because member can be created by a guest or a script
|
||||
$sql .= ", ".($user->id > 0 ? ((int) $user->id) : "null"); // Can be null because member can be created by a guest or a script
|
||||
$sql .= ", null, null, '".$this->db->escape($this->morphy)."'";
|
||||
$sql .= ", ".((int) $this->typeid);
|
||||
$sql .= ", ".((int) $this->entity);
|
||||
|
|
@ -871,7 +871,7 @@ class Adherent extends CommonObject
|
|||
if ($this->datevalid) {
|
||||
$sql .= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
|
||||
}
|
||||
$sql .= ", fk_user_mod = ".($user->id > 0 ? $user->id : 'null'); // Can be null because member can be create by a guest
|
||||
$sql .= ", fk_user_mod = ".($user->id > 0 ? ((int) $user->id) : 'null'); // Can be null because member can be create by a guest
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
// If we change the type of membership, we set also label of new type..
|
||||
|
|
@ -1503,7 +1503,7 @@ class Adherent extends CommonObject
|
|||
if ($thirdpartyid > 0) {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
|
||||
$sql .= " WHERE fk_soc = ".((int) $thirdpartyid);
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
|
||||
$resql = $this->db->query($sql);
|
||||
}
|
||||
|
|
@ -1539,7 +1539,7 @@ class Adherent extends CommonObject
|
|||
|
||||
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
|
||||
$sql .= " WHERE login='".$this->db->escape($login)."'";
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
|
|
@ -1568,7 +1568,7 @@ class Adherent extends CommonObject
|
|||
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
|
||||
$sql .= " WHERE firstname='".$this->db->escape($firstname)."'";
|
||||
$sql .= " AND lastname='".$this->db->escape($lastname)."'";
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
|
|
@ -3333,7 +3333,7 @@ class Adherent extends CommonObject
|
|||
|
||||
$subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
|
||||
$msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
|
||||
$from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
|
||||
$email_from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
|
||||
$to = $adherent->email;
|
||||
$cc = getDolGlobalString('ADHERENT_CC_MAIL_FROM');
|
||||
|
||||
|
|
@ -3341,7 +3341,7 @@ class Adherent extends CommonObject
|
|||
$moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
||||
$cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), $cc, '', 0, 1, '', '', $trackid, $moreinheader);
|
||||
$cmail = new CMailFile($subject, $to, $email_from, $msg, array(), array(), array(), $cc, '', 0, 1, '', '', $trackid, $moreinheader);
|
||||
$result = $cmail->sendfile();
|
||||
if (!$result) {
|
||||
$error++;
|
||||
|
|
@ -3363,9 +3363,9 @@ class Adherent extends CommonObject
|
|||
$extraparams = array();
|
||||
|
||||
$actionmsg = '';
|
||||
$actionmsg2 = $langs->transnoentities('MailSentByTo', CMailFile::getValidAddress($from, 4, 0, 1), CMailFile::getValidAddress($sendto, 4, 0, 1));
|
||||
$actionmsg2 = $langs->transnoentities('MailSentByTo', CMailFile::getValidAddress($email_from, 4, 0, 1), CMailFile::getValidAddress($sendto, 4, 0, 1));
|
||||
if ($message) {
|
||||
$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
|
||||
$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($email_from);
|
||||
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
|
||||
// if ($sendtocc) {
|
||||
// $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
|
||||
|
|
@ -3394,7 +3394,7 @@ class Adherent extends CommonObject
|
|||
$actioncomm->userownerid = $user->id; // Owner of action
|
||||
// Fields when action is an email (content should be added into note)
|
||||
$actioncomm->email_msgid = $cmail->msgid;
|
||||
$actioncomm->email_from = $from;
|
||||
$actioncomm->email_from = $email_from;
|
||||
$actioncomm->email_sender = '';
|
||||
$actioncomm->email_to = $to;
|
||||
$actioncomm->email_tocc = $sendtocc;
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ class Subscription extends CommonObject
|
|||
$sql .= " '".$this->db->escape($this->note_public ? $this->note_public : $this->note)."',";
|
||||
$sql .= " '".$this->db->escape($this->note_private)."',";
|
||||
$sql .= " ".(empty($this->ref_ext) ? "null" : "'".$this->db->escape($this->ref_ext)."'").",";
|
||||
$sql .= " ".((int) ($this->user_creation_id > 0 ? $this->user_creation_id : $user->id));
|
||||
$sql .= " ".((int) ($this->user_creation_id > 0 ? $this->user_creation_id : ((int) $user->id)));
|
||||
$sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
|
||||
$sql .= ")";
|
||||
|
||||
|
|
@ -547,9 +547,9 @@ class Subscription extends CommonObject
|
|||
*/
|
||||
public function info($id)
|
||||
{
|
||||
$sql = 'SELECT c.rowid, c.datec, c.tms as datem, c.fk_user_creat';
|
||||
$sql .= ' FROM '.MAIN_DB_PREFIX.'subscription as c';
|
||||
$sql .= ' WHERE c.rowid = '.((int) $id);
|
||||
$sql = "SELECT c.rowid, c.datec, c.tms as datem, c.fk_user_creat";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
|
||||
$sql .= " WHERE c.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
|
|
|
|||
|
|
@ -834,11 +834,11 @@ print '<input type="hidden" name="page_y" value="">';
|
|||
print '<input type="hidden" name="mode" value="'.$mode.'">';
|
||||
|
||||
$newcardbutton = '';
|
||||
$queryforbutton = $query;
|
||||
$queryforbutton['mode'] = 'common';
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', dolBuildUrl($_SERVER["PHP_SELF"], $queryforbutton), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
|
||||
$queryforbutton['mode'] = 'kanban';
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', dolBuildUrl($_SERVER["PHP_SELF"], $queryforbutton), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
|
||||
$argsforbutton = $query;
|
||||
$argsforbutton['mode'] = 'common';
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', dolBuildUrl($_SERVER["PHP_SELF"], $argsforbutton), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
|
||||
$argsforbutton['mode'] = 'kanban';
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', dolBuildUrl($_SERVER["PHP_SELF"], $argsforbutton), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('Statistics'), '', 'fa fa-chart-bar imgforviewmode', dol_buildpath('/adherents/stats/geo.php', 1).'?mode=memberbycountry&objecttype=adherent@adherent'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', ($mode == 'statistics' ? 2 : 1), array('morecss' => 'reposition'));
|
||||
$newcardbutton .= dolGetButtonTitleSeparator();
|
||||
$newcardbutton .= dolGetButtonTitle($langs->trans('NewMember'), '', 'fa fa-plus-circle', dolBuildUrl(DOL_URL_ROOT.'/adherents/card.php', ['action' => 'create']), '', $user->hasRight('adherent', 'creer'));
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ if ($id > 0 || !empty($ref)) {
|
|||
|
||||
// Define variables to determine what the current user can do on the members
|
||||
$permissiontoaddmember = $user->hasRight('adherent', 'creer');
|
||||
$permissiontoeditextra = $permissiontoaddmember;
|
||||
if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
|
||||
// For action 'update_extras', is there a specific permission set for the attribute to update
|
||||
$permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
|
||||
}
|
||||
|
||||
// Security check
|
||||
$result = restrictedArea($user, 'adherent', $object->id, '', '', 'socid', 'rowid', 0);
|
||||
|
|
@ -138,6 +143,28 @@ if ($reshook < 0) {
|
|||
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
||||
}
|
||||
|
||||
if (empty($reshook) && $action == 'update_extras' && $permissiontoeditextra) {
|
||||
$error = 0;
|
||||
$object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
|
||||
$attribute_name = GETPOST('attribute', 'aZ09');
|
||||
|
||||
// Fill array 'array_options' with data from update form
|
||||
$ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
|
||||
if ($ret < 0) {
|
||||
$error++;
|
||||
}
|
||||
if (!$error) {
|
||||
$result = $object->updateExtraField($attribute_name, 'MEMBER_MODIFY');
|
||||
if ($result < 0) {
|
||||
setEventMessages($object->error, $object->errors, 'errors');
|
||||
$error++;
|
||||
}
|
||||
}
|
||||
if ($error) {
|
||||
$action = 'edit_extras';
|
||||
}
|
||||
}
|
||||
|
||||
// Create third party from a member
|
||||
if (empty($reshook) && $action == 'confirm_create_thirdparty' && $confirm == 'yes' && $user->hasRight('societe', 'creer')) {
|
||||
if ($result > 0) {
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ if ($action == 'setcoder') {
|
|||
$sqlp = "UPDATE ".MAIN_DB_PREFIX."c_barcode_type";
|
||||
$sqlp .= " SET coder = '".$db->escape($coder)."'";
|
||||
$sqlp .= " WHERE rowid = ".((int) $code_id);
|
||||
$sqlp .= " AND entity = ".$conf->entity;
|
||||
$sqlp .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$resql = $db->query($sqlp);
|
||||
if (!$resql) {
|
||||
|
|
@ -106,7 +106,7 @@ if ($action == 'setcoder') {
|
|||
} elseif ($action == 'updateengine') {
|
||||
$sql = "SELECT rowid, coder";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."c_barcode_type";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " ORDER BY code";
|
||||
|
||||
$resql = $db->query($sql);
|
||||
|
|
@ -124,7 +124,7 @@ if ($action == 'setcoder') {
|
|||
$sqlp = "UPDATE ".MAIN_DB_PREFIX."c_barcode_type";
|
||||
$sqlp .= " SET coder = '".$db->escape($coder)."'";
|
||||
$sqlp .= " WHERE rowid = ".((int) $code_id);
|
||||
$sqlp .= " AND entity = ".$conf->entity;
|
||||
$sqlp .= " AND entity = ".((int) $conf->entity);
|
||||
|
||||
$upsql = $db->query($sqlp);
|
||||
if (!$upsql) {
|
||||
|
|
@ -413,7 +413,7 @@ if (getDolGlobalString('BARCODE_USE_ON_PRODUCT') || getDolGlobalString('BARCODE_
|
|||
|
||||
$sql = "SELECT rowid, code as encoding, libelle as label, coder, example";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."c_barcode_type";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " ORDER BY code";
|
||||
|
||||
dol_syslog("admin/barcode.php", LOG_DEBUG);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2004-2022 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -124,7 +124,7 @@ if ($action == 'add') {
|
|||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes (";
|
||||
$sql .= "box_id, position, box_order, fk_user, entity";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= ((int) $boxid['value']).", ".((int) $pos).", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".((int) $fk_user).", ".$conf->entity;
|
||||
$sql .= ((int) $boxid['value']).", ".((int) $pos).", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".((int) $fk_user).", ".((int) $conf->entity);
|
||||
$sql .= ")";
|
||||
|
||||
dol_syslog("boxes.php activate box", LOG_DEBUG);
|
||||
|
|
@ -159,7 +159,7 @@ if ($action == 'delete') {
|
|||
$db->begin();
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " AND box_id=".((int) $obj->box_id);
|
||||
|
||||
$resql = $db->query($sql);
|
||||
|
|
@ -236,7 +236,7 @@ $sql = "SELECT b.rowid, b.box_id, b.position, b.box_order,";
|
|||
$sql .= " bd.rowid as boxid";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."boxes as b, ".MAIN_DB_PREFIX."boxes_def as bd";
|
||||
$sql .= " WHERE b.box_id = bd.rowid";
|
||||
$sql .= " AND b.entity IN (0,".$conf->entity.")";
|
||||
$sql .= " AND b.entity IN (0,".((int) $conf->entity).")";
|
||||
$sql .= " AND b.fk_user = 0";
|
||||
$sql .= " ORDER by b.position, b.box_order";
|
||||
//print $sql;
|
||||
|
|
@ -272,7 +272,7 @@ if ($resql) {
|
|||
// This occurs just after an insert.
|
||||
$sql = "SELECT box_order";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."boxes";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " AND LENGTH(box_order) <= 2";
|
||||
|
||||
dol_syslog("Execute requests to renumber box order", LOG_DEBUG);
|
||||
|
|
@ -282,21 +282,21 @@ if ($resql) {
|
|||
if (dol_strlen($record['box_order']) == 1) {
|
||||
if (preg_match("/[13579]{1}/", substr($record['box_order'], -1))) {
|
||||
$box_order = "A0".$record['box_order'];
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".((int) $conf->entity)." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$resql = $db->query($sql);
|
||||
} elseif (preg_match("/[02468]{1}/", substr($record['box_order'], -1))) {
|
||||
$box_order = "B0".$record['box_order'];
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".((int) $conf->entity)." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$resql = $db->query($sql);
|
||||
}
|
||||
} elseif (dol_strlen($record['box_order']) == 2) {
|
||||
if (preg_match("/[13579]{1}/", substr($record['box_order'], -1))) {
|
||||
$box_order = "A".$record['box_order'];
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".((int) $conf->entity)." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$resql = $db->query($sql);
|
||||
} elseif (preg_match("/[02468]{1}/", substr($record['box_order'], -1))) {
|
||||
$box_order = "B".$record['box_order'];
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".((int) $conf->entity)." AND box_order = '".$db->escape($record['box_order'])."'";
|
||||
$resql = $db->query($sql);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ $hookmanager->initHooks(array('admincompany', 'globaladmin'));
|
|||
|
||||
$object = new Societe($db);
|
||||
|
||||
if (!getDolGlobalString('MAIN_INFO_SOCIETE_NOM') || !getDolGlobalString('MAIN_INFO_SOCIETE_COUNTRY') || getDolGlobalString('MAIN_INFO_SOCIETE_SETUP_TODO_WARNING')) {
|
||||
$setupcompanynotcomplete = 1;
|
||||
} else {
|
||||
$setupcompanynotcomplete = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actions
|
||||
|
|
@ -444,8 +450,8 @@ $head = company_admin_prepare_head();
|
|||
|
||||
print dol_get_fiche_head($head, 'company', '', -1, '');
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("CompanyFundationDesc", $langs->transnoentities("Save"))."</span><br>\n";
|
||||
print "<br><br>\n";
|
||||
print '<div class="'.($setupcompanynotcomplete ? 'warning' : 'info').'">'.$langs->trans("CompanyFundationDesc", $langs->transnoentities("Save"))."</div>\n";
|
||||
print "<br>\n";
|
||||
|
||||
|
||||
// Edit parameters
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ $head = company_admin_prepare_head();
|
|||
|
||||
print dol_get_fiche_head($head, 'socialnetworks', '', -1, '');
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("CompanyFundationDesc", $langs->transnoentities("Save"))."</span><br>\n";
|
||||
print '<span class="opacitymedium">'.$langs->trans("MoreNetworksAvailableWithModule")."</span><br>\n";
|
||||
print '<div class="info">'.$langs->trans("CompanyFundationDesc", $langs->transnoentities("Save"))."<br>\n";
|
||||
print $langs->trans("MoreNetworksAvailableWithModule")."</div>\n";
|
||||
print "<br>\n";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -259,7 +260,7 @@ $sql .= ", note";
|
|||
$sql .= ", tms";
|
||||
$sql .= ", entity";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."const";
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".((int) $conf->entity)).")";
|
||||
if ((empty($user->entity)/* || $user->admin */) && $debug) {
|
||||
// empty
|
||||
} elseif (!GETPOST('visible') || GETPOST('visible') != 'all') {
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ if (empty($sortfield)) {
|
|||
$tmp1 = explode(',', empty($tabcomplete[$keytable]['sqlsort']) ? '' : $tabcomplete[$keytable]['sqlsort']);
|
||||
$tmp2 = explode(' ', $tmp1[0]);
|
||||
$sortfield = preg_replace('/^.*\./', '', $tmp2[0]);
|
||||
$sortorder = (!empty($tmp2[1]) ? $tmp2[1] : '');
|
||||
$sortorder = (!empty($tmp2[1]) ? $tmp2[1] : ''); // @phan-suppress-current-line SqlInjection
|
||||
//var_dump($sortfield); //var_dump($sortorder);
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +984,7 @@ if (empty($reshook)) {
|
|||
|
||||
// List of values
|
||||
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
|
||||
$sql .= $newid.",";
|
||||
$sql .= ((int) $newid).",";
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
|
|
@ -2618,6 +2618,10 @@ if ($id > 0) {
|
|||
$valuetoshow = $langs->trans($valuetoshow ? $valuetoshow : $tmpid);
|
||||
} elseif ($tabname[$id] == 'c_exp_tax_cat') {
|
||||
$valuetoshow = $langs->trans($valuetoshow);
|
||||
} elseif ($value == 'libelle' && ($tabname[$id] == 'c_stcomm' || $tabname[$id] == 'c_stcommcontact')) {
|
||||
$key = 'StatusProspect'.$obj->rowid;
|
||||
$trans = $langs->trans($key);
|
||||
$valuetoshow = ($trans != $key ? $trans : $obj->{$value});
|
||||
} elseif ($value == 'label' && $tabname[$id] == 'c_units') {
|
||||
$langs->load('other');
|
||||
$key = $langs->trans($obj->label);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
/**
|
||||
* \file htdocs/admin/external_rss.php
|
||||
* \ingroup external_rss
|
||||
* \brief Page to setupe module ExternalRss
|
||||
* \brief Page to setup the ExternalRss module
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
|
|
@ -89,7 +89,7 @@ if ($action == 'add' || GETPOST("modify")) {
|
|||
$db->begin();
|
||||
|
||||
if (GETPOST("modify")) {
|
||||
// Supprime boite box_external_rss de definition des boites
|
||||
// Remove box_external_rss from the definition of boxes
|
||||
/* $sql = "UPDATE ".MAIN_DB_PREFIX."boxes_def";
|
||||
$sql.= " SET name = '".$db->escape($boxlabel)."'";
|
||||
$sql.= " WHERE file ='box_external_rss.php' AND note LIKE '".$db->escape(GETPOST("norss"))." %'";
|
||||
|
|
@ -102,7 +102,7 @@ if ($action == 'add' || GETPOST("modify")) {
|
|||
}
|
||||
*/
|
||||
} else {
|
||||
// Ajoute boite box_external_rss dans definition des boites
|
||||
// Add box_external_rss to the definition of boxes
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes_def (file, note)";
|
||||
$sql .= " VALUES ('box_external_rss.php', '".$db->escape(GETPOSTINT("norss")." (".GETPOST($external_rss_title)).")')";
|
||||
if (!$db->query($sql)) {
|
||||
|
|
@ -148,7 +148,7 @@ if (GETPOST("delete")) {
|
|||
$obj = $db->fetch_object($resql);
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " AND box_id = ".((int) $obj->rowid);
|
||||
$resql = $db->query($sql);
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ $linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore
|
|||
print load_fiche_titre($langs->trans("ExternalRSSSetup"), $linkback, 'title_setup');
|
||||
print '<br>';
|
||||
|
||||
// Formulaire ajout
|
||||
// From to add
|
||||
print '<form name="externalrssconfig" action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
|
||||
|
|
@ -358,7 +358,7 @@ llxFooter();
|
|||
$db->close();
|
||||
|
||||
/**
|
||||
* Check if the given RSS feed if inside the list of boxes/widgets
|
||||
* Check if the given RSS feed is inside the list of boxes/widgets
|
||||
*
|
||||
* @param int $idrss The id of the RSS feed
|
||||
* @param ModeleBoxes[] $boxlist A list with boxes/widgets
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ if ($action == 'confirm_delete' && GETPOST('confirm') == 'yes') {
|
|||
$db->begin();
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
$sql .= " AND box_id = ".((int) $key);
|
||||
$resql1 = $db->query($sql);
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ print '<br>';
|
|||
|
||||
$arrayofeinvoiceneed = array(
|
||||
'FR' => array('module' => array('einvoice', 'pdpconnectfr'), 'search' => 'e-invoice'),
|
||||
'ES' => array('search' => 'veri factu'),
|
||||
'ES' => array('search' => 'verifactu'),
|
||||
'BE' => array('search' => 'peppol'),
|
||||
'PL' => array('module' => array('ksef'), 'search' => 'ksef')
|
||||
);
|
||||
|
|
@ -196,7 +196,7 @@ if ($mysoc->country_code && in_array($mysoc->country_code, array_keys($arrayofei
|
|||
print img_picto('', 'bill', 'class="paddingright valignmiddle double"');
|
||||
print ' ';
|
||||
print '<a class="nounderlineimp fontsize-1-1" href="'.$urleinvoice.'">'.$langs->transnoentities("EInvoice").'</a>';
|
||||
if ($modulefound) {
|
||||
if ($modulefound || getDolGlobalString('MAIN_FAKE_EINVOICE_MODULE_FOUND')) {
|
||||
print '<br><br>'.$langs->trans("AnEInvoiceModuleHasBeenEnabled", $mysoc->country_code);
|
||||
} else {
|
||||
print '<br><br>'.$langs->trans("SetupDescriptionEInvoice", $mysoc->country_code);
|
||||
|
|
|
|||
|
|
@ -69,10 +69,19 @@ $form = new Form($db);
|
|||
$formSetup = new FormSetup($db);
|
||||
|
||||
|
||||
// Setup conf MYMODULE_MYPARAM4 : example of quick define write style
|
||||
$formSetup->newItem('INVOICE_USE_SITUATION')
|
||||
->setAsYesNo()
|
||||
->nameText = $langs->trans('UseSituationInvoices');
|
||||
// INVOICE_USE_SITUATION is a 3-state flag (0=off, 1=cumulative/legacy, 2=progressive), see admin/invoice.php.
|
||||
// A yes/no toggle can only write 0 or 1 and deletes the const when turned off (ajax_constantonoff calls
|
||||
// dolibarr_del_const): mode 2 could not be selected and was silently dropped. Use a 3-value select, which
|
||||
// writes the literal value via dolibarr_set_const and never deletes the const.
|
||||
$item = $formSetup->newItem('INVOICE_USE_SITUATION');
|
||||
$item->setAsSelect(array(
|
||||
0 => $langs->trans('Disabled'),
|
||||
1 => $langs->trans('SituationInvoiceModeCumulative'),
|
||||
2 => $langs->trans('SituationInvoiceModeProgressive'),
|
||||
));
|
||||
$situationModeHelp = $langs->trans('SituationInvoiceModeHelp')
|
||||
.'<br><b>'.$langs->trans('SituationInvoiceModeWarning').'</b>';
|
||||
$item->nameText = $langs->trans('SituationInvoiceMode').info_admin($situationModeHelp, 0, 0, 'warning', 'clearboth');
|
||||
|
||||
$item = $formSetup->newItem('INVOICE_USE_SITUATION_CREDIT_NOTE')
|
||||
->setAsYesNo()
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ $langs->loadLangs(array('companies', 'products', 'admin'));
|
|||
$action = GETPOST('action', 'aZ09');
|
||||
$cancel = GETPOST('cancel', 'alpha');
|
||||
$currencycode = GETPOST('currencycode', 'alpha');
|
||||
|
||||
if (empty($action)) {
|
||||
$action = 'edit';
|
||||
}
|
||||
if (isModEnabled('multicompany') && getDolGlobalString('MULTICURRENCY_USE_LIMIT_BY_CURRENCY')) {
|
||||
// When MULTICURRENCY_USE_LIMIT_BY_CURRENCY is on, we use always a defined currency code instead of '' even for default.
|
||||
$currencycode = (!empty($currencycode) ? $currencycode : getDolCurrency());
|
||||
|
|
@ -118,6 +120,8 @@ if ($action == 'update' && !$cancel) {
|
|||
|
||||
dolibarr_set_const($db, $mainroundingruletot, $valmainroundingruletot, 'chaine', 0, '', $conf->entity);
|
||||
|
||||
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
|
||||
|
||||
header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup".(!empty($currencycode) ? '¤cycode='.$currencycode : ''));
|
||||
exit;
|
||||
}
|
||||
|
|
@ -194,8 +198,10 @@ if ($action == 'edit') {
|
|||
|
||||
print '<div class="center">';
|
||||
print '<input class="button button-save" type="submit" name="save" value="'.$langs->trans("Save").'">';
|
||||
/*
|
||||
print ' ';
|
||||
print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
|
||||
*/
|
||||
print '</div>';
|
||||
print '<br>';
|
||||
|
||||
|
|
@ -243,6 +249,8 @@ if (empty($mysoc->country_code)) {
|
|||
// Show examples
|
||||
print load_fiche_titre($langs->trans("ExamplesWithCurrentSetup"), '', '');
|
||||
|
||||
print '<div class="small">';
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("NumberFormatForATotalPrice", '1234.56789').':</span> '.price(price2num(1234.56789, 'MT'), 0, $langs, 1, -1, -1, $currencycode)."<br>\n";
|
||||
|
||||
// Always show vat rates with vat 0
|
||||
|
|
@ -355,6 +363,8 @@ if (empty($mysoc->country_code)) {
|
|||
print ' - <span class="opacitymedium">'.$langs->trans("VAT").":</span> ".$vat.'%';
|
||||
print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n";
|
||||
}
|
||||
|
||||
print '</div>';
|
||||
}
|
||||
|
||||
// End of page
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2016 Jonathan TISSEAU <jonathan.tisseau@86dev.fr>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/**
|
||||
* \file htdocs/admin/mails.php
|
||||
* \brief Page to setup emails sending
|
||||
* \brief Email setup page
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
|
|
@ -798,7 +798,7 @@ if ($action == 'edit') {
|
|||
|
||||
print dol_get_fiche_head(array(), '', '', -1);
|
||||
|
||||
// Cree l'objet formulaire mail
|
||||
// Create the mail form object
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$formmail = new FormMail($db);
|
||||
$formmail->trackid = (($action == 'testhtml') ? "testhtml" : "test");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2016 Jonathan TISSEAU <jonathan.tisseau@86dev.fr>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -849,7 +849,7 @@ if ($action == 'edit') {
|
|||
|
||||
print dol_get_fiche_head(array(), '', '', -1);
|
||||
|
||||
// Cree l'objet formulaire mail
|
||||
// Create the email form object
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$formmail = new FormMail($db);
|
||||
$formmail->fromname = (GETPOSTISSET('fromname') ? GETPOST('fromname', 'restricthtml') : getDolGlobalString('MAIN_MAIL_EMAIL_FROM'));
|
||||
|
|
|
|||
|
|
@ -776,6 +776,9 @@ if ($sortorder) {
|
|||
if ($sortfield) {
|
||||
$paramwithsearch .= '&sortfield='.urlencode($sortfield);
|
||||
}
|
||||
if ($limit) {
|
||||
$paramwithsearch .= '&limit='.((int) $limit);
|
||||
}
|
||||
if (GETPOST('from', 'alpha')) {
|
||||
$paramwithsearch .= '&from='.urlencode(GETPOST('from', 'alpha'));
|
||||
}
|
||||
|
|
@ -813,7 +816,6 @@ if ($action != 'create') {
|
|||
if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) {
|
||||
print load_fiche_titre($title, '', $titlepicto);
|
||||
} else {
|
||||
//print load_fiche_titre($title, $newcardbutton, $titlepicto);
|
||||
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'tools', 0, $newcardbutton, '', $limit, 'limit', 0, 1);
|
||||
}
|
||||
|
||||
|
|
@ -1173,11 +1175,11 @@ foreach ($fieldlist as $field => $value) {
|
|||
if ($sortfieldtouse == 'type_template') {
|
||||
$sortfieldtouse .= ',lang,position,label';
|
||||
}
|
||||
print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], $sortfieldtouse, ($page ? 'page='.$page.'&' : ''), $param, '', $sortfield, $sortorder, $css.' ');
|
||||
print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], $sortfieldtouse, ($page ? 'page='.$page.'&' : ''), $paramwithsearch, '', $sortfield, $sortorder, $css.' ');
|
||||
}
|
||||
}
|
||||
|
||||
print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $param, '', $sortfield, $sortorder, 'center ');
|
||||
print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $paramwithsearch, '', $sortfield, $sortorder, 'center ');
|
||||
// Action column
|
||||
if (!$conf->main_checkbox_left_column) {
|
||||
print getTitleFieldOfList('');
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2016 Jonathan TISSEAU <jonathan.tisseau@86dev.fr>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -794,7 +794,7 @@ if ($action == 'edit') {
|
|||
|
||||
print dol_get_fiche_head(array(), '', '', -1);
|
||||
|
||||
// Cree l'objet formulaire mail
|
||||
// Create the mail form object
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$formmail = new FormMail($db);
|
||||
$formmail->fromname = (GETPOSTISSET('fromname') ? GETPOST('fromname', 'restricthtml') : getDolGlobalString('MAIN_MAIL_EMAIL_FROM'));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2019-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -100,9 +100,9 @@ if ($action == 'up') {
|
|||
// Menu before
|
||||
$sql = "SELECT m.rowid, m.position";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
|
||||
$sql .= " WHERE (m.position < ".($current['order'])." OR (m.position = ".($current['order'])." AND rowid < ".GETPOSTINT("menuId")."))";
|
||||
$sql .= " WHERE (m.position < ".((int) $current['order'])." OR (m.position = ".((int) $current['order'])." AND rowid < ".GETPOSTINT("menuId")."))";
|
||||
$sql .= " AND m.menu_handler='".$db->escape($menu_handler_to_search)."'";
|
||||
$sql .= " AND m.entity = ".$conf->entity;
|
||||
$sql .= " AND m.entity = ".((int) $conf->entity);
|
||||
$sql .= " AND m.type = '".$db->escape($current['type'])."'";
|
||||
$sql .= " AND m.fk_menu = '".$db->escape((string) $current['fk_menu'])."'";
|
||||
$sql .= " ORDER BY m.position, m.rowid";
|
||||
|
|
@ -151,9 +151,9 @@ if ($action == 'up') {
|
|||
// Menu after
|
||||
$sql = "SELECT m.rowid, m.position";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
|
||||
$sql .= " WHERE (m.position > ".($current['order'])." OR (m.position = ".($current['order'])." AND rowid > ".GETPOSTINT("menuId")."))";
|
||||
$sql .= " WHERE (m.position > ".((int) $current['order'])." OR (m.position = ".((int) $current['order'])." AND rowid > ".GETPOSTINT("menuId")."))";
|
||||
$sql .= " AND m.menu_handler='".$db->escape($menu_handler_to_search)."'";
|
||||
$sql .= " AND m.entity = ".$conf->entity;
|
||||
$sql .= " AND m.entity = ".((int) $conf->entity);
|
||||
$sql .= " AND m.type = '".$db->escape($current['type'])."'";
|
||||
$sql .= " AND m.fk_menu = '".$db->escape((string) $current['fk_menu'])."'";
|
||||
$sql .= " ORDER BY m.position, m.rowid";
|
||||
|
|
@ -291,7 +291,7 @@ $data[] = array('rowid' => 0, 'fk_menu' => -1, 'title' => 'racine', 'mainmenu' =
|
|||
$sql = "SELECT m.rowid, m.titre, m.langs, m.mainmenu, m.leftmenu, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.position, m.module";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
|
||||
$sql .= " WHERE menu_handler = '".$db->escape($menu_handler_to_search)."'";
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
//$sql.= " AND fk_menu >= 0";
|
||||
$sql .= " ORDER BY m.position, m.rowid"; // Order is position then rowid (because we need a sort criteria when position is same)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
||||
* Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
|
||||
* Copyright (C) 2021-2026 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2026 Charlene Benke <charlene@patas-monkey.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -432,8 +432,7 @@ if ($action == 'install' && $allowonlineinstall) {
|
|||
'search_nature' => '-1',
|
||||
'search_version' => '-1'
|
||||
);
|
||||
$queryString = http_build_query($searchParams);
|
||||
$redirectUrl = DOL_URL_ROOT . '/admin/modules.php?' . $queryString;
|
||||
$redirectUrl = dolBuildUrl(DOL_URL_ROOT . '/admin/modules.php', $searchParams);
|
||||
|
||||
$message = $langs->trans("SetupIsReadyForUse", $redirectUrl, $langs->transnoentitiesnoconv("Home").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules"));
|
||||
|
||||
|
|
@ -1255,7 +1254,7 @@ if ($mode == 'common' || $mode == 'commonkanban') {
|
|||
}
|
||||
|
||||
$urltogo = $_SERVER["PHP_SELF"].'?id='.$objMod->numero.'&token='.newToken().'&module_position='.$module_position.'&action=set&token='.newToken().'&value='.$modName.'&mode='.$mode.$param;
|
||||
$popupWidth = 500;
|
||||
$popupWidth = 600;
|
||||
$popupHeight = 300;
|
||||
$codeenabledisable .= '<!-- Message to show: '.$warningmessage.' -->'."\n";
|
||||
$codeenabledisable .= '<a class="reposition" id="idqualified'.$objMod->numero.'" data-alreadyclicked="0" href="'.$urltogo.'"';
|
||||
|
|
@ -1307,7 +1306,7 @@ if ($mode == 'common' || $mode == 'commonkanban') {
|
|||
print '<a href="javascript:document_preview(\''.DOL_URL_ROOT.'/admin/modulehelp.php?id='.((int) $objMod->numero).'\',\'text/html\',\''.dol_escape_js($langs->trans("Module")).'\')">';
|
||||
print img_picto(($objMod->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule").' - ' : '').$langs->trans("ClickToShowDescription"), $imginfo, '', 0, 0, 0, '', 'purple');
|
||||
print '</a>';
|
||||
print ($timestoinit[$modName] > 500 ? img_picto($langs->trans('InitModuleIsSlow'), 'fa-exclamation-circle') : '');
|
||||
print($timestoinit[$modName] > 500 ? img_picto($langs->trans('InitModuleIsSlow'), 'fa-exclamation-circle') : '');
|
||||
print '</td>';
|
||||
|
||||
// Version
|
||||
|
|
@ -1492,11 +1491,11 @@ if ($mode == 'marketplace') {
|
|||
</div>
|
||||
<?php
|
||||
$totalnboflines = '<span class="product-count opacitymedium paddingleft">';
|
||||
$totalnboflines .= $langs->trans("itemFound", $remotestore->numberTotalOfProducts);
|
||||
$totalnboflines .= '</span>';
|
||||
$totalnboflines .= $langs->trans("itemFound", $remotestore->numberTotalOfProducts);
|
||||
$totalnboflines .= '</span>';
|
||||
|
||||
print $totalnboflines;
|
||||
print $remotestore->getPagination();
|
||||
print $totalnboflines;
|
||||
print $remotestore->getPagination();
|
||||
print '</form>';
|
||||
|
||||
print '</div>';
|
||||
|
|
|
|||
|
|
@ -24,12 +24,6 @@
|
|||
|
||||
// Load Dolibarr environment
|
||||
require '../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'adminaccoutant'; // To manage different context of search
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
* @var DoliDB $db
|
||||
|
|
@ -37,6 +31,11 @@ $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'ad
|
|||
* @var Translate $langs
|
||||
* @var User $user
|
||||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'adminaccoutant'; // To manage different context of search
|
||||
|
||||
// Load translation files required by the page
|
||||
$langs->loadLangs(array('admin', 'companies', 'other'));
|
||||
|
|
@ -105,8 +104,8 @@ $head = company_admin_prepare_head();
|
|||
|
||||
print dol_get_fiche_head($head, 'openinghours', '', -1, '');
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("OpeningHoursDesc")."</span><br>\n";
|
||||
print "<br><br>\n";
|
||||
print '<div class="info">'.$langs->trans("OpeningHoursDesc")."</div>\n";
|
||||
print "<br>\n";
|
||||
|
||||
if (empty($action) || $action == 'edit' || $action == 'updateedit') {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2004-2009 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2013 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -58,14 +58,14 @@ if (!$user->admin) {
|
|||
if ($action == 'add') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."rights_def SET bydefault=1";
|
||||
$sql .= " WHERE id = ".GETPOSTINT("pid");
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
if ($action == 'remove') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."rights_def SET bydefault=0";
|
||||
$sql .= " WHERE id = ".GETPOSTINT('pid');
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 2010-2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2019 Markus Welters <markus@welters.de>
|
||||
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -483,7 +483,7 @@ if (isModEnabled('notification') )
|
|||
$sql.= " ".MAIN_DB_PREFIX."c_action_trigger as ad";
|
||||
$sql.= " WHERE u.rowid = nd.fk_user";
|
||||
$sql.= " AND nd.fk_action = ad.rowid";
|
||||
$sql.= " AND u.entity IN (0,".$conf->entity.")";
|
||||
$sql.= " AND u.entity IN (0,".((int) $conf->entity).")";
|
||||
|
||||
$resql = $db->query($sql);
|
||||
if ($resql)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ require '../main.inc.php';
|
|||
* @var HookManager $hookmanager
|
||||
* @var Translate $langs
|
||||
* @var User $user
|
||||
*
|
||||
* @var string $dolibarr_main_restrict_os_commands
|
||||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (C) 2009 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
|
||||
* Copyright (C) 2020-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,7 +21,7 @@
|
|||
|
||||
/**
|
||||
* \file htdocs/admin/sms.php
|
||||
* \brief Page to setup emails sending
|
||||
* \brief Page to set up SMS sending
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
|
|
@ -267,12 +268,12 @@ if ($action == 'edit') {
|
|||
print '</div>';
|
||||
|
||||
|
||||
// Affichage formulaire de TEST simple
|
||||
// Display simple test form
|
||||
if ($action == 'test') {
|
||||
print '<br>';
|
||||
print load_fiche_titre($langs->trans("DoTestSend"));
|
||||
|
||||
// Cree l'objet formulaire mail
|
||||
// Create SMS form object
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formsms.class.php';
|
||||
$formsms = new FormSms($db);
|
||||
$formsms->fromtype = 'user';
|
||||
|
|
|
|||
|
|
@ -148,13 +148,11 @@ $head = company_admin_prepare_head();
|
|||
print dol_get_fiche_head($head, 'subcontractors', '', -1, '');
|
||||
|
||||
$form = new Form($db);
|
||||
$formother = new FormOther($db);
|
||||
$formcompany = new FormCompany($db);
|
||||
|
||||
$countrynotdefined = '<span class="error">'.$langs->trans("ErrorSetACountryFirst").' ('.$langs->trans("SeeAbove").')</span>';
|
||||
|
||||
print '<span class="opacitymedium">'.$langs->trans("SubcontractorsDesc")."</span><br>\n";
|
||||
print "<br><br>\n";
|
||||
print '<div class="info">'.$langs->trans("SubcontractorsDesc")."</div>\n";
|
||||
print "<br>\n";
|
||||
|
||||
/**
|
||||
* Edit parameters
|
||||
|
|
|
|||
|
|
@ -195,12 +195,12 @@ if (empty($conf->use_javascript_ajax)) {
|
|||
print $value_subtotal == 0 ? img_picto($langs->trans("Disabled"), 'switch_off') : img_picto($langs->trans("Enabled"), 'switch_on') . '</a>';
|
||||
print '</td>';
|
||||
|
||||
print '<td class="center">';
|
||||
print '<td class="center nowraponall">';
|
||||
$can_modify = !($value_subtotal == 0 && $value_title == 0);
|
||||
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '" >';
|
||||
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
||||
print '<input type="hidden" name="action" value="SUBTOTAL_' . $const . '_MAX_DEPTH">';
|
||||
print '<input size="3" type="text"';
|
||||
print '<input size="3" type="text" class="center"';
|
||||
print $can_modify ? '' : ' disabled="disabled" ';
|
||||
print 'name="SUBTOTAL_' . $const . '_MAX_DEPTH" value="' . getDolGlobalString('SUBTOTAL_' . $const . '_MAX_DEPTH', $can_modify ? 2 : 0) . '">';
|
||||
print $can_modify ? '<input type="submit" class="button button-edit reposition smallpaddingimp" name="Button"value="' . $langs->trans("Modify") . '">' : '';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
||||
* Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2009 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -231,11 +231,11 @@ $sql .= ", entity";
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."const";
|
||||
if (!isModEnabled('multicompany')) {
|
||||
// If no multicompany mode, admins can see global and their constantes
|
||||
$sql .= " WHERE entity IN (0,".$conf->entity.")";
|
||||
$sql .= " WHERE entity IN (0,".((int) $conf->entity).")";
|
||||
} else {
|
||||
// If multicompany mode, superadmin (user->entity=0) can see everything, admin are limited to their entities.
|
||||
if ($user->entity) {
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".((int) $conf->entity)).")";
|
||||
}
|
||||
}
|
||||
$sql .= " ORDER BY entity, name ASC";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
|
||||
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
|
||||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -67,7 +67,7 @@ if ($action == 'convertutf8') {
|
|||
while ($i < $num) {
|
||||
$row = $db->fetch_row($resql);
|
||||
if ($row[0] == $field) {
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." CHARACTER SET utf8"; // We must not sanitize the $row[1]
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." CHARACTER SET utf8"; // We must not sanitize the $row[1] @phan-suppress-current-line SqlInjection
|
||||
$logsql .= $sql.'<br>';
|
||||
|
||||
$db->query($sql);
|
||||
|
|
@ -78,7 +78,7 @@ if ($action == 'convertutf8') {
|
|||
$collation = 'utf8_general_ci';
|
||||
}
|
||||
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." COLLATE ".$db->sanitize($collation); // We must not sanitize the $row[1]
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." COLLATE ".$db->sanitize($collation); // We must not sanitize the $row[1] @phan-suppress-current-line SqlInjection
|
||||
$logsql .= $sql.'<br>';
|
||||
|
||||
$resql2 = $db->query($sql);
|
||||
|
|
@ -103,7 +103,7 @@ if ($action == 'convertutf8mb4') {
|
|||
while ($i < $num) {
|
||||
$row = $db->fetch_row($resql);
|
||||
if ($row[0] == $field) {
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." CHARACTER SET utf8mb4"; // We must not sanitize the $row[1]
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." CHARACTER SET utf8mb4"; // We must not sanitize the $row[1] @phan-suppress-current-line SqlInjection
|
||||
$logsql .= $sql.'<br>';
|
||||
|
||||
$db->query($sql);
|
||||
|
|
@ -114,7 +114,7 @@ if ($action == 'convertutf8mb4') {
|
|||
$collation = 'utf8mb4_general_ci';
|
||||
}
|
||||
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." COLLATE ".$db->sanitize($collation); // We must not sanitize the $row[1]
|
||||
$sql = "ALTER TABLE ".$db->sanitize($table)." MODIFY ".$db->sanitize($row[0])." ".$row[1]." COLLATE ".$db->sanitize($collation); // We must not sanitize the $row[1] @phan-suppress-current-line SqlInjection
|
||||
$logsql .= $sql.'<br>';
|
||||
|
||||
$resql2 = $db->query($sql);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/* Copyright (C) 2005-2020 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
||||
* Copyright (C) 2007-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -49,7 +49,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
|||
require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
|
||||
|
||||
// Load translation files required by the page
|
||||
$langs->loadLangs(array("install", "other", "admin"));
|
||||
$langs->loadLangs(array("blockedlog", "install", "other", "admin"));
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
|
||||
|
|
@ -595,11 +595,11 @@ $sql .= ", entity";
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."const";
|
||||
if (!isModEnabled('multicompany')) {
|
||||
// If no multicompany mode, admins can see global and their constantes
|
||||
$sql .= " WHERE entity IN (0,".$conf->entity.")";
|
||||
$sql .= " WHERE entity IN (0,".((int) $conf->entity).")";
|
||||
} else {
|
||||
// If multicompany mode, superadmin (user->entity=0) can see everything, admin are limited to their entities.
|
||||
if ($user->entity) {
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
|
||||
$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".((int) $conf->entity)).")";
|
||||
}
|
||||
}
|
||||
$sql .= " ORDER BY entity, name ASC";
|
||||
|
|
|
|||
|
|
@ -23,14 +23,11 @@
|
|||
|
||||
/**
|
||||
* \file htdocs/admin/system/phpinfo.php
|
||||
* \brief Page des infos systeme de php
|
||||
* \brief Page of PHP system information
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
* @var DoliDB $db
|
||||
|
|
@ -38,6 +35,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
|||
* @var Translate $langs
|
||||
* @var User $user
|
||||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
||||
|
||||
$langs->loadLangs(array("admin", "install", "errors"));
|
||||
|
||||
|
|
@ -154,6 +153,16 @@ print '<td class="titlefield">'.$langs->trans("Extension").'</td>';
|
|||
print '<td>'.$langs->trans("Test").'</td>';
|
||||
print '</tr>';
|
||||
|
||||
if ($db->type == 'mysqli') {
|
||||
$functions = ["mysqli_connect"];
|
||||
$name = "MySQLi";
|
||||
|
||||
print "<tr>";
|
||||
print "<td>".$name."</td>";
|
||||
print getResultColumn($name, $activatedExtensions, $loadedExtensions, $functions);
|
||||
print "</tr>";
|
||||
}
|
||||
|
||||
$functions = ["mb_check_encoding"];
|
||||
$name = "MBString";
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ $lowmemorydump = (int) (GETPOSTISSET("lowmemorydump") ? GETPOSTINT("lowmemorydum
|
|||
// MYSQL
|
||||
if ($what == 'mysql') {
|
||||
$cmddump = GETPOST("mysqldump", 'none'); // Do not sanitize here with 'alpha', will be sanitize later by dol_sanitizePathName and escapeshellarg
|
||||
$cmddump = dol_sanitizePathName($cmddump);
|
||||
$cmddump = dol_sanitizePathName($cmddump); // Sanitize path
|
||||
$cmddump = dol_string_nospecial($cmddump, '', array("|", ";", "<", ">", "&", "+")); // Sanitize command
|
||||
$basenamecmddump = basename(str_replace('\\', '/', $cmddump));
|
||||
|
||||
// Add a fallback when we detect something wrong with the path of the dump command
|
||||
|
|
@ -136,21 +137,12 @@ if ($what == 'mysql') {
|
|||
$reg = array();
|
||||
if (preg_match('/mysqldump(\.exe)?$/', $cmddump, $reg)) { // And if command ends with mysqldump
|
||||
$cmddump = 'mysqldump'.(empty($reg[1]) ? '' : $reg[1]); // Then we try the command with no forced path
|
||||
$langs->load("errors");
|
||||
setEventMessage($langs->trans("WarningFullPathWasNotFoundSoWeUseAnAlternativeValue", $cmddump), 'warnings');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($dolibarr_main_restrict_os_commands)) {
|
||||
$arrayofallowedcommand = explode(',', $dolibarr_main_restrict_os_commands);
|
||||
$arrayofallowedcommand = array_map('trim', $arrayofallowedcommand);
|
||||
dol_syslog("Command are restricted to ".$dolibarr_main_restrict_os_commands.". We check that one of this command is inside ".$cmddump);
|
||||
if (!in_array($basenamecmddump, $arrayofallowedcommand)) { // the provided command $cmddump must be an allowed command
|
||||
$langs->load("errors");
|
||||
$errormsg = $langs->trans('CommandIsNotInsideAllowedCommands');
|
||||
$errormsg .= '<br>'.$langs->trans('ErrorCheckTheCommandInsideTheAdvancedOptions');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errormsg && $cmddump) {
|
||||
dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump, 'chaine', 0, '', 0);
|
||||
}
|
||||
|
|
@ -177,6 +169,7 @@ if ($what == 'mysqlnobin') {
|
|||
if ($what == 'postgresql') {
|
||||
$cmddump = GETPOST("postgresqldump", 'none'); // Do not sanitize here with 'alpha', will be sanitize later by dol_sanitizePathName and escapeshellarg
|
||||
$cmddump = dol_sanitizePathName($cmddump);
|
||||
$cmddump = dol_string_nospecial($cmddump, '', array("|", ";", "<", ">", "&", "+")); // Sanitize command
|
||||
|
||||
/* Not required, the command is output on screen but not ran for pgsql
|
||||
if (!empty($dolibarr_main_restrict_os_commands))
|
||||
|
|
|
|||
|
|
@ -30,11 +30,6 @@ if (! defined('CSRFCHECK_WITH_TOKEN')) {
|
|||
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
* @var DoliDB $db
|
||||
|
|
@ -42,6 +37,10 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
|||
* @var Translate $langs
|
||||
* @var User $user
|
||||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
||||
|
||||
$langs->load("admin");
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2015 Bahfir Abbes <bafbes@gmail.com>
|
||||
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -178,7 +178,7 @@ if ($action == 'confirm_purge' && $confirm == 'yes' && $user->admin) {
|
|||
|
||||
// Delete events
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."events";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
$sql .= " WHERE entity = ".((int) $conf->entity);
|
||||
|
||||
dol_syslog("listevents purge", LOG_DEBUG);
|
||||
$resql = $db->query($sql);
|
||||
|
|
@ -224,7 +224,7 @@ $sql .= " u.login, u.admin, u.email, u.entity, u.firstname, u.lastname, u.gender
|
|||
$sql .= " FROM ".MAIN_DB_PREFIX."events as e";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = e.fk_user";
|
||||
if ($search_entity > 0) {
|
||||
$sql .= " WHERE e.entity = ".((int) $search_entity).")";
|
||||
$sql .= " WHERE e.entity = ".((int) $search_entity);
|
||||
} else {
|
||||
$sql .= " WHERE e.entity IN (".getEntity('event', (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ if ($savehandler == 'files') {
|
|||
print '<tr class="oddeven">';
|
||||
|
||||
// Login
|
||||
print '<td>'.$sessionentry['login'].'</td>';
|
||||
print '<td>'.dol_escape_htmltag($sessionentry['login']).'</td>';
|
||||
|
||||
// ID
|
||||
print '<td class="nowrap left">';
|
||||
|
|
@ -207,7 +207,7 @@ if ($savehandler == 'files') {
|
|||
print '<tr class="oddeven">';
|
||||
|
||||
// Login
|
||||
print '<td>'.$sessionentry['login'].'</td>';
|
||||
print '<td>'.dol_escape_htmltag($sessionentry['login']).'</td>';
|
||||
|
||||
// ID
|
||||
print '<td class="nowrap left">';
|
||||
|
|
@ -228,10 +228,10 @@ if ($savehandler == 'files') {
|
|||
print '<td>'.$sessionentry['age'].'</td>';
|
||||
|
||||
// Remote IP
|
||||
print '<td>'.$sessionentry['remote_ip'].'</td>';
|
||||
print '<td>'.dol_escape_htmltag((string) $sessionentry['remote_ip']).'</td>';
|
||||
|
||||
// User Agent
|
||||
print '<td class="nowrap left">'.$sessionentry['user_agent'].'</td>';
|
||||
print '<td class="nowrap left">'.dol_escape_htmltag((string) $sessionentry['user_agent']).'</td>';
|
||||
print '<td> </td>';
|
||||
print "</tr>\n";
|
||||
$i++;
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ if ($transvalue) {
|
|||
}
|
||||
|
||||
|
||||
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
|
||||
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" spellcheck="false">';
|
||||
if ($optioncss != '') {
|
||||
print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
|
|||
|
||||
// List of values
|
||||
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
|
||||
$sql .= $newid.",";
|
||||
$sql .= ((int) $newid).",";
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($listfieldinsert as $f => $value) {
|
||||
|
|
|
|||
|
|
@ -616,6 +616,15 @@ body.ai-fullpage {
|
|||
}
|
||||
|
||||
/* Input Field */
|
||||
#user-input::placeholder {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
#user-input::placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#user-input {
|
||||
flex-grow: 1;
|
||||
padding: 11px 15px;
|
||||
|
|
@ -744,7 +753,7 @@ body.ai-fullpage {
|
|||
}
|
||||
|
||||
/* Helpers */
|
||||
.hidden {
|
||||
.ai-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
|
@ -964,7 +973,7 @@ body.ai-fullpage {
|
|||
position: fixed;
|
||||
top: var(--ai-popover-top, 48px);
|
||||
right: 12px;
|
||||
width: 380px;
|
||||
width: 460px;
|
||||
height: min(560px, calc(100vh - var(--ai-popover-top, 48px) - 16px));
|
||||
z-index: 1010;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ export function initAiAssistant(container) {
|
|||
*/
|
||||
function updateInterfaceMode(mode) {
|
||||
// Reset all wrappers
|
||||
micWrapper.classList.add('hidden');
|
||||
uploadWrapper.classList.add('hidden');
|
||||
micWrapper.classList.add('ai-hidden');
|
||||
uploadWrapper.classList.add('ai-hidden');
|
||||
|
||||
if (mode === 'text') {
|
||||
input.placeholder = t('TypeYourQuestion');
|
||||
|
|
@ -184,13 +184,13 @@ export function initAiAssistant(container) {
|
|||
}
|
||||
else if (mode === 'cloud' || mode === 'whisper') {
|
||||
// Voice Modes
|
||||
micWrapper.classList.remove('hidden');
|
||||
micWrapper.classList.remove('ai-hidden');
|
||||
input.placeholder = 'Type or speak...';
|
||||
initEngine(mode);
|
||||
}
|
||||
else if (mode === 'local_docs' || mode === 'cloud_docs') {
|
||||
// Document Modes
|
||||
uploadWrapper.classList.remove('hidden');
|
||||
uploadWrapper.classList.remove('ai-hidden');
|
||||
input.placeholder = mode === 'local_docs'
|
||||
? t('UploadLocalDoc')
|
||||
: t('UploadCloudDoc');
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@ function getAiChatAssistantConfig()
|
|||
*/
|
||||
function getAiChatAssistantHtml($mode = 'page')
|
||||
{
|
||||
global $langs, $user;
|
||||
global $langs, $user, $conf;
|
||||
|
||||
$out = '';
|
||||
|
||||
|
|
@ -711,16 +711,20 @@ function getAiChatAssistantHtml($mode = 'page')
|
|||
$out .= '<div class="chat-controls">';
|
||||
$out .= '<div class="chat-input-pill">';
|
||||
// Upload Wrapper (Visible only in Doc modes)
|
||||
$out .= '<div id="upload-wrapper" class="upload-wrapper hidden">';
|
||||
$out .= '<div id="upload-wrapper" class="upload-wrapper ai-hidden">';
|
||||
$out .= '<input type="file" id="file-upload" accept=".pdf,.txt,.xml,.png,.jpg,.jpeg,.doc,.docx,.xls,.xlsx,.odt,.ods" style="display: none;">';
|
||||
$out .= '<button type="button" id="upload-btn" class="round-btn" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("AttachFile")).'">'.img_picto('', 'fa-paperclip').'</button>';
|
||||
$out .= '</div>';
|
||||
// Microphone Wrapper (Visible only in Voice modes)
|
||||
$out .= '<div id="mic-wrapper" class="mic-wrapper hidden">';
|
||||
$out .= '<div id="mic-wrapper" class="mic-wrapper ai-hidden">';
|
||||
$out .= '<button type="button" id="mic-btn" class="round-btn mic-btn" title="'.dol_escape_htmltag($langs->trans("ToggleMicrophone")).'">'.img_picto('', 'fa-microphone').'</button>';
|
||||
$out .= '</div>';
|
||||
// Text Input
|
||||
$out .= '<textarea id="user-input" class="ia-input" rows="1" placeholder="'.dol_escape_htmltag($langs->trans("TypeYourQuestion")).'" autocomplete="off" spellcheck="false"></textarea>';
|
||||
$out .= '<textarea id="user-input" class="ia-input" rows="1"';
|
||||
if (empty($conf->dol_optimize_smallscreen)) {
|
||||
$out .= ' placeholder="'.dol_escape_htmltag($langs->trans("TypeYourQuestion")).'"';
|
||||
}
|
||||
$out .= ' autocomplete="off" spellcheck="false"></textarea>';
|
||||
// Send Button
|
||||
$out .= '<button type="button" id="send-btn" class="chat-send-btn" title="'.dol_escape_htmltag($langs->trans("SendPrompt")).'">'.img_picto('', 'fa-paper-plane').'</button>';
|
||||
$out .= '</div>';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2026 Nick Fragoulis
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -131,6 +132,14 @@ if ($userId > 0) {
|
|||
|
||||
if ($result > 0) {
|
||||
$serviceUser->loadRights();
|
||||
// Promote the service user to the global $user so MCP tools that
|
||||
// legitimately rely on the `global $user` pattern (Dolibarr core
|
||||
// convention) see an authenticated user. Without this, there is
|
||||
// no PHP web session in HTTP MCP context and any tool reading
|
||||
// `global $user` would treat the request as unauthenticated even
|
||||
// though authentication via X-API-Key/Bearer succeeded above.
|
||||
global $user;
|
||||
$user = $serviceUser;
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ class ToolCategories extends McpTool
|
|||
* Executes the requested tool function based on its name.
|
||||
*
|
||||
* @param string $name The name of the tool to execute.
|
||||
* @param array<string, mixed> $args The arguments for the tool (key-value pairs).
|
||||
* @param array<string, mixed> $args The arguments for the tool (key-value pairs). Only SQL safe arguments!
|
||||
* @return mixed The result of the tool execution (usually an array) or an error array.
|
||||
*/
|
||||
public function execute(string $name, array $args)
|
||||
|
|
@ -406,6 +406,8 @@ class ToolCategories extends McpTool
|
|||
/**
|
||||
* Searches for categories based on a query and type.
|
||||
*
|
||||
* Note: Only call with sql safe parameters
|
||||
*
|
||||
* @param array<string, mixed> $args Array containing 'query' (string), 'scope' (string), 'limit' (int), 'offset' (int).
|
||||
* @return array{error:string}|array{count:int}|list<array<string, mixed>> A list of found categories or an error array.
|
||||
*/
|
||||
|
|
@ -442,9 +444,9 @@ class ToolCategories extends McpTool
|
|||
$sql .= " WHERE c.entity IN (" . getEntity('category') . ")";
|
||||
|
||||
if (!empty($query)) {
|
||||
$query_lower = strtolower($query);
|
||||
$sqlSearchText = $this->db->escape(strtolower($query));
|
||||
|
||||
$sql .= " AND (LOWER(c.label) LIKE '%" . $this->db->escape($query_lower) . "%' OR LOWER(c.description) LIKE '%" . $this->db->escape($query_lower) . "%')";
|
||||
$sql .= " AND (LOWER(c.label) LIKE '%" . $sqlSearchText . "%' OR LOWER(c.description) LIKE '%" . $sqlSearchText . "%')";
|
||||
}
|
||||
|
||||
if (!empty($scope_filter)) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2026 Nick Fragoulis
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -37,11 +38,22 @@ class ToolCrudObjects extends McpTool
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Aligned with McpHandler's instantiation contract: new $className($db, $user, $conf).
|
||||
* Accepting $user via DI allows this tool to work in HTTP MCP context where no PHP
|
||||
* web session exists. Some sibling tool classes (ToolThirdParty, ToolCategories,
|
||||
* ToolProducts) already use this signature; this aligns ToolCrudObjects with them.
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
* @param User|null $user Service user provided by McpHandler (from AI_MCP_USER_ID)
|
||||
* @param Conf|null $conf Dolibarr config (optional)
|
||||
*/
|
||||
public function __construct(DoliDB $db)
|
||||
public function __construct(DoliDB $db, $user = null, $conf = null)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
if ($conf !== null) {
|
||||
$this->conf = $conf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -322,13 +334,20 @@ If user says 'order' without any qualifier, they mean a SALES ORDER - use this t
|
|||
*/
|
||||
public function execute(string $name, array $args)
|
||||
{
|
||||
global $user, $langs, $conf, $mysoc;
|
||||
global $langs, $conf, $mysoc;
|
||||
|
||||
// Ensure $this->user is the authenticated global user
|
||||
$this->user = $user;
|
||||
|
||||
if (!$user->id) {
|
||||
return ["error" => "User not authenticated."];
|
||||
// Use the user injected via constructor (McpHandler). Fall back to global $user
|
||||
// when running in a web session context (e.g. AI Assistant) where DI is not used.
|
||||
// is_object() is used instead of empty() because the parent McpTool declares $user
|
||||
// with a non-nullable type hint, which makes PHPStan flag empty($this->user) as
|
||||
// unreachable code.
|
||||
if (!is_object($this->user) || empty($this->user->id)) {
|
||||
global $user;
|
||||
if (is_object($user) && !empty($user->id)) {
|
||||
$this->user = $user;
|
||||
} else {
|
||||
return ["error" => "User not authenticated."];
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_object($mysoc) || empty($mysoc->id)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2026 Nick Fragoulis
|
||||
* Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -40,11 +41,36 @@ class ToolInvoices extends McpTool
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Aligned with McpHandler's instantiation contract: new $className($db, $user, $conf).
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
* @param User|null $user Service user provided by McpHandler (from AI_MCP_USER_ID)
|
||||
* @param Conf|null $conf Dolibarr config (optional)
|
||||
*/
|
||||
public function __construct(DoliDB $db)
|
||||
public function __construct(DoliDB $db, $user = null, $conf = null)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
if ($conf !== null) {
|
||||
$this->conf = $conf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authenticated user, preferring DI ($this->user) and falling back to global $user.
|
||||
* In HTTP MCP context there is no PHP web session — only the service user injected via DI.
|
||||
*
|
||||
* @return User|null
|
||||
*/
|
||||
private function getUser()
|
||||
{
|
||||
// is_object() instead of empty() to avoid PHPStan flagging empty() on a
|
||||
// non-nullable typed parent property as unreachable.
|
||||
if (is_object($this->user) && !empty($this->user->id)) {
|
||||
return $this->user;
|
||||
}
|
||||
global $user;
|
||||
return is_object($user) && !empty($user->id) ? $user : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -312,7 +338,10 @@ class ToolInvoices extends McpTool
|
|||
*/
|
||||
private function validateInvoice($args)
|
||||
{
|
||||
global $user;
|
||||
$user = $this->getUser();
|
||||
if ($user === null) {
|
||||
return ["error" => "User not authenticated."];
|
||||
}
|
||||
$invoice = $this->findInvoice($args['invoice']);
|
||||
if (is_array($invoice)) {
|
||||
return $invoice;
|
||||
|
|
@ -351,7 +380,10 @@ class ToolInvoices extends McpTool
|
|||
*/
|
||||
private function payInvoice($args)
|
||||
{
|
||||
global $user;
|
||||
$user = $this->getUser();
|
||||
if ($user === null) {
|
||||
return ["error" => "User not authenticated."];
|
||||
}
|
||||
$invoice = $this->findInvoice($args['invoice']);
|
||||
if (is_array($invoice)) {
|
||||
return $invoice;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2026 Nick Fragoulis
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -134,25 +135,25 @@ class ToolNavigation extends McpTool
|
|||
}
|
||||
|
||||
// Build Query Parameters
|
||||
$queryParams = [];
|
||||
$getQueryParams = [];
|
||||
|
||||
// Handle Action/ID logic
|
||||
if ($id > 0) {
|
||||
$queryParams['id'] = $id;
|
||||
$getQueryParams['id'] = $id;
|
||||
} elseif (!empty($ref)) {
|
||||
$queryParams['ref'] = $ref;
|
||||
$getQueryParams['ref'] = $ref;
|
||||
}
|
||||
|
||||
// Set action for create view
|
||||
if ($view === 'create') {
|
||||
$queryParams['action'] = 'create';
|
||||
$getQueryParams['action'] = 'create';
|
||||
}
|
||||
|
||||
// Handle Status Filtering
|
||||
if ($view === 'list' && !empty($statusFilter)) {
|
||||
$statusParam = $this->mapStatusToFilter($elementType, $statusFilter);
|
||||
if ($statusParam) {
|
||||
$queryParams = array_merge($queryParams, $statusParam);
|
||||
$getQueryParams = array_merge($getQueryParams, $statusParam);
|
||||
} else {
|
||||
return ["error" => "Unknown status filter '$statusFilter' for object type '$rawType'."];
|
||||
}
|
||||
|
|
@ -162,15 +163,15 @@ class ToolNavigation extends McpTool
|
|||
|
||||
// Merge extra params
|
||||
if (!empty($params) && is_array($params)) {
|
||||
$queryParams = array_merge($queryParams, $params);
|
||||
$getQueryParams = array_merge($getQueryParams, $params);
|
||||
}
|
||||
|
||||
// Generate Native URL
|
||||
$baseUrl = dol_buildpath($relativePath, 1);
|
||||
|
||||
$finalUrl = $baseUrl;
|
||||
if (!empty($queryParams)) {
|
||||
$finalUrl .= '?' . http_build_query($queryParams);
|
||||
if (!empty($getQueryParams)) {
|
||||
$finalUrl .= '?' . http_build_query($getQueryParams);
|
||||
}
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2026 Nick Fragoulis
|
||||
* Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
|
||||
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -36,15 +38,22 @@ require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
|
|||
*/
|
||||
class ToolReports extends McpTool
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Aligned with McpHandler's instantiation contract: new $className($db, $user, $conf).
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
* @param User|null $user Service user provided by McpHandler (from AI_MCP_USER_ID)
|
||||
* @param Conf|null $conf Dolibarr config (optional)
|
||||
*/
|
||||
public function __construct(DoliDB $db)
|
||||
public function __construct(DoliDB $db, $user = null, $conf = null)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
if ($conf !== null) {
|
||||
$this->conf = $conf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -204,10 +213,10 @@ class ToolReports extends McpTool
|
|||
}
|
||||
|
||||
if (!empty($args['thirdparty_name'])) {
|
||||
$name = $this->db->escape($args['thirdparty_name']);
|
||||
$sqlName = $this->db->escape($args['thirdparty_name']);
|
||||
|
||||
$sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe
|
||||
WHERE nom LIKE '%" . $name . "%'
|
||||
WHERE nom LIKE '%" . $sqlName . "%'
|
||||
AND entity IN (" . getEntity('societe') . ")
|
||||
LIMIT 1";
|
||||
|
||||
|
|
@ -379,11 +388,11 @@ class ToolReports extends McpTool
|
|||
return [[$langs->transnoentitiesnoconv("Error") => $langs->transnoentitiesnoconv("ErrorThirdPartyNotFound")]];
|
||||
}
|
||||
|
||||
$queries = [];
|
||||
$sqlQueries = [];
|
||||
|
||||
// Invoices
|
||||
if ($type == 'all' || $type == 'invoices') {
|
||||
$queries[] = "SELECT 'Invoice' as source_type, rowid, ref, total_ttc as amount, datef as date_entry, fk_statut
|
||||
$sqlQueries[] = "SELECT 'Invoice' as source_type, rowid, ref, total_ttc as amount, datef as date_entry, fk_statut
|
||||
FROM " . MAIN_DB_PREFIX . "facture
|
||||
WHERE fk_soc = " . (int) $socid . " AND entity IN (" . getEntity('facture') . ")
|
||||
AND fk_statut IN (1, 2)";
|
||||
|
|
@ -391,7 +400,7 @@ class ToolReports extends McpTool
|
|||
|
||||
// Orders
|
||||
if ($type == 'all' || $type == 'orders') {
|
||||
$queries[] = "SELECT 'Order' as source_type, rowid, ref, total_ttc as amount, date_commande as date_entry, fk_statut
|
||||
$sqlQueries[] = "SELECT 'Order' as source_type, rowid, ref, total_ttc as amount, date_commande as date_entry, fk_statut
|
||||
FROM " . MAIN_DB_PREFIX . "commande
|
||||
WHERE fk_soc = " . (int) $socid . " AND entity IN (" . getEntity('commande') . ")
|
||||
AND fk_statut > 0";
|
||||
|
|
@ -399,18 +408,18 @@ class ToolReports extends McpTool
|
|||
|
||||
// Proposals
|
||||
if ($type == 'all' || $type == 'proposals') {
|
||||
$queries[] = "SELECT 'Proposal' as source_type, rowid, ref, total_ttc as amount, datep as date_entry, fk_statut
|
||||
$sqlQueries[] = "SELECT 'Proposal' as source_type, rowid, ref, total_ttc as amount, datep as date_entry, fk_statut
|
||||
FROM " . MAIN_DB_PREFIX . "propal
|
||||
WHERE fk_soc = " . (int) $socid . " AND entity IN (" . getEntity('propal') . ")
|
||||
AND fk_statut > 0";
|
||||
}
|
||||
|
||||
if (empty($queries)) {
|
||||
if (empty($sqlQueries)) {
|
||||
return [[$langs->transnoentitiesnoconv("Error") => "Invalid transaction type"]];
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM (";
|
||||
$sql .= implode(" UNION ", $queries);
|
||||
$sql .= implode(" UNION ", $sqlQueries);
|
||||
$sql .= ") as combined_transactions ";
|
||||
$whereParts = [];
|
||||
if ($dateStart > 0) {
|
||||
|
|
|
|||
|
|
@ -29,10 +29,6 @@
|
|||
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/api.lib.php';
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
* @var DoliDB $db
|
||||
|
|
@ -46,6 +42,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/api.lib.php';
|
|||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/api.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
|
||||
// Load translation files required by the page
|
||||
$langs->load("admin");
|
||||
|
|
@ -136,7 +135,7 @@ print '<table class="noborder centpercent">';
|
|||
|
||||
print '<tr class="liste_titre">';
|
||||
print "<td>".$langs->trans("Parameter")."</td>";
|
||||
print '<td>'.$langs->trans("Value")."</td>";
|
||||
print '<td></td>';
|
||||
print "<td> </td>";
|
||||
print "</tr>";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 2016 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2023 Romain Neil <contact@romain-neil.fr>
|
||||
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
||||
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
|
||||
* Copyright (C) 2025 William Mead <william@m34d.com>
|
||||
* Copyright (C) 2025-2026 Charlene Benke <charlene@patas-monkey.com>
|
||||
*
|
||||
|
|
@ -50,7 +50,7 @@ class Documents extends DolibarrApi
|
|||
|
||||
|
||||
/**
|
||||
* Download a document
|
||||
* Download a given document
|
||||
*
|
||||
* Note that, this API is similar to using the wrapper link "documents.php" to download a file (used for
|
||||
* internal HTML links of documents into application), but with no need to have a session cookie (the token is used instead).
|
||||
|
|
@ -432,7 +432,7 @@ class Documents extends DolibarrApi
|
|||
}
|
||||
|
||||
/**
|
||||
* List documents of an element
|
||||
* List all documents of an element
|
||||
*
|
||||
* Use element ID or Ref.
|
||||
* Supported modules: thirdparty, user, member, proposal, order, supplier_order, shipment, invoice, supplier_invoice, product, event, expensereport, knowledgemanagement, category, contract, project, project_task
|
||||
|
|
@ -449,22 +449,19 @@ class Documents extends DolibarrApi
|
|||
* @param string $content_type Filter on content-type (example 'application/pdf' or 'application/pdf,image/jpeg'))
|
||||
* @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*
|
||||
* @return array Array of documents with path
|
||||
* @phan-return array<array<string,int|string>>
|
||||
* @phan-return array{data:array<mixed,array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string}>,pagination:array{total:int,page:int,page_count:int,limit:int}}|array<mixed,array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string}>
|
||||
* @phpstan-return array<array<string,int|string>>
|
||||
*
|
||||
* @url GET /
|
||||
*
|
||||
* @throws RestException 400 Bad value for parameter modulepart, id or ref
|
||||
* @throws RestException 403 Access denied
|
||||
* @throws RestException 404 Thirdparty, User, Member, Order, Invoice or Proposal not found
|
||||
* @throws RestException 404 Object (Thirdparty, User, Member, Order, Invoice, Proposal...) not found
|
||||
* @throws RestException 500 Error while fetching object
|
||||
* @throws RestException 503 Error when retrieve ecm list
|
||||
* @throws RestException 503 Error when retrieving ecm list
|
||||
*/
|
||||
public function getDocumentsListByElement($modulepart, $id = 0, $ref = '', $sortfield = '', $sortorder = '', $limit = 100, $page = 0, $content_type = '', $pagination_data = false)
|
||||
{
|
||||
global $conf;
|
||||
/** @var Conf $conf */
|
||||
|
||||
if (empty($modulepart)) {
|
||||
throw new RestException(400, 'bad value for parameter modulepart');
|
||||
}
|
||||
|
|
@ -474,372 +471,155 @@ class Documents extends DolibarrApi
|
|||
}
|
||||
|
||||
$id = (empty($id) ? 0 : $id);
|
||||
$recursive = 0;
|
||||
$type = 'files';
|
||||
|
||||
|
||||
// Define $object
|
||||
$object = fetchObjectByElement($id, $modulepart, $ref);
|
||||
if (!is_object($object)) {
|
||||
throw new RestException(404, 'Object with (id, ref) = ('.$id.', '.$ref.') not found or not allowed for modulepart = '.$modulepart);
|
||||
}
|
||||
|
||||
// Define $upload_dir to scan
|
||||
$upload_dir = getMultidirOutput($object, '', 1);
|
||||
|
||||
// Check object-level permissions
|
||||
$ok = checkUserAccessToObject(DolibarrApiAccess::$user, array($object->element), $object, $object->table_element, '');
|
||||
if (empty($ok)) {
|
||||
throw new RestException(403, 'Access not allowed to this object (refused by checkUserAccessToObject)');
|
||||
}
|
||||
|
||||
// Check permission on module
|
||||
if ($modulepart == 'societe' || $modulepart == 'thirdparty') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Societe($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Thirdparty not found');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->societe->multidir_output[$object->entity ?? $conf->entity]."/".$object->id;
|
||||
} elseif ($modulepart == 'user') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
|
||||
|
||||
// Can get doc if has permission to read all user or if it is user itself
|
||||
if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'lire') && DolibarrApiAccess::$user->id != $id) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new User($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'User not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/'.get_exdir(0, 0, 0, 0, $object, 'user').'/'.$object->id;
|
||||
} elseif ($modulepart == 'adherent' || $modulepart == 'member') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Adherent($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Member not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/".get_exdir(0, 0, 0, 1, $object, 'member');
|
||||
} elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('propal', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Propal($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Proposal not found');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
|
||||
} elseif ($modulepart == 'supplier_proposal') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('supplier_proposal', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Propal($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Supplier proposal not found');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
|
||||
} elseif ($modulepart == 'commande' || $modulepart == 'order') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Commande($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Order not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object). "/".get_exdir(0, 0, 0, 1, $object, 'commande');
|
||||
} elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
|
||||
$modulepart = 'supplier_order';
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'commande', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_order', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new CommandeFournisseur($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Purchase order not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/commande/".dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'shipment' || $modulepart == 'expedition') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Expedition($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Shipment not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
|
||||
} elseif ($modulepart == 'facture' || $modulepart == 'invoice') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Facture($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Invoice not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/".get_exdir(0, 0, 0, 1, $object, 'invoice');
|
||||
} elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
|
||||
$modulepart = 'supplier_invoice';
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'facture', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_invoice', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new FactureFournisseur($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Invoice not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/".get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').dol_sanitizeFileName($object->ref);
|
||||
} elseif ($modulepart == 'produit' || $modulepart == 'product' || $modulepart == 'service') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('produit', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Product($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if ($result == 0) {
|
||||
throw new RestException(404, 'Product not found');
|
||||
} elseif ($result < 0) {
|
||||
throw new RestException(500, 'Error while fetching object: '.$object->error);
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event' || $modulepart == 'actioncomm') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('agenda', 'myactions', 'read') && !DolibarrApiAccess::$user->hasRight('agenda', 'allactions', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new ActionComm($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Event not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'expensereport') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('expensereport', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new ExpenseReport($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Expense report not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'holiday') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('holiday', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Holiday($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Holiday not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'ticket') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('ticket', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Ticket($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Ticket not found');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->ticket->dir_output.'/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'knowledgemanagement') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new KnowledgeRecord($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'KM article not found');
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . '/knowledgerecord/'.dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'categorie' || $modulepart == 'category') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Categorie($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Category not found');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->categorie->multidir_output[$object->entity ?? $conf->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'category').$object->id."/photos/".dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'ecm') {
|
||||
throw new RestException(500, 'Modulepart Ecm not implemented yet.');
|
||||
// require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
|
||||
|
||||
// if (!DolibarrApiAccess::$user->hasRight('ecm', 'read')) {
|
||||
// throw new RestException(403);
|
||||
// }
|
||||
|
||||
// // $object = new EcmDirectory($this->db);
|
||||
// // $result = $object->fetch($ref);
|
||||
// // if (!$result) {
|
||||
// // throw new RestException(404, 'EcmDirectory not found');
|
||||
// // }
|
||||
// $upload_dir = $conf->ecm->dir_output;
|
||||
// $type = 'all';
|
||||
// $recursive = 0;
|
||||
} elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
|
||||
$modulepart = 'contrat';
|
||||
require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
|
||||
|
||||
$object = new Contrat($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contract not found');
|
||||
if (!DolibarrApiAccess::$user->hasRight('contrat', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/" . get_exdir(0, 0, 0, 1, $object, 'contract');
|
||||
} elseif ($modulepart == 'intervention' || $modulepart == 'ficheinter') {
|
||||
$modulepart = 'ficheinter';
|
||||
require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
|
||||
|
||||
$object = new Fichinter($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Interventional not found');
|
||||
if (!DolibarrApiAccess::$user->hasRight('ficheinter', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$upload_dir = $conf->ficheinter->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'ficheinter');
|
||||
} elseif ($modulepart == 'projet' || $modulepart == 'project') {
|
||||
$modulepart = 'project';
|
||||
require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
|
||||
|
||||
$object = new Project($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Project not found');
|
||||
}
|
||||
$upload_dir = $conf->project->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'project');
|
||||
} elseif ($modulepart == 'task' || $modulepart == 'project_task') {
|
||||
$modulepart = 'project_task';
|
||||
require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Task($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Task not found');
|
||||
} elseif ($modulepart == 'task' || $modulepart == 'project_task') {
|
||||
$modulepart = 'project_task';
|
||||
if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
// Fetch the project to build the correct path
|
||||
$project_result = $object->fetchProject();
|
||||
if ($project_result < 0) {
|
||||
throw new RestException(500, 'Error while fetching project for task');
|
||||
}
|
||||
|
||||
$upload_dir = $conf->project->dir_output . "/" . dol_sanitizeFileName((string) $object->project->ref) . "/" . dol_sanitizeFileName((string) $object->ref);
|
||||
} elseif ($modulepart == 'mrp') {
|
||||
$modulepart = 'mrp';
|
||||
require_once DOL_DOCUMENT_ROOT . '/mrp/class/mo.class.php';
|
||||
|
||||
$object = new Mo($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'MO not found');
|
||||
if (!DolibarrApiAccess::$user->hasRight('mrp', 'read')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$upload_dir = getMultidirOutput($object) . "/" . get_exdir(0, 0, 0, 1, $object, 'mrp');
|
||||
} elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
|
||||
$modulepart = 'contact';
|
||||
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
|
||||
|
||||
$object = new Contact($this->db);
|
||||
$result = $object->fetch($id?$id:$ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Contact not found');
|
||||
if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
$upload_dir = $conf->societe->multidir_output[$object->entity ?? $conf->entity] . "/contact/" . get_exdir(0, 0, 0, 1, $object, 'contact');
|
||||
} elseif ($modulepart == 'stock') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
|
||||
|
||||
if (!DolibarrApiAccess::$user->hasRight('stock', 'lire')) {
|
||||
throw new RestException(403);
|
||||
}
|
||||
|
||||
$object = new Entrepot($this->db);
|
||||
$result = $object->fetch($id, $ref);
|
||||
if (!$result) {
|
||||
throw new RestException(404, 'Warehouse not found');
|
||||
}
|
||||
$upload_dir = $conf->stock->multidir_output[$object->entity ?? $conf->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'stock');
|
||||
} else {
|
||||
throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
|
||||
}
|
||||
|
||||
// Scan files into directory
|
||||
$recursive = 0;
|
||||
$type = 'files';
|
||||
|
||||
$objectType = $modulepart;
|
||||
if (! empty($object->id) && ! empty($object->table_element)) {
|
||||
$objectType = $object->table_element;
|
||||
}
|
||||
|
||||
$filearray = dol_dir_list($upload_dir, $type, $recursive, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ? SORT_DESC : SORT_ASC), 1);
|
||||
$countarray = count($filearray);
|
||||
$filearray = array_slice($filearray, $limit * $page, $limit);
|
||||
|
||||
$countarray = is_array($filearray) ? count($filearray) : 0;
|
||||
|
||||
if (empty($filearray)) {
|
||||
throw new RestException(404, 'Search for modulepart '.$modulepart.' with Id '.$object->id.(!empty($object->ref) ? ' or Ref '.$object->ref : '').' does not return any document.');
|
||||
} else {
|
||||
$filearray = array_slice($filearray, $limit * $page, $limit);
|
||||
if (($object->id) > 0 && !empty($modulepart)) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
|
||||
$ecmfile = new EcmFiles($this->db);
|
||||
|
|
@ -847,36 +627,63 @@ class Documents extends DolibarrApi
|
|||
if ($result < 0) {
|
||||
throw new RestException(503, 'Error when retrieve ecm list : '.$this->db->lasterror());
|
||||
} elseif (is_array($ecmfile->lines) && count($ecmfile->lines) > 0) {
|
||||
$count = count($filearray);
|
||||
for ($i = 0 ; $i < $count ; $i++) {
|
||||
foreach ($filearray as &$fileitem) {
|
||||
foreach ($ecmfile->lines as $line) {
|
||||
unset($line->db);
|
||||
if ($filearray[$i]['name'] == $line->filename) {
|
||||
if ($fileitem['name'] == $line->filename) {
|
||||
// Next line converts EcmFilesLine properties to array
|
||||
$filearray[$i] = array_merge($filearray[$i], (array) $line);
|
||||
//$fileitem = array_merge($fileitem, (array) $line);
|
||||
$fileitem['ref'] = $line->ref;
|
||||
$fileitem['label'] = $line->label;
|
||||
$fileitem['filepath'] = $line->filepath;
|
||||
$fileitem['filename'] = $line->filename;
|
||||
$fileitem['fullpath_orig'] = $line->fullpath_orig;
|
||||
$fileitem['position'] = $line->position;
|
||||
$fileitem['gen_or_uploaded'] = $line->gen_or_uploaded;
|
||||
$fileitem['description'] = $line->desc;
|
||||
$fileitem['keywords'] = $line->keywords;
|
||||
$fileitem['cover'] = $line->cover;
|
||||
$fileitem['share'] = $line->share;
|
||||
$fileitem['date_c'] = $line->date_c;
|
||||
$fileitem['agenda_id'] = $line->agenda_id;
|
||||
$fileitem['fk_user_c'] = $line->fk_user_c;
|
||||
$fileitem['fk_user_m'] = $line->fk_user_m;
|
||||
$fileitem['note_private'] = $line->note_private;
|
||||
$fileitem['note_public'] = $line->note_public;
|
||||
}
|
||||
}
|
||||
if (isset($filearray[$i]['relativename'])) $filearray[$i]['content-type'] = dol_mimetype($filearray[$i]['relativename']);
|
||||
$arraycontenttype = explode(",", $content_type);
|
||||
if (!empty($content_type) && isset($filearray[$i]['relativename']) && !in_array(dol_mimetype($filearray[$i]['relativename']), $arraycontenttype)) {
|
||||
unset($filearray[$i]);
|
||||
$countarray -= 1;
|
||||
if (isset($fileitem['relativename'])) {
|
||||
$fileitem['content-type'] = dol_mimetype((string) $fileitem['relativename']);
|
||||
}
|
||||
}
|
||||
|
||||
// Select only files that match the requested $content_type, if provided
|
||||
$arraycontenttype = explode(",", $content_type);
|
||||
if (!empty($arraycontenttype)) {
|
||||
$filearray = array_filter(
|
||||
$filearray,
|
||||
/**
|
||||
* @param array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,content-type?:string} $fileitem Item to check for content type (for filtering)
|
||||
* @return bool True if file matches a content type
|
||||
*/
|
||||
static function ($fileitem) use (&$arraycontenttype) {
|
||||
return in_array(($fileitem['content-type'] ?: 'UNKNOWN'), $arraycontenttype);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
|
||||
if ($pagination_data) {
|
||||
$tmp = $filearray;
|
||||
$filearray = [];
|
||||
$filearray['data'] = $tmp;
|
||||
$filearray['pagination'] = [
|
||||
'total' => (int) $countarray,
|
||||
'page' => $page, //count starts from 0
|
||||
'page_count' => ceil((int) $countarray / $limit),
|
||||
'limit' => $limit
|
||||
$filearray = [
|
||||
'data' => $filearray,
|
||||
'pagination' => [
|
||||
'total' => (int) $countarray,
|
||||
'page' => $page, // count starts from 0
|
||||
'page_count' => (int) ceil((int) $countarray / $limit),
|
||||
'limit' => $limit
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -1043,12 +850,12 @@ class Documents extends DolibarrApi
|
|||
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
|
||||
$object = new Societe($this->db);
|
||||
$fetchbyid = true;
|
||||
} elseif ($modulepart == 'knowledgemanagement' ) {
|
||||
} elseif ($modulepart == 'knowledgemanagement') {
|
||||
$modulepart = 'knowledgemanagement';
|
||||
require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
|
||||
$object = new KnowledgeRecord($this->db);
|
||||
$fetchbyid = true;
|
||||
} elseif ($modulepart == 'ticket' ) {
|
||||
} elseif ($modulepart == 'ticket') {
|
||||
$modulepart = 'ticket';
|
||||
require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
|
||||
$object = new Ticket($this->db);
|
||||
|
|
@ -1104,6 +911,9 @@ class Documents extends DolibarrApi
|
|||
$relativefile = $tmpreldir.dol_sanitizeFileName((string) $object->ref);
|
||||
}
|
||||
$tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, $ref, 'write');
|
||||
if (empty($tmp['accessallowed'])) {
|
||||
throw new RestException(403, 'Access not allowed to upload file into this directory');
|
||||
}
|
||||
$upload_dir = $tmp['original_file']; // No dirname here, tmp['original_file'] is already the dir because dol_check_secure_access_document was called with param original_file that is only the dir
|
||||
/*} else {
|
||||
if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
|
||||
|
|
@ -1127,6 +937,9 @@ class Documents extends DolibarrApi
|
|||
if ($modulepart != 'ecm') {
|
||||
$relativefile = $subdir;
|
||||
$tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
|
||||
if (empty($tmp['accessallowed'])) {
|
||||
throw new RestException(403, 'Access not allowed to upload file into this directory');
|
||||
}
|
||||
$upload_dir = $tmp['original_file']; // No dirname here, tmp['original_file'] is already the dir because dol_check_secure_access_document was called with param original_file that is only the dir
|
||||
} else {
|
||||
if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
|
||||
|
|
|
|||
|
|
@ -87,9 +87,9 @@ class EmailTemplates extends DolibarrApi
|
|||
*/
|
||||
public function deleteById($id)
|
||||
{
|
||||
$allowaccess = $this->_checkAccessRights('lire');
|
||||
$allowaccess = $this->_checkAccessRights('supprimer');
|
||||
if (!$allowaccess) {
|
||||
throw new RestException(403, 'denied read access to email templates');
|
||||
throw new RestException(403, 'denied delete access to email templates');
|
||||
}
|
||||
|
||||
$result = $this->email_template->apifetch($id, '');
|
||||
|
|
@ -123,11 +123,11 @@ class EmailTemplates extends DolibarrApi
|
|||
* @throws RestException 404
|
||||
* @throws RestException 500
|
||||
*/
|
||||
public function deleteByLAbel($label)
|
||||
public function deleteByLabel($label)
|
||||
{
|
||||
$allowaccess = $this->_checkAccessRights('lire');
|
||||
$allowaccess = $this->_checkAccessRights('supprimer');
|
||||
if (!$allowaccess) {
|
||||
throw new RestException(403, 'denied read access to email templates');
|
||||
throw new RestException(403, 'denied delete access to email templates');
|
||||
}
|
||||
|
||||
$result = $this->email_template->apifetch(0, $label);
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class Login
|
|||
// We store API token into database
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."user";
|
||||
$sql .= " SET api_key = '".$this->db->escape(dolEncrypt($token, '', '', 'dolibarr'))."'";
|
||||
$sql .= " WHERE login = '".$this->db->escape($login)."'";
|
||||
$sql .= " WHERE rowid = ".((int) $tmpuser->id);
|
||||
|
||||
dol_syslog(get_class($this)."::login", LOG_DEBUG); // No log
|
||||
$result = $this->db->query($sql);
|
||||
|
|
|
|||
|
|
@ -167,7 +167,14 @@ class ObjectLinks extends DolibarrApi
|
|||
if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
|
||||
throw new RestException(403, 'denied access to create the objectlinks targettype='.$this->objectlink->targettype);
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
|
||||
throw new RestException(403, 'denied access to create the objectlinks sourcetype='.$this->objectlink->sourcetype);
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
|
||||
throw new RestException(403, 'denied access to create the objectlinks targettype='.$this->objectlink->targettype);
|
||||
}
|
||||
|
||||
// Create object link (in database)
|
||||
$result = $this->objectlink->create(DolibarrApiAccess::$user, $this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype, $this->notrigger);
|
||||
|
||||
if ($result < 0) {
|
||||
|
|
@ -225,6 +232,12 @@ class ObjectLinks extends DolibarrApi
|
|||
if (!DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'creer') && !DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'write')) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks sourcetype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
} else {
|
||||
throw new RestException(404, 'Object Link not found');
|
||||
}
|
||||
|
|
@ -297,6 +310,12 @@ class ObjectLinks extends DolibarrApi
|
|||
if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
|
||||
throw new RestException(403, 'denied access to get the objectlinks targettype='.$this->objectlink->targettype);
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks sourcetype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
|
||||
$findresult = $this->objectlink->fetchByValues($this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype);
|
||||
|
||||
|
|
@ -367,6 +386,12 @@ class ObjectLinks extends DolibarrApi
|
|||
if (!DolibarrApiAccess::$user->hasRight((string) $tgttype, 'creer') && !DolibarrApiAccess::$user->hasRight((string) $tgttype, 'write')) {
|
||||
throw new RestException(403, 'denied access to delete the objectlinks targettype='.$this->objectlink->targettype);
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks sourcetype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
|
||||
$findresult = $this->objectlink->fetchByValues($this->objectlink->fk_source, $this->objectlink->sourcetype, $this->objectlink->fk_target, $this->objectlink->targettype, $this->objectlink->relationtype);
|
||||
|
||||
|
|
@ -427,6 +452,12 @@ class ObjectLinks extends DolibarrApi
|
|||
if (!DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'lire') && !DolibarrApiAccess::$user->hasRight(((string) $tgttype), 'read')) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($srctype), $this->objectlink->fk_source)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks sourcetype');
|
||||
}
|
||||
if (!checkUserAccessToObject(DolibarrApiAccess::$user, array($tgttype), $this->objectlink->fk_target)) {
|
||||
throw new RestException(403, 'denied access to the objectlinks targettype');
|
||||
}
|
||||
} else {
|
||||
throw new RestException(404, 'Object Link not found');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2744,6 +2744,9 @@ class Setup extends DolibarrApi
|
|||
public function getEstablishments()
|
||||
{
|
||||
$list = array();
|
||||
if (!DolibarrApiAccess::$user->admin) {
|
||||
throw new RestException(403, 'Error API open to admin users only');
|
||||
}
|
||||
|
||||
$limit = 0;
|
||||
|
||||
|
|
@ -2782,6 +2785,10 @@ class Setup extends DolibarrApi
|
|||
*/
|
||||
public function getEtablishmentByID($id)
|
||||
{
|
||||
if (!DolibarrApiAccess::$user->admin) {
|
||||
throw new RestException(403, 'Error API open to admin users only');
|
||||
}
|
||||
|
||||
$establishment = new Establishment($this->db);
|
||||
|
||||
$result = $establishment->fetch($id);
|
||||
|
|
@ -2790,6 +2797,9 @@ class Setup extends DolibarrApi
|
|||
} elseif ($result == 0) {
|
||||
throw new RestException(404, 'Establishment not found');
|
||||
}
|
||||
if (!in_array($establishment->entity, explode(',', getEntity('establishment')))) {
|
||||
throw new RestException(404, 'Establishment not found');
|
||||
}
|
||||
|
||||
return $this->_cleanObjectDatas($establishment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1765,14 +1765,14 @@ class Asset extends CommonObject
|
|||
if (preg_match('/^[\(]?PROV/i', $this->ref)) {
|
||||
// Now we rename also files into index
|
||||
$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'asset/".$this->db->escape($this->newref)."'";
|
||||
$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'bom/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
|
||||
$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'bom/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->error = $this->db->lasterror();
|
||||
}
|
||||
$sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'asset/".$this->db->escape($this->newref)."'";
|
||||
$sql .= " WHERE filepath = 'asset/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
|
||||
$sql .= " WHERE filepath = 'asset/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue