Merge branch 'develop' into new-api-rest-tokens

This commit is contained in:
Laurent Destailleur 2025-10-15 03:41:05 +02:00 committed by GitHub
commit 634e27d1f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3103 changed files with 57009 additions and 368545 deletions

View file

@ -1,3 +0,0 @@
# Add this tag for any changes for more than 1 line
"Pending analysis of PR (maintenance team)":
min: 1

View file

@ -1,6 +1,19 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
allow:
# Allow production updates only (can do a AND, several entries are doing a OR)
- dependency-type: "production"
#- dependency-type: "direct"
exclude-paths:
- 'dev'
- 'tests/acceptance'
- 'tests/selenium'

View file

@ -20,10 +20,10 @@ See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workf
The other worklows are:
-----------------------
- stale-issues-safe to autoclose old issues.
- phpstan_baseline to update the phpstan baseline file.
- cache-clean-pr to clean cache when closing a PR.
- ci-stale-issues-safe to autoclose old issues.
- ci-phpstan_baseline to update the phpstan baseline file.
- ci-cache-clean-pr to clean cache when closing a PR.
- ci-test to make CI tests
Some tests workflows are:
------------------------

View file

@ -6,6 +6,8 @@ on:
pull_request:
types: [closed]
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest

View file

@ -1,6 +1,7 @@
name: "CI-PULL-REQUEST"
on: [pull_request]
jobs:
pre-commit:
uses: ./.github/workflows/pre-commit.yml
@ -25,15 +26,15 @@ jobs:
# uses: ./.github/workflows/windows-ci.yml
# with:
# gh_event: ${{ github.event_name }}
gh-travis: # Runs travis script on github runner (not on travis)
if: false
# needs: [pre-commit, phan]
# needs: [windows-ci]
secrets: inherit
needs: [pre-commit, phan, phpstan]
uses: ./.github/workflows/gh-travis.yml
with:
gh_event: ${{ github.event_name }}
#gh-travis: # Runs travis script on github runner (not on travis)
# if: false
# # needs: [pre-commit, phan]
# # needs: [windows-ci]
# secrets: inherit
# needs: [pre-commit, phan, phpstan]
# uses: ./.github/workflows/gh-travis.yml
# with:
# gh_event: ${{ github.event_name }}
# Note (not tested, from https://github.com/orgs/community/discussions/38361)
# To cancel jobs if one fails, the following action may help

View file

@ -1,6 +1,7 @@
name: "CI-PUSH"
on: [push]
jobs:
pre-commit:
uses: ./.github/workflows/pre-commit.yml
@ -25,15 +26,15 @@ jobs:
uses: ./.github/workflows/windows-ci.yml
with:
gh_event: ${{ github.event_name }}
gh-travis: # Runs travis script on github runner (not on travis)
if: false
# needs: [pre-commit, phan]
# needs: [windows-ci]
secrets: inherit
needs: [pre-commit, phan, phpstan]
uses: ./.github/workflows/gh-travis.yml
with:
gh_event: ${{ github.event_name }}
# gh-travis: # Runs travis script on github runner (not on travis)
# if: false
# # needs: [pre-commit, phan]
# # needs: [windows-ci]
# secrets: inherit
# needs: [pre-commit, phan, phpstan]
# uses: ./.github/workflows/gh-travis.yml
# with:
# gh_event: ${{ github.event_name }}
# Note (not tested, from https://github.com/orgs/community/discussions/38361)
# To cancel jobs if one fails, the following action may help

View file

@ -39,7 +39,7 @@ jobs:
with:
php-version: ${{ env.PHP_VERSION }}
coverage: none # disable xdebug, pcov
tools: phpstan:2.1.8, cs2pr
tools: phpstan:2.1.12, cs2pr
extensions: calendar, json, imagick, gd, zip, mbstring, intl, opcache, imap,
mysql, pgsql, sqlite3, ldap, xml, mcrypt
env:

View file

@ -0,0 +1,24 @@
# See syntax file on https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
name: "Check tag branch"
on:
push:
tags:
- "18.*"
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Verify tag is on main
run: |
TAG_COMMIT=$(git rev-list -n 1 $GITHUB_REF)
if ! git branch --contains $TAG_COMMIT | grep -q "18.0"; then
echo "The tag must be on branch 18.0"
exit 1
fi

View file

@ -27,11 +27,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
fail-fast: false
# matrix:
# php-version:
matrix:
php-version:
# # PHPStan requires PHP >= 7.2.
# #- "7.2"
# - "8.2"
- "8.2"
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Checkout travis file

View file

@ -1,4 +1,7 @@
---
# This is a basic workflow to check code with PHPSTAN tool
name: Phan
on:
# workflow called by the parent workflow ci.yml
workflow_call:
@ -12,6 +15,7 @@ on:
concurrency:
group: phan-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
gh_event: ${{ inputs.gh_event || github.event_name }}
PHAN_CONFIG: dev/tools/phan/config.php
@ -20,7 +24,6 @@ env:
PHAN_QUICK: ${{ github.event.schedule && '' || '--quick' }}
GITHUB_JSON: ${{ toJSON(github) }} # Helps in debugging Github Action
name: phan
jobs:
phan:
name: Run phan

View file

@ -1,6 +1,7 @@
---
# This is a basic workflow to check code with PHPSTAN tool
name: PHPStan
# Controls when the workflow will run
on:
# workflow called by the parent workflow ci.yml
@ -13,8 +14,9 @@ on:
workflow_dispatch:
concurrency:
group: stan-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: phpstan-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
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 }}
@ -43,7 +45,7 @@ jobs:
with:
php-version: ${{ matrix.php-version }}
coverage: none # disable xdebug, pcov
tools: phpstan:2.1.8, cs2pr
tools: phpstan:2.1.12, cs2pr
extensions: calendar, json, imagick, gd, zip, mbstring, intl, opcache, imap,
mysql, pgsql, sqlite3, ldap, xml, mcrypt

View file

@ -1,5 +1,6 @@
---
name: pre-commit
on:
# workflow called by the parent workflow ci.yml
workflow_call:
@ -16,6 +17,7 @@ concurrency:
cancel-in-progress: true
env:
gh_event: ${{ inputs.gh_event || github.event_name }}
jobs:
pre-commit:
runs-on: ubuntu-latest
@ -66,7 +68,7 @@ jobs:
run: |-
[ -r requirements.txt ] || [ -r pyproject.toml ] || touch requirements.txt
# Install python and pre-commit tool
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
cache: pip
python-version: "3.11"

View file

@ -1,30 +0,0 @@
name: Test github actions
on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
push:
env:
ENVGHT: ${{ secrets.GITHUB_TOKEN }}
ENVGHU: ${{ github.token }}
TEST_ACCESS_KEY: ${{ secrets.TEST_ACCESS_KEY }}
TEST_VAR_REPO: ${{ vars.TEST_VAR_REPO }}
TEST_VAR_ORGA: ${{ vars.TEST_VAR_ORGA }}
ENVLOCAL: "varenvlocal"
jobs:
testjob:
runs-on: ubuntu-latest
steps:
- name: Log
run: |
echo "Run action by ${{ github.actor }}"
echo "github.token=${{ github.token }}"
echo "secrets.GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}"
echo "GITHUB_EVENT_PATH=$GITHUB_EVENT_PATH"
echo "repo-token: ${{secrets.GITHUB_TOKEN}}"
echo "secret repository TEST_ACCESS_KEY: ${{secrets.TEST_ACCESS_KEY}}"
echo "variable repository : ${{vars.TEST_VAR_REPO}}"
echo "variable organization : ${{vars.TEST_VAR_ORGA}}"
echo "ENVLOCAL: ${{env.ENVLOCAL}}"

View file

@ -1,5 +1,6 @@
---
name: Win CI
# yamllint disable-line rule:truthy
on:
# workflow called by the parent workflow ci.yml
@ -25,6 +26,7 @@ env:
PHP_INI_SCAN_DIR: C:\myphpini
CKEY: win-ci-2
GITHUB_JSON: ${{ toJSON(github) }} # Helps in debugging Github Action
jobs:
win-test:
strategy:

View file

@ -44,12 +44,6 @@ source_file = htdocs/langs/en_US/blockedlog.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:bookmarks]
file_filter = htdocs/langs/<lang>/bookmarks.lang
source_file = htdocs/langs/en_US/bookmarks.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:boxes]
file_filter = htdocs/langs/<lang>/boxes.lang
source_file = htdocs/langs/en_US/boxes.lang
@ -104,12 +98,6 @@ source_file = htdocs/langs/en_US/datapolicy.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:deliveries]
file_filter = htdocs/langs/<lang>/deliveries.lang
source_file = htdocs/langs/en_US/deliveries.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:dict]
file_filter = htdocs/langs/<lang>/dict.lang
source_file = htdocs/langs/en_US/dict.lang
@ -146,12 +134,6 @@ source_file = htdocs/langs/en_US/exports.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:help]
file_filter = htdocs/langs/<lang>/help.lang
source_file = htdocs/langs/en_US/help.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:holiday]
file_filter = htdocs/langs/<lang>/holiday.lang
source_file = htdocs/langs/en_US/holiday.lang
@ -284,12 +266,6 @@ source_file = htdocs/langs/en_US/partnership.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:paybox]
file_filter = htdocs/langs/<lang>/paybox.lang
source_file = htdocs/langs/en_US/paybox.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:paypal]
file_filter = htdocs/langs/<lang>/paypal.lang
source_file = htdocs/langs/en_US/paypal.lang
@ -380,6 +356,12 @@ source_file = htdocs/langs/en_US/stripe.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:subtotals]
file_filter = htdocs/langs/<lang>/subtotals.lang
source_file = htdocs/langs/en_US/subtotals.lang
source_lang = en_US
type = MOZILLAPROPERTIES
[o:dolibarr-association:p:dolibarr:r:supplier_proposal]
file_filter = htdocs/langs/<lang>/supplier_proposal.lang
source_file = htdocs/langs/en_US/supplier_proposal.lang

View file

@ -53,7 +53,7 @@ TCPDI 1.1.0 LGPL-3+ / Apache 2.0 Yes
bacon, dasprid, swiss-qr-bill, kmukku, symfony/validator
JS libraries:
Ace 1.4.14 BSD Yes JS library to get code syntaxique coloration in a textarea.
Ace 1.43.12 BSD Yes JS library to get code syntaxique coloration in a textarea (Must take src dir into https://github.com/ajaxorg/ace-builds/).
ChartJS 3.7.1 MIT License Yes JS library for graph
CKEditor 4.22.1 LGPL-2.1+ Yes Editor WYSIWYG
jQuery 3.6.4 MIT License Yes JS library

121
ChangeLog
View file

@ -7,18 +7,70 @@ English Dolibarr ChangeLog
For users:
----------
For developers:
---------------
* Introducing the TRIGGER_PREFIX property to force developers to use unique triggerkey per business object, limit also code to business CRUD events and identity when it is not.
WARNING:
--------
The following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* The deprecated column egroupware_id has been dropped
* The deprecated column egroupware_id has been dropped.
* The property $sumpayed (duplicated of $totalpaid), $sumdeposit (duplicate of $totaldeposits) and $sumcreditnote (duplicate of $totalcreditnotes) has
been removed (there are replaced with the property that was a duplication of (same for $sumpayed_multicurrency, $sumdeposit_multicurrency, $sumcreditnote_multicurrency).
* Parameters $maxlen and $notooltip of Contract have been inverted to follow the standard. It was breaking the common use of getNomUrl() but if you were using the parameter
maxlen (rare) by using the old signature, result may be a tooltip that is no more visible on ref printed by you module.
* Removed array $MAP_ID_TO_CODE that was a duplicate of array "array_flip($categ->MAP_ID)"
* The signature of the Sale order ->cancel() method and shipment ->cancel() has been modified to introduce the $user param like for other methods that modify a status.
* Adding new document templates must be done by adding files into the mymodule/core/modules/xxx/doc directory. Adding files into custom directory with the
same path than the core path without using a mymodule directory is now forbidden.
* The directory theme/common/octicons has been removed
* The library timepicker.js has been removed. Was not used by Dolibarr.
* Because of new TRIGGER_PREFIX property triggers SUPPLIER_PRODUCT_BUYPRICE_XXX are renamed to PRODUCT_BUYPRICE_XXX.
* Function img_pdf() has been removed. Replace it with img_picto('', 'pdf.png') if you were using it.
***** ChangeLog for 22.0.2 compared to 22.0.1 *****
FIX: ContratLigne::fetch() returns 1 even if the line doesn't exist (#35324)
FIX: #34678
FIX: #35142 FIX: #35143
FIX: #35154 - Massaction createbills in reception list don't mind about order and/or thirdparty currency (#35156)
FIX: #35181 Cancelled purchase orders now shown as such in Project Overview (#35186)
FIX: #35407 After updating to version 22, local taxes were no longer applied (#35408)
FIX: #35425 (#35426)
FIX: accountancy general ledger: bad handling of hook return (#34029)
FIX: Add security test for show terminal selection if no terminal selected when invoice.php is call (#34717)
FIX: allow to create First Situation Invoice (#35228)
FIX: api orders : forward database error on failure (backport commit d9e81cb) (#35478)
FIX: Can't edit tags of a user.
FIX: can't reset intracomm transport mode
FIX: can't save setup of odt template for stock
FIX: check commande liste validate (#35479)
FIX: color of late warning for nb of bank account reconciliation lines
FIX: Correct the calculation of the amount of the current period between the period provided (#35083)
FIX: Date planned of delivery is not propagated from order to shipment
FIX: Edit of email in emailing. Property messtype not set.
FIX: extra field list depend on parent list when editing a card (#35165)
FIX: fallback of "from" email when sending email in member module
FIX: missing token to disable custom group category for compta report (page /htdocs/accountancy/admin/categories_list.php) (#35084)
FIX: Generation of member cards (file not found and substitution broken)
FIX: invoice not set to closed when we add a credit note to close it
FIX: missing check constant PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS (#33277)
FIX: missing entity filter (#35461)
FIX: missing quick edit for extrafields (backport commit 4fc66c6) (#35160)
FIX: Missing sentence part (#35144)
FIX: Remove perms to access commerce tab when the only active permission is fournisseur:lire (#35467)
FIX: Restore decimal quantity for stock correction/transfer
FIX: save the packaging qty on update buying price (#35234)
FIX: set global mysoc and load langs in API access (#35041)
FIX: Societe - Problem of date on outstanding opened late (#35266)
FIX: vat detection when country of buyer is unknown.
FIX: wrong extrafield template in create mode (#35241) (#35470)
***** ChangeLog for 22.0.1 compared to 22.0.0 *****
@ -41,6 +93,8 @@ FIX: Missing a column on group permissions
FIX: several minor troubles with modulebuilder
FIX: Test on mandatory product or thirdparty barcode
FIX: trigger mailmanspip when un/linking categories
FIX: Security when using Advanced Target page of emailing (feature hidden in v21, default in v22+). Possible
SQL injection by users with permission to make and send mass emailing.
***** ChangeLog for 22.0.0 compared to 21.0 *****
@ -202,6 +256,38 @@ The following changes may create regressions for some external modules, but were
* The property ->price_ht of an object line that was a duplicate of ->subprice has been standardized. Use ->subprice everywhere now.
***** ChangeLog for 21.0.4 compared to 21.0.3 *****
FIX: #35147 SQL Error on Beluga Export when ExpenseReport is enabled (#35149)
FIX: error when using a code too large in dictionary
FIX: Security when using Advanced Target page of emailing (feature hidden in v21, default in v22+). Possible
SQL injection by users with permission to make and send mass emailing.
***** ChangeLog for 21.0.3 compared to 21.0.2 *****
FIX: #34843 (#34875)
FIX: #34936
FIX: #35005
FIX: #35006 SQL error when using external user
FIX: a Fatal error when a trigger files is not correctly named.
FIX: array for arrayofkeyval is lost in module builder edit of property
FIX: asset: could not select invoice in disposal pop-in (#34725)
FIX: avoid php warning with "$forceFullTextIndexation" (#34881)
FIX: bad consistency on test on permission to disable service
FIX: Can edit status of tasks
FIX: Create public ticket if email need exist. (#34965)
FIX: DA026536: missing <br> in automatic e-mail (#34895)
FIX: extrafields of type "int" not displayed on `projet/tasks.php` (#34896)
FIX: Filter on the balance of leave
FIX: Logo on company is no more visible.
FIX: mailing destination list title (#34929)
FIX: main checkbox left column was before global conf (#34858)
FIX: Missing a column on group permissions
FIX: several minor troubles with modulebuilder
FIX: Test on mandatory product or thirdparty barcode
FIX: trigger mailmanspip when un/linking categories
SEC: Remove functions accepting callable params - Reported by phdwg1410 - CVE-2024-40137
***** ChangeLog for 21.0.2 compared to 21.0.1 *****
FIX: 21.0: $height and $width can be ints, but also 'auto' (#34636)
@ -1187,6 +1273,7 @@ FIX: when qty is not an integer, apply price() (#31138)
FIX: Wrong default PDF model when creating the second situation invoice (#30843)
FIX: wrong subprice if price base type is TTC (#30887)
***** ChangeLog for 19.0.3 compared to 19.0.2 *****
FIX: #29403 HRM - Unable to delete a skill in a job Profile (#29779)
FIX: #29439 incomplete API return (#29796)
@ -1750,7 +1837,39 @@ The following changes may create regressions for some external modules, but were
* The load of hook context productdao has been removed before calling loadvirtualstock. Modules must use the context of main parent page or 'all' for all cases.
* booking.class.php was removed, please have a look at calendar.class.php
***** ChangeLog for 18.0.8 compared to 18.0.7 *****
35 files changed, 647 insertions(+), 298 deletions(-)
FIX: #34746 - More complete fix for CVE-2024-40137
FIX: Correct the calculation of the amount of the current period between the period provided (#35083)
FIX: Add security test for show terminal selection if no terminal selected when invoice.php is call (#34717)
FIX: Add security test for show terminal selection if no terminal selected when invoice.php is call
FIX: missing quick edit for extrafields (baclport commit 4fc66c6) (#35160)
FIX: Missing sentence part (#35144)
FIX: set global mysoc and load langs in API access (#35041)
FIX: set global mysoc and load langs in API access
FIX: reset mysoc and langs only if entity of API has changed
FIX: accountancy general ledger: bad handling of hook return (#34029)
FIX: accountancy general ledger: bad handling of hook return
FIX: accountancy balance: bad handling of hook return
FIX: - Fix missing token for disable custom group category for compta report (page /htdocs/accountancy/admin/categories_list.php) (#35084)
FIX: The combo of custom groups has disappeared (backport v19) (#35016)
FIX: #34893 (#34897)
FIX: #34893
FIX: change error code to USERNOTALLOWEDTOCHANGEPASS
FIX: asset: could not select invoice in disposal pop-in (#34725)
FIX: 17.0 SQL syntax error and/or constraint error when calling Facture::update() after a clone (e.g. in a trigger) (#34778)
FIX: 17.0: when you clone an invoice that was created from a template invoice, the clone should not be linked to the template invoice (#34777)
FIX: pre-send mail mass action: keep __EMAIL__ substitution (#34522)
FIX: pre-send mail mass action: keep __EMAIL__ substitution
FIX: comment
FIX: massaction email tpl: keep preset
FIX: loop interrupt if an error occurs in sendEmailsRemindersOnInvoiceDueDate (#34657)
FIX: #34654
***** ChangeLog for 18.0.7 compared to 18.0.6 *****
138 files changed, 1622 insertions(+), 530 deletions(-)
FIX: 17.0 API endpoints "PUT": prevent overwriting all extrafields if only some are supplied in the request cf. PR #29237
FIX: 17.0 - collisions in cache for dol_getIdFromCode
FIX: 17.0 - missing error handling for FactureRec::fetch in card-rec.php

View file

@ -41,7 +41,7 @@ PROJECT_NUMBER = x.y.z
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = build
OUTPUT_DIRECTORY = dev/build
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output

View file

@ -38,8 +38,8 @@ DefaultGroupName=Dolibarr
;Compression=none
Compression=lzma
SolidCompression=yes
WizardImageFile=build\exe\doliwamp\doliwamp.bmp
WizardSmallImageFile=build\exe\doliwamp\doliwampsmall.bmp
WizardImageFile=dev\build\exe\doliwamp\doliwamp.bmp
WizardSmallImageFile=dev\build\exe\doliwamp\doliwampsmall.bmp
SetupIconFile=doc\images\dolibarr_favicon.ico
;To say the installer must be ran as admin
PrivilegesRequired=admin

View file

@ -49,9 +49,18 @@ $includecustom = 0;
$includeconstants = array();
$buildzip = 0;
print '***** '.$script_file.' *****'."\n";
if (empty($argv[1])) {
print "Usage: ".$script_file." release=auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value] [buildzip=1]\n";
print "Example: ".$script_file." release=6.0.0 includecustom=1 includeconstant=FR:INVOICE_CAN_ALWAYS_BE_REMOVED:0 includeconstant=all:MAILING_NO_USING_PHPMAIL:1\n";
print "\n";
print "Generate the file filelist-x.y.z[-mybuild].xml with signature of files. ";
print "This includes the 3 sections:\n";
print "- dolibarr_htdocs_dir\n";
print "- dolibarr_scripts_dir\n";
print "- dolibarr_unalterable_files (only files inside the scope of the unalterable module)\n";
print "\n";
exit(1);
}
@ -68,20 +77,17 @@ while ($i < $argc) {
if (!empty($result["includecustom"])) {
$includecustom = $result["includecustom"];
}
if (!empty($result["includeconstant"])) {
$includeconstants[$i] = $result["includeconstant"];
}
if (!empty($result["buildzip"])) {
$buildzip = 1;
}
if (preg_match('/includeconstant=/', strval($argv[$i]))) {
$tmp = explode(':', $result['includeconstant'], 3); // $includeconstant has been set with previous parse_str()
if (count($tmp) != 3) {
print "Error: Bad parameter includeconstant=".$result['includeconstant'] ."\n";
exit -1;
exit(1);
}
$includeconstants[$tmp[0]][$tmp[1]] = $tmp[2];
}
if (!empty($result["buildzip"])) {
$buildzip = 1;
}
$i++;
}
@ -97,7 +103,7 @@ $savrelease = $release;
$tmpver = explode('-', $release, 2);
if ($tmpver[0] == 'auto') {
$release = DOL_VERSION;
if ($tmpver[1] && $tmpver[0] == 'auto') {
if (!empty($tmpver[1]) && $tmpver[0] == 'auto') {
$release .= '-'.$tmpver[1];
}
}
@ -126,10 +132,10 @@ if (empty($includecustom)) {
}
}
print "Working on files into : ".DOL_DOCUMENT_ROOT."\n";
print "Release : ".$release."\n";
print "Include custom in signature : ".$includecustom."\n";
print "Include constants in signature : ";
print "Working on files into : ".DOL_DOCUMENT_ROOT."\n";
print "Release : ".$release."\n";
print "Include custom dir in signature : ".(empty($includecustom) ? 'no' : 'yes')."\n";
print "Include constants in signature : ".(empty($includeconstants) ? 'none' : '');
foreach ($includeconstants as $countrycode => $tmp) {
foreach ($tmp as $constname => $constvalue) {
print $constname.'='.$constvalue." ";
@ -155,9 +161,12 @@ $gitcommit = 'seetag';
$branchname = preg_replace('/^(\d+\.\d+)\..*$/', '\1', $release); // Keep only x.y into x.y.z
$fileforgit = dirname(dirname(dirname(__FILE__))).'/.git/refs/heads/'.$branchname;
print "Try to get last commit ID from file ".$fileforgit."\n";
$fileforgitcontent = file_get_contents($fileforgit);
$fileforgitcontent = '';
if (file_exists($fileforgit)) {
$fileforgitcontent = file_get_contents($fileforgit);
}
if (empty($fileforgitcontent)) {
print "Failed to get the last commit ID. Are you on the branch for the release (branch name '.$branchname.') ?\n";
print "Failed to get the last commit ID (are you on the branch for the release branch name ".$branchname." ?). We will use an empty value for gitcommit.\n";
}
$gitcommit = trim($fileforgitcontent);
@ -180,7 +189,7 @@ fputs($fp, '<dolibarr_htdocs_dir includecustom="'.$includecustom.'">'."\n");
// Define qualified files (must be same than into generate_filelist_xml.php and in api_setup.class.php)
$regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$';
$regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs
$regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|escpos-php\/doc|escpos-php\/example|escpos-php\/test|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs
$files = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude, 'fullname');
$dir = '';
@ -350,7 +359,7 @@ if ($newdir != $dir) {
}
fputs($fp, ' <dir name="'.$newdir.'">'."\n");
$dir = $newdir;
$needtoclose = 1;
//$needtoclose = 1; // close will be done in next filethat is in same dir
}
if (filetype($file) == "file") {
$md5 = md5_file($file);
@ -361,7 +370,7 @@ if ($needtoclose) {
fputs($fp, ' </dir>'."\n");
$needtoclose = 0;
}
// Add the interfaces.class.php file
// Add the commontrigger.class.php file
$file = dirname(__FILE__).'/../../htdocs/core/class/commontrigger.class.php';
$newdir = str_replace(DOL_DOCUMENT_ROOT, '', dirname($file));
$newdir = str_replace(dirname(__FILE__).'/../../htdocs', '', dirname($file));
@ -374,6 +383,8 @@ if ($newdir != $dir) {
$dir = $newdir;
$needtoclose = 1;
}
$needtoclose = 1; // This is the last file
if (filetype($file) == "file") {
$md5 = md5_file($file);
$checksumconcat[] = $md5;
@ -399,22 +410,26 @@ fputs($fp, '</dolibarr_unalterable_files_checksum>'."\n\n");
fputs($fp, '</checksum_list>'."\n");
fclose($fp);
print "\n";
if (empty($buildzip)) {
print "File ".$outputfile." generated\n";
print "File ".$outputfile." generated.\n";
} else {
if ($buildzip == '1' || $buildzip == 'zip') {
$result = dol_compress_file($outputfile, $outputfile.'.zip', 'zip');
if ($result > 0) {
dol_delete_file($outputfile);
print "File ".$outputfile.".zip generated\n";
print "File ".$outputfile.".zip generated.\n";
}
} elseif ($buildzip == '2' || $buildzip == 'gz') {
$result = dol_compress_file($outputfile, $outputfile.'.gz', 'gz');
if ($result > 0) {
dol_delete_file($outputfile);
print "File ".$outputfile.".gz generated\n";
print "File ".$outputfile.".gz generated.\n";
}
}
}
print "\n";
exit(0);

View file

@ -446,6 +446,15 @@ if ($nboftargetok) {
print 'Create xml check file with md5 checksum with command php '.$SOURCE.'/dev/build/generate_filelist_xml.php release='.$MAJOR.'.'.$MINOR.'.'.$BUILD."\n";
$ret=`php $SOURCE/dev/build/generate_filelist_xml.php release=$MAJOR.$MINOR.$BUILD`;
my $retcode=$?;
if ($retcode!=0)
{
print "Error running generate_filelist_xml.php please check\n";
print $ret;
print "Canceled.\n";
exit;
}
print $ret."\n";
# Copy to final dir
$NEWDESTI=$DESTI;
@ -477,14 +486,14 @@ if ($nboftargetok) {
{
print 'Run git tag -a -f -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n";
$ret=`git tag -a -f -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD"`;
print 'Run git push $GITREMOTENAME -f "$MAJOR.$MINOR.$BUILD"'."\n";
print 'Run git push '.$GITREMOTENAME.' -f "$MAJOR.$MINOR.$BUILD"'."\n";
$ret=`git push $GITREMOTENAME -f -"$MAJOR.$MINOR.$BUILD"`;
#$ret=`git push -f origin "$MAJOR.$MINOR.$BUILD"`;
}
}
else
{
print 'Run git push $GITREMOTENAME --tags'."\n";
print "Run git push $GITREMOTENAME --tags\n";
$ret=`git push $GITREMOTENAME --tags`;
#$ret=`git push origin "$MAJOR.$MINOR.$BUILD"`;
}

File diff suppressed because it is too large Load diff

View file

@ -234,7 +234,7 @@ In htdocs/includes/tecnickcom/tcpdf/tcpdf.php
PHP TCPDI:
----------
Add file fpdf_tpl.php 1.2
Add file fpdf_tpl.php 1.2.3
Add file tcpdi.php

View file

@ -57,7 +57,7 @@ if (empty($argv[1])) {
print "Usage: $script_file nbofrecord\n";
print "Usage: $script_file 100\n";
print "\n";
exit(-1);
exit(1);
}
define('GEN_NUMBER_FACTURE', ((int) $argv[1]) ?? 1);

View file

@ -64,7 +64,7 @@ if (empty($argv[1])) {
print "Usage: $script_file nbofrecord\n";
print "Usage: $script_file 100\n";
print "\n";
exit(-1);
exit(1);
}
define('GEN_NUMBER_COMMANDE', ((int) $argv[1]) ?? 10);

View file

@ -62,7 +62,7 @@ if (empty($argv[1])) {
print "Usage: $script_file nbofrecord\n";
print "Usage: $script_file 100\n";
print "\n";
exit(-1);
exit(1);
}
define('GEN_NUMBER_PRODUIT', ((int) $argv[1]) ?? 100);

View file

@ -60,7 +60,7 @@ if (empty($argv[1])) {
print "Usage: $script_file nbofrecord\n";
print "Usage: $script_file 100\n";
print "\n";
exit(-1);
exit(1);
}
define('GEN_NUMBER_PROPAL', ((int) $argv[1]) ?? 10);

View file

@ -65,7 +65,7 @@ if (empty($argv[1])) {
print "Usage: $script_file nbofrecord\n";
print "Usage: $script_file 100\n";
print "\n";
exit(-1);
exit(1);
}
define('GEN_NUMBER_SOCIETE', ((int) $argv[1]) ?? 10);

View file

@ -71,12 +71,12 @@ if (empty($mode) || ! in_array($mode, array('test','confirm','confirmforced')) |
print "Usage: $script_file (test|confirm|confirmforced) filepath.csv [defaultlang] [startlinenb] [endlinenb]\n";
print "Usage: $script_file test myfilepath.csv fr_FR 2 1002\n";
print "\n";
exit(-1);
exit(1);
}
if (! file_exists($filepath)) {
print "Error: File ".$filepath." not found.\n";
print "\n";
exit(-1);
exit(1);
}
$ret = $user->fetch('', 'admin');

View file

@ -71,12 +71,12 @@ if (empty($mode) || ! in_array($mode, array('test','confirm','confirmforced')) |
print "Usage: $script_file (test|confirm|confirmforced) filepath.csv [startlinenb] [endlinenb]\n";
print "Usage: $script_file test myfilepath.csv 2 1002\n";
print "\n";
exit(-1);
exit(1);
}
if (! file_exists($filepath)) {
print "Error: File ".$filepath." not found.\n";
print "\n";
exit(-1);
exit(1);
}
$ret = $user->fetch('', 'admin');

View file

@ -71,12 +71,12 @@ if (empty($mode) || ! in_array($mode, array('test','confirm','confirmforced')) |
print "Usage: $script_file (test|confirm|confirmforced) filepath.csv [startlinenb] [endlinenb]\n";
print "Usage: $script_file test myfilepath.csv 2 1002\n";
print "\n";
exit(-1);
exit(1);
}
if (! file_exists($filepath)) {
print "Error: File ".$filepath." not found.\n";
print "\n";
exit(-1);
exit(1);
}
$ret=$user->fetch('', 'admin');

View file

@ -32,7 +32,7 @@ $path=__DIR__.'/';
// Test si mode batch
if (substr($sapi_type, 0, 3) == 'cgi') {
echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n";
exit(-1);
exit(1);
}
// Recupere root dolibarr
@ -187,13 +187,13 @@ if (empty($mode) || ! in_array($mode, array('test','confirm'))) {
print "Usage: $script_file (test|confirm) (all|option) (all|YYYY-MM-DD) [dbtype dbhost dbuser dbpassword dbname dbport]\n";
print "\n";
print "option can be ".implode(',', array_keys($sqls))."\n";
exit(-1);
exit(1);
}
if (empty($option)) {
print "Usage: $script_file (test|confirm) (all|option) (all|YYYY-MM-DD) [dbtype dbhost dbuser dbpassword dbname dbport]\n";
print "\n";
print "option must be defined with a value in list ".implode(',', array_keys($sqls))."\n";
exit(-1);
exit(1);
}
if ($option != 'all') {
$listofoptions=explode(',', $option);
@ -202,7 +202,7 @@ if ($option != 'all') {
print "Usage: $script_file (test|confirm) (all|option) (all|YYYY-MM-DD) [dbtype dbhost dbuser dbpassword dbname dbport]\n";
print "\n";
print "option '".$cursoroption."' must be in list ".implode(',', array_keys($sqls))."\n";
exit(-1);
exit(1);
}
}
}
@ -211,7 +211,7 @@ if (empty($date) || (! preg_match('/\d\d\d\d\-\d\d\-\d\d$/', $date) && $date !=
print "Usage: $script_file (test|confirm) (all|option) (all|YYYY-MM-DD) [dbtype dbhost dbuser dbpassword dbname dbport]\n";
print "\n";
print "date can be 'all' or 'YYYY-MM-DD' to delete record before YYYY-MM-DD\n";
exit(-1);
exit(1);
}
if ($date == 'all') {

View file

@ -65051,7 +65051,7 @@ INSERT INTO `llx_const` VALUES
(11890,'MAIN_AGENDA_ACTIONAUTO_USER_CREATE',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11891,'MAIN_AGENDA_ACTIONAUTO_USER_MODIFY',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11892,'MAIN_AGENDA_ACTIONAUTO_USER_DELETE',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11893,'MAIN_AGENDA_ACTIONAUTO_USER_NEW_PASSWORD',1,'dolcrypt:AES-256-CTR:9eebc9ac2c57a4ec:ww==','chaine',0,'','2023-03-01 16:57:33'),
(11893,'MAIN_AGENDA_ACTIONAUTO_USER_NEW_PASSWORD',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11894,'MAIN_AGENDA_ACTIONAUTO_USER_ENABLEDISABLE',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11895,'MAIN_AGENDA_ACTIONAUTO_BOM_VALIDATE',1,'1','chaine',0,'','2023-03-01 16:57:33'),
(11896,'MAIN_AGENDA_ACTIONAUTO_BOM_UNVALIDATE',1,'1','chaine',0,'','2023-03-01 16:57:33'),
@ -65205,7 +65205,6 @@ INSERT INTO `llx_const` VALUES
(14411,'MARKETPLACE_BUYER_ORDER_CONFIRMATION_TEMPLATE',1,'-1','chaine',0,'','2025-02-05 14:08:06'),
(14412,'MARKETPLACE_SELLERS_ORDER_CONFIRMATION_TEMPLATE',1,'-1','chaine',0,'','2025-02-05 14:08:06'),
(14413,'MARKETPLACE_MINIMUM_PAYOUT_AMOUNT',1,'50','chaine',0,'','2025-02-05 14:08:06'),
(14417,'MARKETPLACE_SECRET_KEY',1,'dolcrypt:AES-256-CTR:a113efb19906f2be:q6ZG+E22cA==','chaine',0,'','2025-02-05 14:09:55'),
(14459,'MARKETPLACE_PAYMENT_IN_FRAME',1,'1','chaine',0,'','2025-02-05 14:33:21'),
(14491,'HELLOASSO_BANK_ACCOUNT_FOR_PAYMENTS',1,'6','chaine',0,'','2025-02-06 12:52:19'),
(14521,'MAIN_MAIL_SENDMODE_PASSWORDRESET',1,'default','chaine',0,'','2025-02-12 18:07:29'),
@ -65251,7 +65250,7 @@ INSERT INTO `llx_const` VALUES
(15001,'PROPALE_VALIDITY_DURATION',1,'15','chaine',0,'','2025-03-03 02:52:32'),
(15002,'PROPOSAL_FREE_TEXT',1,'Ceci est <a href=\"https://www.dolibarr.org\">un lien</a>','chaine',0,'','2025-03-03 02:52:32'),
(15004,'PDF_SECURITY_ENCRYPTION',1,'0','chaine',1,'','2025-03-03 02:53:28'),
(15007,'MARKETPLACE_PUBLIC_API_KEY',1,'dolcrypt:AES-256-CTR:d515f8d303aad816:+32sG1DvuxkMOYlMzFOY6Y1VhKf5r+dvMfz2e+6EjHU=','chaine',0,'','2025-03-03 16:22:48'),
(15007,'MARKETPLACE_PUBLIC_API_KEY',1,'demokey','chaine',0,'','2025-03-03 16:22:48'),
(15011,'MAIN_ENABLE_COMMUNITY_REPO',1,'1','chaine',1,'','2025-03-03 16:54:48'),
(15020,'MAIN_ENABLE_DOLISTORE',1,'0','chaine',1,'','2025-03-04 22:03:12'),
(15161,'MAIN_MODULE_OPENIDCONNECT',1,'1','string',0,'{\"authorid\":\"12\",\"ip\":\"127.0.0.1\",\"lastactivationversion\":\"dolibarr\"}','2025-03-06 15:18:21'),
@ -65304,7 +65303,7 @@ INSERT INTO `llx_const` VALUES
(15630,'MULTICURRENCY_APP_ID',1,'knJn9aj77LqcGtHp9m6rRWB5iD1yhfRO','chaine',0,'','2025-03-21 12:43:49'),
(15726,'EMAILING_USE_ADVANCED_SELECTOR',1,'1','chaine',0,'','2025-03-25 11:08:47'),
(15731,'CONTRACT_ALLOW_ONLINESIGN',1,'0','chaine',0,'','2025-03-25 12:47:09'),
(15746,'MULTICURRENCY_APP_KEY',1,'dolcrypt:AES-256-CTR:a972ff0c9e92c932:dqOrWexGkIENOk0Fen4hKMCN+jxY2ou0EDwmV1pk2uQ=','chaine',0,'','2025-03-25 15:03:23'),
(15746,'MULTICURRENCY_APP_KEY',1,'demokey','chaine',0,'','2025-03-25 15:03:23'),
(15747,'MULTICURRENCY_APP_ENDPOINT',1,'https://api.apilayer.com/currency_data/live?base=__MULTICURRENCY_APP_SOURCE__','chaine',0,'','2025-03-25 15:03:23'),
(15752,'MAIN_AGENDA_ACTIONAUTO_COMPANY_RIB_CREATE',1,'1','chaine',0,NULL,'2025-03-25 19:50:16'),
(15753,'MAIN_AGENDA_ACTIONAUTO_COMPANY_RIB_MODIFY',1,'1','chaine',0,NULL,'2025-03-25 19:50:16'),
@ -65447,12 +65446,12 @@ INSERT INTO `llx_const` VALUES
(17506,'ACCOUNTING_PRODUCT_MODE',1,'ACCOUNTANCY_SELL','chaine',0,'','2025-04-03 18:15:02'),
(17586,'FACTURE_ADDON',1,'mod_facture_mars','chaine',0,'','2025-04-05 14:25:19'),
(17777,'AI_API_SERVICE',1,'mistral','chaine',0,'','2025-04-07 23:24:36'),
(17778,'AI_API_CHATGPT_KEY',1,'dolcrypt:AES-256-CTR:9613a045bab6c491:GZp61Q3TMSMF/iTVCl/0QXXkGcMsTJetGBR5Zy6nLac=','chaine',0,'','2025-04-07 23:24:36'),
(17778,'AI_API_CHATGPT_KEY',1,'demokey','chaine',0,'','2025-04-07 23:24:36'),
(17779,'AI_API_CHATGPT_URL',1,'https://api.openai.com/v1/','chaine',0,'','2025-04-07 23:24:36'),
(17780,'AI_API_GROQ_URL',1,'https://api.groq.com/openai/','chaine',0,'','2025-04-07 23:24:36'),
(17781,'AI_API_MISTRAL_KEY',1,'dolcrypt:AES-256-CTR:1abe518475f89cfa:LNtWUSvYyIf8LQ/JEtpuu2ZrorjJMUxRFZG4VmmEn7o=','chaine',0,'','2025-04-07 23:24:36'),
(17781,'AI_API_MISTRAL_KEY',1,'demokey','chaine',0,'','2025-04-07 23:24:36'),
(17782,'AI_API_MISTRAL_URL',1,'https://api.mistral.ai/v1/','chaine',0,'','2025-04-07 23:24:36'),
(17783,'AI_API_CUSTOM_KEY',1,'dolcrypt:AES-256-CTR:9733d785d0113ed2:+KXzk7ILKPq99LL2g9dpxGlprEWAScO26jEeFnpJBxQ=','chaine',0,'','2025-04-07 23:24:36'),
(17783,'AI_API_CUSTOM_KEY',1,'demokey','chaine',0,'','2025-04-07 23:24:36'),
(17784,'AI_API_CUSTOM_URL',1,'https://mydomainofapi.com/v1','chaine',0,'','2025-04-07 23:24:36'),
(17788,'SOCIETE_RIB_ALLOW_ONLINESIGN',1,'1','chaine',0,'','2025-04-08 08:59:48'),
(17803,'SOCIETE_ENABLE_PUBLIC',1,'1','chaine',1,'','2025-04-08 10:55:06'),
@ -65506,7 +65505,7 @@ INSERT INTO `llx_const` VALUES
(18204,'MAIN_INFO_SOCIETE_OBJECT',1,'A company demo to show how Dolibarr ERP CRM is wonderfull','chaine',0,'','2025-04-16 19:50:19'),
(18205,'SOCIETE_FISCAL_MONTH_START',1,'4','chaine',0,'','2025-04-16 19:50:19'),
(18206,'FACTURE_TVAOPTION',1,'1','chaine',0,'','2025-04-16 19:50:19'),
(18234,'MAIN_MODULE_DOLISTORE_API_KEY',1,'dolcrypt:AES-256-CTR:d4169f5ecebe9852:mSXcyJujXRYwvP1DmsaFgevA','chaine',1,'','2025-04-17 10:04:08'),
(18234,'MAIN_MODULE_DOLISTORE_API_KEY',1,'dolistorepublicapi','chaine',1,'','2025-04-17 10:04:08'),
(18241,'PROJET_VISIBILITY',1,'0','chaine',0,'','2025-04-18 11:17:47'),
(18242,'PROJECT_ENABLE_PUBLIC',1,'1','chaine',0,'','2025-04-18 11:17:47'),
(18243,'PROJECT_DEFAULT_OPPORTUNITY_STATUS_FOR_ONLINE_LEAD',1,'-1','chaine',0,'','2025-04-18 11:17:47'),
@ -65517,7 +65516,7 @@ INSERT INTO `llx_const` VALUES
(18256,'EVENTORGANIZATION_TEMPLATE_EMAIL_AFT_SUBS_EVENT',1,'34','chaine',0,'','2025-04-18 11:21:49'),
(18257,'SERVICE_BOOTH_LOCATION',1,'0','chaine',0,'','2025-04-18 11:21:49'),
(18258,'SERVICE_CONFERENCE_ATTENDEE_SUBSCRIPTION',1,'0','chaine',0,'','2025-04-18 11:21:49'),
(18260,'EVENTORGANIZATION_SECUREKEY',1,'dolcrypt:AES-256-CTR:83f6e644d47eaf29:GIDq0w==','chaine',0,'','2025-04-18 13:46:59'),
(18260,'EVENTORGANIZATION_SECUREKEY',1,'demokey','chaine',0,'','2025-04-18 13:46:59'),
(18271,'MAIN_ENABLE_OVERWRITE_TRANSLATION',1,'1','chaine',0,'','2025-04-21 12:59:49'),
(18273,'RESOURCE_USED_IN_EVENT_CHECK',1,'1','chaine',0,'','2025-04-22 17:20:40'),
(18275,'MAIN_MENU_STANDARD',1,'eldy_menu.php','chaine',0,'','2025-04-24 12:08:27'),
@ -65556,8 +65555,6 @@ INSERT INTO `llx_const` VALUES
(18588,'TAWKTO_WIDGET_ID',1,'123','chaine',0,'','2025-05-12 08:36:50'),
(18678,'SELLYOURSAAS_ALLOW_SELECTION_OF_SERVICE',1,'1','chaine',0,'','2025-05-26 12:57:33'),
(18719,'SELLYOURSAAS_ALLOW_RESELLER_PROGRAM',1,'1','chaine',0,'','2025-05-26 13:41:52'),
(18722,'STRIPE_TEST_PUBLISHABLE_KEY',1,'dolcrypt:AES-256-CTR:d484ce93b5b8497d:T5UVYovfd4RjjYBmTt7Xipdly/dt5R7A/7TwBytAV6E=','chaine',0,'','2025-05-26 15:26:42'),
(18723,'STRIPE_TEST_SECRET_KEY',1,'dolcrypt:AES-256-CTR:eebc90c2ac9810a9:87fh2hsZr7l+dExy/ngsDP25FaoEkRfHkjdqKGulFBU=','chaine',0,'','2025-05-26 15:26:42'),
(18724,'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS',1,'4','chaine',0,'','2025-05-26 15:26:42'),
(18725,'STRIPE_USER_ACCOUNT_FOR_ACTIONS',1,'0','chaine',0,'','2025-05-26 15:26:42'),
(18726,'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS',1,'0','chaine',0,'','2025-05-26 15:26:42'),
@ -65824,12 +65821,12 @@ LOCK TABLES `llx_contrat_extrafields` WRITE;
/*!40000 ALTER TABLE `llx_contrat_extrafields` DISABLE KEYS */;
INSERT INTO `llx_contrat_extrafields` VALUES
(1,'2023-01-19 12:39:56',2,NULL,NULL,NULL,'done',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(5,'2025-01-03 14:13:54',8,NULL,'DOLICLOUD','testldr1-ABC','processing','127.0.0.1','2025-01-03 15:13:54',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 15:13:54',NULL,NULL,NULL,NULL,NULL,'testldr1d.with1.home.lan','osuo724k4hqa','dolcrypt:AES-256-CTR:ce01e4a8ade3c2ee:Rn1kmDfhbw0Eb8zpBI8=','0','testldr1d.with1.home.lan','dbntq7Wk89Mt','3306','dbuZe76P3B70','dolcrypt:AES-256-CTR:e0775c31971de7f3:YsE0Bi6lWG63zd537qc=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(6,'2025-01-03 14:17:40',9,NULL,'DOLICLOUD','testldr1-ABC','processing','127.0.0.1','2025-01-03 15:17:40',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 15:17:40',NULL,NULL,NULL,NULL,NULL,'testldre.with1.home.lan','osuky642i38n','dolcrypt:AES-256-CTR:402192d99e39c190:5DrzVbVS5kac7ZQUchU=','0','testldre.with1.home.lan','dbnd3X892MlO','3306','dbuCbWmMi7O8','dolcrypt:AES-256-CTR:b22360d10ff565a0:DXpgecqzOn7X/3PQCo0=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(7,'2025-03-25 23:57:06',7,NULL,'DOLICLOUD','testldr1b-ABC','undeployed','127.0.0.1','2025-01-03 15:08:56',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-23 15:08:56','2025-01-03 15:26:46','127.0.0.1',NULL,NULL,NULL,'testldr1c.with1.home.lan','osu6viclw5if','dolcrypt:AES-256-CTR:281a87e3e9c5fccb:O/N7kTAeXiZaHqlEupE=','0','testldr1c.with1.home.lan','dbnrC5ydd7GC','3306','dbub5pLDMaTw','dolcrypt:AES-256-CTR:2e4a79eda1bf538a:PS7p579ZNsDQAycuq8o=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(8,'2025-01-03 14:26:46',5,NULL,'DOLICLOUD','testldr1-ABC','undeployed','127.0.0.1','2025-01-03 14:59:56',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 14:59:56','2025-01-03 15:26:46','127.0.0.1',NULL,NULL,NULL,'testldr1.with1.home.lan','osu07jp64r9z','dolcrypt:AES-256-CTR:d94d86baf2f8483b:Op7TNgxhUwrSgbilZDo=','0','testldr1.with1.home.lan','dbnL4N55fzF6','3306','dbuH73bA3QfX','dolcrypt:AES-256-CTR:535b648bbae2f12a:VEc+yVQFXPbxOqhIItQ=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(9,'2025-03-25 21:53:24',6,NULL,'DOLICLOUD','testldr1-ABC','undeployed','127.0.0.1','2025-01-03 15:05:10',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2026-01-19 15:05:10','2025-01-03 15:27:11','127.0.0.1',NULL,NULL,NULL,'testldr1b.with1.home.lan','osu7xkedfm24','dolcrypt:AES-256-CTR:fa3d910f3fbfdad2:o+C4Ksn2W5veGS5R5Ag=','0','testldr1b.with1.home.lan','dbnVmeQT2M8i','3306','dbuK7VsLk5c8','dolcrypt:AES-256-CTR:ccb4d385381f4b4b:lDR/2Y6QjlNt3onLr3U=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(10,'2025-01-28 16:39:40',10,NULL,'DOLICLOUD','Azerty01','processing','127.0.0.1','2025-01-28 17:39:40',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-02-12 17:39:40',NULL,NULL,NULL,NULL,NULL,'aaa.with1.home.lan','osuy6m0f5xtl','dolcrypt:AES-256-CTR:54fed010c0ce1d1c:8eXkLuQl7gNbC9RZEPM=','0','aaa.with1.home.lan','dbnSE8YB6jGm','3306','dbu8MhF1Dwcl','dolcrypt:AES-256-CTR:44f9f66acc719394:Bi7LNv+Vf6cf2ySF2aw=',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(5,'2025-01-03 14:13:54',8,NULL,'DOLICLOUD','testldr1-ABC','processing','127.0.0.1','2025-01-03 15:13:54',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 15:13:54',NULL,NULL,NULL,NULL,NULL,'testldr1d.with1.home.lan','osuo724k4hqa','demokey','0','testldr1d.with1.home.lan','dbntq7Wk89Mt','3306','dbuZe76P3B70','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(6,'2025-01-03 14:17:40',9,NULL,'DOLICLOUD','testldr1-ABC','processing','127.0.0.1','2025-01-03 15:17:40',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 15:17:40',NULL,NULL,NULL,NULL,NULL,'testldre.with1.home.lan','osuky642i38n','demokey','0','testldre.with1.home.lan','dbnd3X892MlO','3306','dbuCbWmMi7O8','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(7,'2025-03-25 23:57:06',7,NULL,'DOLICLOUD','testldr1b-ABC','undeployed','127.0.0.1','2025-01-03 15:08:56',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-23 15:08:56','2025-01-03 15:26:46','127.0.0.1',NULL,NULL,NULL,'testldr1c.with1.home.lan','osu6viclw5if','demokey','0','testldr1c.with1.home.lan','dbnrC5ydd7GC','3306','dbub5pLDMaTw','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(8,'2025-01-03 14:26:46',5,NULL,'DOLICLOUD','testldr1-ABC','undeployed','127.0.0.1','2025-01-03 14:59:56',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-01-18 14:59:56','2025-01-03 15:26:46','127.0.0.1',NULL,NULL,NULL,'testldr1.with1.home.lan','osu07jp64r9z','demokey','0','testldr1.with1.home.lan','dbnL4N55fzF6','3306','dbuH73bA3QfX','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(9,'2025-03-25 21:53:24',6,NULL,'DOLICLOUD','testldr1-ABC','undeployed','127.0.0.1','2025-01-03 15:05:10',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2026-01-19 15:05:10','2025-01-03 15:27:11','127.0.0.1',NULL,NULL,NULL,'testldr1b.with1.home.lan','osu7xkedfm24','demokey','0','testldr1b.with1.home.lan','dbnVmeQT2M8i','3306','dbuK7VsLk5c8','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(10,'2025-01-28 16:39:40',10,NULL,'DOLICLOUD','Azerty01','processing','127.0.0.1','2025-01-28 17:39:40',NULL,'127.0.0.1',NULL,NULL,NULL,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 - fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',NULL,'2025-02-12 17:39:40',NULL,NULL,NULL,NULL,NULL,'aaa.with1.home.lan','osuy6m0f5xtl','demokey','0','aaa.with1.home.lan','dbnSE8YB6jGm','3306','dbu8MhF1Dwcl','demokey',NULL,NULL,NULL,'Europe/Paris',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(13,'2025-06-26 17:54:04',14,NULL,NULL,NULL,'0',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'0',NULL,NULL,NULL,NULL,NULL,NULL);
/*!40000 ALTER TABLE `llx_contrat_extrafields` ENABLE KEYS */;
UNLOCK TABLES;
@ -78962,10 +78959,10 @@ INSERT INTO `llx_societe_rib` VALUES
(2,1,'ban',10,'2023-02-06 14:28:24','2025-04-08 08:59:57','NLTechno','aaaa','','','','','LIABLT2XXXX',NULL,'FR76 1223 9000 0740 4608 0100 091',NULL,'','','',1,NULL,NULL,NULL,'sepamandate','societe/10/Mandat SEPA 10-NLTechno-UMR-CU1212-0005-2-1675704504.pdf','UMR-CU1212-0005-2-1675704504',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL),
(3,1,'ban',33,'2023-02-21 21:33:04','2023-02-22 00:33:04','aaainlux','aaa','','','','','aaa',NULL,'aaa',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'UMR-2302212133-3-CU2212-00026',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL),
(4,1,'card',33,'2023-02-21 22:26:00','2023-02-22 01:26:00','aa','',NULL,NULL,'',NULL,NULL,NULL,NULL,NULL,NULL,'aa',NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,'',1,2032,'FR',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(5,1,'ban',1,'2023-03-08 06:41:28','2025-06-26 22:04:48','Indian SAS RIB','dfgdfgfd','','','','','LIABLT2XXXX',NULL,'dolcrypt:AES-256-CTR:6c5e3bcfba8c0873:sGWo/KYhvG8bw/oDC1uxal95cpvQLuKdzDGk86DYpdV2',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'RUM-2303080641-5-CU1212-0007',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL),
(6,1,'ban',39,'2025-01-03 16:11:35','2025-01-03 15:11:37','test','test','','','','','LIABLT2XXXX',NULL,'dolcrypt:AES-256-CTR:d0fbb5f8f1882d9f:QruV8ONPL6fQK4ew6aDzI4VSdBU=',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'8ANKF3PEOTZ53TR4','2025-01-03','RCUR',NULL,NULL,'sepa_debit',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'pm_1QdCXECxfvxGwHdwPnN4agJk',0,'mandate_1QdCXECxfvxGwHdwIdo2yLTd',NULL,'cus_test@sk_test_xxx',NULL,NULL,NULL,'StripeTest',NULL),
(7,1,'ban',39,'2025-01-03 16:21:39','2025-01-03 15:21:56','Bank Testldr1','test2','','','','','',NULL,'dolcrypt:AES-256-CTR:2143648571f74d32:ohNxpDnLCHNMP97+7XVn5i7zLNc=',NULL,'','','',0,NULL,NULL,NULL,NULL,NULL,'SDB8CASXISKK0R7L','2025-01-03','FRST',NULL,NULL,'sepa_debit',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'pm_1QdChDCxfvxGwHdw57zEzGtC',1,'mandate_1QdChDCxfvxGwHdwvIt0244D',NULL,'cus_test@sk_test_xxx',NULL,NULL,NULL,'StripeTest',NULL),
(9,1,'ban',62,'2025-06-26 21:41:42','2025-06-26 21:41:42','Banque ddd','Banque ddd','','','','','aaa',NULL,'dolcrypt:AES-256-CTR:ef6a60cae760f8d1:Q8YW',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'RUM-2506262141-9-CU2506-0003',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL);
(5,1,'ban',1,'2023-03-08 06:41:28','2025-06-26 22:04:48','Indian SAS RIB','dfgdfgfd','','','','','LIABLT2XXXX',NULL,'val1',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'RUM-2303080641-5-CU1212-0007',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL),
(6,1,'ban',39,'2025-01-03 16:11:35','2025-01-03 15:11:37','test','test','','','','','LIABLT2XXXX',NULL,'val2',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'8ANKF3PEOTZ53TR4','2025-01-03','RCUR',NULL,NULL,'sepa_debit',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'pm_1QdCXECxfvxGwHdwPnN4agJk',0,'mandate_1QdCXECxfvxGwHdwIdo2yLTd',NULL,'cus_test@sk_test_xxx',NULL,NULL,NULL,'StripeTest',NULL),
(7,1,'ban',39,'2025-01-03 16:21:39','2025-01-03 15:21:56','Bank Testldr1','test2','','','','','',NULL,'val3',NULL,'','','',0,NULL,NULL,NULL,NULL,NULL,'SDB8CASXISKK0R7L','2025-01-03','FRST',NULL,NULL,'sepa_debit',NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'pm_1QdChDCxfvxGwHdw57zEzGtC',1,'mandate_1QdChDCxfvxGwHdwvIt0244D',NULL,'cus_test@sk_test_xxx',NULL,NULL,NULL,'StripeTest',NULL),
(9,1,'ban',62,'2025-06-26 21:41:42','2025-06-26 21:41:42','Banque ddd','Banque ddd','','','','','aaa',NULL,'val4',NULL,'','','',1,NULL,NULL,NULL,NULL,NULL,'RUM-2506262141-9-CU2506-0003',NULL,'FRST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,'',1,NULL,NULL,'',NULL,NULL,NULL,NULL,NULL);
/*!40000 ALTER TABLE `llx_societe_rib` ENABLE KEYS */;
UNLOCK TABLES;
@ -79918,13 +79915,13 @@ CREATE TABLE `llx_user` (
LOCK TABLES `llx_user` WRITE;
/*!40000 ALTER TABLE `llx_user` DISABLE KEYS */;
INSERT INTO `llx_user` VALUES
(1,'2012-07-08 13:20:11','2025-03-13 09:13:00',NULL,NULL,'aeinstein',0,'','',NULL,1,NULL,NULL,'$2y$10$lIvMb5RJjxqmd6OxnZLqvuLZGOXj3gxIQhZQUqcY8fQTyh0cTtUpa',NULL,'dolcrypt:AES-256-CTR:10fbb3f05469219f:vCpWlcfDIoN6yOj2yGQ1WsOCfB8i2cjEKOAhNzPwf/A=','Einstein','Albert','','123456789','','','','aeinstein@example.com','','[]','',0,NULL,NULL,NULL,'','2017-10-05 08:32:44','2017-10-03 11:43:50',NULL,'',1,'alberteinstein.jpg',NULL,NULL,14,NULL,NULL,NULL,'','','',NULL,NULL,'aaaaff','',NULL,0,'',0,NULL,NULL,NULL,44.00000000,'man','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(1,'2012-07-08 13:20:11','2025-03-13 09:13:00',NULL,NULL,'aeinstein',0,'','',NULL,1,NULL,NULL,'$2y$10$lIvMb5RJjxqmd6OxnZLqvuLZGOXj3gxIQhZQUqcY8fQTyh0cTtUpa',NULL,'demokey','Einstein','Albert','','123456789','','','','aeinstein@example.com','','[]','',0,NULL,NULL,NULL,'','2017-10-05 08:32:44','2017-10-03 11:43:50',NULL,'',1,'alberteinstein.jpg',NULL,NULL,14,NULL,NULL,NULL,'','','',NULL,NULL,'aaaaff','',NULL,0,'',0,NULL,NULL,NULL,44.00000000,'man','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(2,'2012-07-08 13:54:48','2025-05-05 12:08:56',NULL,NULL,'demo',1,'','',NULL,1,NULL,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Doe','David','Trainee','09123123','','','','daviddoe@example.com','','[]','',0,NULL,NULL,NULL,'','2018-07-30 23:10:54','2018-07-30 23:04:17',NULL,'',1,'person9.jpeg',NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,NULL,NULL,NULL,35.00000000,'man','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(3,'2012-07-11 16:18:59','2025-05-05 14:48:17',NULL,NULL,'pcurie',1,'','',NULL,1,NULL,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Curie','Pierre','','','','','','pcurie@example.com','','[]','',0,NULL,NULL,2,'','2014-12-21 17:38:55',NULL,NULL,'',1,'dolicloud_avent_saas.png',NULL,NULL,14,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,NULL,NULL,NULL,39.00000000,'','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(4,'2015-01-23 17:52:27','2025-05-05 14:48:18',NULL,NULL,'bbookkeeper',1,'','',NULL,1,NULL,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Bookkeeper','Bob','Bookkeeper','','','','','bbookkeeper@example.com','','{\"skype\":\"skypebbookkeeper\"}','',0,17,6,NULL,'','2015-02-25 10:18:41','2015-01-23 17:53:20',NULL,'',1,'person8.jpeg',NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,NULL,NULL,NULL,16.00000000,'man','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(10,'2017-10-03 11:47:41','2023-03-15 15:07:13',NULL,NULL,'mcurie',1,NULL,NULL,NULL,1,0,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Curie','Marie','','','','','','mcurie@example.com','','[]','',0,NULL,NULL,NULL,'',NULL,NULL,NULL,'',1,'mariecurie.jpg',NULL,NULL,14,NULL,NULL,NULL,'','','',NULL,NULL,'ffaaff','',NULL,0,NULL,0,NULL,NULL,NULL,44.00000000,'woman',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,-1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(11,'2017-10-05 09:07:52','2023-03-15 15:07:13',NULL,NULL,'zzeceo',1,NULL,'',NULL,1,0,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Zeceo','Zack','President - CEO','','','','','zzeceo@example.com','','{\"facebook\":\"\",\"skype\":\"\",\"twitter\":\"\",\"linkedin\":\"\",\"instagram\":\"\",\"snapchat\":\"\",\"googleplus\":\"\",\"youtube\":\"\",\"whatsapp\":\"\",\"tumblr\":\"\",\"vero\":\"\",\"viadeo\":\"\",\"slack\":\"\",\"xing\":\"\",\"meetup\":\"\",\"pinterest\":\"\",\"flickr\":\"\",\"500px\":\"\",\"giphy\":\"\",\"gifycat\":\"\",\"dailymotion\":\"\",\"vimeo\":\"\",\"periscope\":\"\",\"twitch\":\"\",\"discord\":\"\",\"wikipedia\":\"\",\"reddit\":\"\",\"quora\":\"\",\"tripadvisor\":\"\",\"mastodon\":\"\",\"diaspora\":\"\",\"viber\":\"\",\"github\":\"\"}','',0,NULL,NULL,NULL,'','2017-10-05 22:48:08','2017-10-05 21:18:46',NULL,'',1,'person4.jpeg',NULL,NULL,NULL,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,NULL,0,NULL,NULL,NULL,39.00000000,NULL,'','2019-06-10 00:00:00',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(12,'2017-10-05 09:09:46','2025-03-27 23:27:43',NULL,12,'admin',0,'','',NULL,1,NULL,NULL,'$2y$10$MiDs0GVn0ksYbOHw8XgAf.oEihYvLI0ZYd0PSVq7/6ret6gifWSh6',NULL,'dolcrypt:AES-256-CTR:10fbb3f05469219f:5nJ/t5SbepR61dTsy2pTYfGEZS5j+bj3Ds0FN0OVM5M=','Adminson','Alice','Admin Technical','','','','','laurent@destailleur.fr','','[]','Alice - 123',1,NULL,NULL,NULL,'kmlk','2025-07-10 13:00:34','2025-07-09 16:26:18',NULL,'',1,NULL,NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,2700.00000000,NULL,NULL,39.00000000,'woman','',NULL,NULL,'generic_user_odt','1985-09-15',NULL,NULL,NULL,NULL,NULL,'127.0.0.1','127.0.0.1','2025-03-27 23:27:43',NULL,NULL,'',NULL,'2025-03-27 23:27:38',NULL),
(12,'2017-10-05 09:09:46','2025-03-27 23:27:43',NULL,12,'admin',0,'','',NULL,1,NULL,NULL,'$2y$10$MiDs0GVn0ksYbOHw8XgAf.oEihYvLI0ZYd0PSVq7/6ret6gifWSh6',NULL,'demokey','Adminson','Alice','Admin Technical','','','','','laurent@destailleur.fr','','[]','Alice - 123',1,NULL,NULL,NULL,'kmlk','2025-07-10 13:00:34','2025-07-09 16:26:18',NULL,'',1,NULL,NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,2700.00000000,NULL,NULL,39.00000000,'woman','',NULL,NULL,'generic_user_odt','1985-09-15',NULL,NULL,NULL,NULL,NULL,'127.0.0.1','127.0.0.1','2025-03-27 23:27:43',NULL,NULL,'',NULL,'2025-03-27 23:27:38',NULL),
(13,'2017-10-05 21:29:35','2025-04-15 13:30:44',NULL,NULL,'ccommercy',1,'','',NULL,1,NULL,NULL,'$2y$10$KTaKE0NyYyJSCogsxtwR.eADst17XYMrOWlsFfVLR60IbjANIVLHK',NULL,NULL,'Commercy','Coraly','Commercial leader','','','','','ccommercy@example.com','','{\"facebook\":\"\",\"skype\":\"\",\"twitter\":\"\",\"linkedin\":\"\",\"instagram\":\"\",\"snapchat\":\"\",\"googleplus\":\"\",\"youtube\":\"\",\"whatsapp\":\"\",\"tumblr\":\"\",\"vero\":\"\",\"viadeo\":\"\",\"slack\":\"\",\"xing\":\"\",\"meetup\":\"\",\"pinterest\":\"\",\"flickr\":\"\",\"500px\":\"\",\"giphy\":\"\",\"gifycat\":\"\",\"dailymotion\":\"\",\"vimeo\":\"\",\"periscope\":\"\",\"twitch\":\"\",\"discord\":\"\",\"wikipedia\":\"\",\"reddit\":\"\",\"quora\":\"\",\"tripadvisor\":\"\",\"mastodon\":\"\",\"diaspora\":\"\",\"viber\":\"\",\"github\":\"\"}','',0,NULL,NULL,NULL,'',NULL,NULL,NULL,'',1,'person7.jpeg',NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,'',0,1890.00000000,NULL,NULL,25.00000000,'woman','','2018-09-11 00:00:00',NULL,NULL,'1998-12-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',NULL,NULL,NULL),
(14,'2017-10-05 21:33:33','2023-03-15 15:07:36',NULL,NULL,'sscientol',1,NULL,NULL,NULL,1,0,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Scientol','Sam','Scientist leader','','','','','sscientol@example.com','','[]','',0,NULL,NULL,NULL,'',NULL,NULL,NULL,'',1,'person3.jpeg',NULL,NULL,11,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,NULL,0,3500.00000000,NULL,NULL,39.00000000,NULL,NULL,'2018-07-03 00:00:00',NULL,NULL,NULL,NULL,NULL,NULL,NULL,-1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(16,'2017-10-05 22:47:52','2025-01-30 14:37:22',NULL,NULL,'ccommerson',1,NULL,NULL,NULL,1,0,NULL,'$2y$10$Hgawd0DFS2bgBiM6rJuAZ.ff250vlm111HVWBJQvRzRq5hNijLxam',NULL,NULL,'Charle1','Commerson','Sale representative','','','','','ccommerson@example.com','','[]','',0,NULL,NULL,NULL,'','2017-10-05 23:46:24','2017-10-05 23:37:31',NULL,'',0,'person1.jpeg',NULL,NULL,13,NULL,NULL,NULL,'','','',NULL,NULL,'','',NULL,0,NULL,0,2900.00000000,NULL,NULL,39.00000000,NULL,NULL,'2019-09-01 00:00:00',NULL,NULL,'1976-02-05',NULL,NULL,NULL,NULL,-1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -80120,7 +80117,7 @@ INSERT INTO `llx_user_param` VALUES
(12,1,'MAIN_BOXES_11','1'),
(12,1,'MAIN_BOXES_2','1'),
(12,1,'MAIN_BOXES_27','1'),
(12,1,'MAIN_LANG_DEFAULT','fr_FR'),
(12,1,'MAIN_LANG_DEFAULT','auto'),
(12,1,'MAIN_SELECTEDFIELDS_/dolibarr_4.0/htdocs/adherents/list.php','d.zip,d.ref,d.lastname,d.firstname,d.company,d.login,d.morphy,t.libelle,d.email,d.datefin,d.statut,'),
(12,1,'MAIN_SELECTEDFIELDS_accountancycustomerlist','l.rowid,f.ref,f.datef,p.ref,l.total_ht,l.tva_tx,s.nom,co.label,s.tva_intra,aa.data_suggest,aa.account_number,'),
(12,1,'MAIN_SELECTEDFIELDS_accountancysupplierlines','l.rowid,f.ref,f.datef,p.ref,l.description,l.total_ht,l.tva_tx,s.nom,co.label,s.tva_intra,aa.account_number,'),

View file

@ -84,7 +84,7 @@ if (empty($sourceserver) || empty($server) || empty($login) || empty($sourcefile
print "Usage: $script_file login@server:/src/file.(sql|gz|bz2) passssh databaseserver databasename loginbase passbase\n";
print "Return code: 0 if success, <>0 if error\n";
print "Warning, this script may take a long time.\n";
exit(-1);
exit(1);
}
@ -106,7 +106,7 @@ $connection = ssh2_connect($server, 22);
if ($connection) {
if (!@ssh2_auth_password($connection, $login, $password)) {
dol_syslog("Could not authenticate with username ".$login." . and password ".preg_replace('/./', '*', $password), LOG_ERR);
exit(-5);
exit(5);
} else {
//$stream = ssh2_exec($connection, '/usr/bin/php -i');
/*
@ -143,7 +143,7 @@ if ($connection) {
}
} else {
print 'Failed to connect to ssh2 to '.$server;
exit(-6);
exit(6);
}

View file

@ -72,7 +72,7 @@ print "Update dates to current year for database name = ".$db->database_name."\n
if (empty($confirm)) {
print "Usage: $script_file confirm\n";
print "Return code: 0 if success, <>0 if error\n";
exit(-1);
exit(1);
}

View file

@ -2,33 +2,33 @@
#php_admin_value sendmail_path "/usr/sbin/sendmail -t -i"
#php_admin_value mail.force_extra_parameters "-f postmaster@mydomain.com"
#php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f postmaster@mydomain.com"
php_admin_value open_basedir /tmp/:/home/.../htdocs:/home/.../dolibarr_documents:
# Add this to use a custom apparmor profile when using apache php handler
<IfModule mod_apparmor.c>
AADefaultHatName sellyoursaas-instances
</IfModule>
# The URLs of the web site
ServerName myvirtualalias
ServerAlias myvirtualalias
UseCanonicalName On
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 20
AddDefaultCharset UTF-8
# Detect if we are using DoliDroid
#SetEnvIf User-Agent DoliDroid dolidroid
# The directory and permissions for the web site
DocumentRoot "/home/.../htdocs"
<Directory /home/.../htdocs/>
@ -36,24 +36,19 @@
Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
Require all granted
# To restrict access by a HTTP basic auth
# To restrict access by a HTTP basic auth
#AuthType Basic
#AuthName "Authenticate to backoffice"
#AuthUserFile /etc/apache2/.htpasswd
#require valid-user
</Directory>
# Leaving /public and /api, /dav, .well_known but also wrappers for document, viewimage and public json/img accessible to everyone
# Leaving /public, /dav and /.well_known directory accessible to everyone
<Directory /home/admin/wwwroot/dolibarr/htdocs/public/>
AuthType None
Satisfy any
Require all granted
</Directory>
<Directory /home/admin/wwwroot/dolibarr/htdocs/api/>
AuthType None
Satisfy any
Require all granted
</Directory>
<Directory /home/admin/wwwroot/dolibarr/htdocs/dav/>
AuthType None
Satisfy any
@ -64,6 +59,14 @@
Satisfy any
Require all granted
</Directory>
# You may also want to allow access to everyone to wrappers for api, document, viewimage, manifest and public json/img
# but if you can avoid it, it is better.
<Files /home/admin/wwwroot/dolibarr/htdocs/api/index.php>
AuthType None
Satisfy any
Require all granted
</Files>
<Files ~ "(document\.php|viewimage\.php|\.js\.php|\.json\.php|\.js|\.css\.php|\.css|\.gif|\.png|\.svg|\.woff2|favicon\.ico)$">
AuthType None
Satisfy any
@ -71,11 +74,11 @@
</Files>
# Log directives
# Log directives
ErrorLog /var/log/apache2/myvirtualalias_error_log
TransferLog /var/log/apache2/myvirtualalias_access_log
# Compress is done on resources of type php pages, text file export, css and javascript
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript
AddType text/javascript .jgz
@ -92,21 +95,21 @@
ExpiresByType text/javascript A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType application/javascript A2592000
# To enable the SSL if the certificate file exists
<IfFile "/etc/letsencrypt/live/www.mydomain.com/cert.pem">
SSLEngine On
# If both key and certificate are stored in the same file, only the
# SSLCertificateFile directive is needed.
SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
#RewriteEngine on
#RewriteCond %{SERVER_PORT} ^80$
#RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
</IfFile>
</VirtualHost>

View file

@ -28,8 +28,15 @@
<rule ref="Internal.NoCodeFound" />
<!-- Rules from Generic Standard -->
<!--
<rule ref="PSR12.Files.OpenTag">
<properties>
<property name="ignoreIndent" value="true"/>
</properties>
</rule>
<exclude name="PSR12.WhiteSpace.ScopeIndent"/>
-->
<!-- We want to allow empty statement: It allows to put some code comments into the else for examples -->
<rule ref="Generic.CodeAnalysis.EmptyStatement">
@ -134,7 +141,7 @@
<rule ref="Generic.Formatting.SpaceAfterCast" />
<rule ref="Generic.Functions.CallTimePassByReference" />
<!-- <rule ref="Generic.Functions.CallTimePassByReference" /> This rule does not exists anymore -->
<rule ref="Generic.Functions.FunctionCallArgumentSpacing" />

5
dev/setup/git/README.md Normal file
View file

@ -0,0 +1,5 @@
To enable a default git commit template:
git config --local commit.template gitmessage
To enable the git hook pre-commit, to make CI validation at commit:
See the file pre-commit/README.md

12
dev/setup/git/hooks/msg-commit Executable file
View file

@ -0,0 +1,12 @@
#!/bin/sh
# Hook to force a prefix on commits
commit_msg_file=$1
first_line=$(head -n1 "$commit_msg_file")
if echo "$first_line" | grep -Eqi '^(QUAL|SEC|PERF|FIX|CLOSE|NEW|Clean code|Debug[CSS)'; then
exit 0
else
echo "The commit message must start with QUAL, SEC, PERF, FIX, CLOSE, NEW, Clean code, Debug, CSS ..."
exit 1
fi

View file

@ -12,10 +12,10 @@ HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
if [ -x "$INSTALL_PYTHON" ]; then
exec "$INSTALL_PYTHON" -mpre_commit "${ARGS[@]}" 1>&2
exec "$INSTALL_PYTHON" -mpre_commit "${ARGS[@]}" 1>&2
elif command -v pre-commit > /dev/null; then
exec pre-commit "${ARGS[@]}" 1>&2
exec pre-commit "${ARGS[@]}" 1>&2
else
echo 'pre-commit not found. Did you forget to activate your virtualenv?' 1>&2
exit 1
echo 'pre-commit not found. Did you forget to activate your virtualenv?' 1>&2
exit 1
fi

View file

@ -124,14 +124,14 @@ $urlgit = 'https://github.com/Dolibarr/dolibarr/blob/develop/';
$output_arrproj = array();
$output_arrdep = array();
if ($dirscc != 'disabled') {
$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc . --exclude-dir=htdocs/includes,htdocs/custom,htdocs/theme/common/fontawesome-5,htdocs/theme/common/octicons';
$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc . --exclude-dir=htdocs/custom,htdocs/includes,htdocs/public/includes,htdocs/theme/common/fontawesome-5,htdocs/public/theme/common/fontawesome-5 --cocomo-project-type semi-detached';
print 'Execute SCC to count lines of code in project: '.$commandcheck."\n";
$resexecproj = 0;
exec($commandcheck, $output_arrproj, $resexecproj);
// Count lines of code of dependencies
$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc htdocs/includes htdocs/theme/common/fontawesome-5 htdocs/theme/common/octicons';
$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc htdocs/includes htdocs/public/includes htdocs/theme/common/fontawesome-5 htdocs/public/theme/common/fontawesome-5 --cocomo-project-type semi-detached';
print 'Execute SCC to count lines of code in dependencies: '.$commandcheck."\n";
$resexecdep = 0;
exec($commandcheck, $output_arrdep, $resexecdep);
@ -149,7 +149,7 @@ $phpstanversion = $output_arrver[0];
$output_arrtd = array();
if ($dirphpstan != 'disabled') {
$commandcheck = ($dirphpstan ? $dirphpstan.'/' : '').'phpstan --level='.$PHPSTANLEVEL.' -v analyze -a dev/build/phpstan/bootstrap.php --memory-limit 5G --error-format=github -c ~/preview.dolibarr.org/dolibarr/phpstan_apstats.neon';
$commandcheck = ($dirphpstan ? $dirphpstan.'/' : '').'phpstan --level='.$PHPSTANLEVEL.' -v analyze -a dev/build/phpstan/bootstrap.php --memory-limit 5G --error-format=github -c phpstan_apstats.neon';
print 'Execute PHPStan to get the technical debt: '.$commandcheck."\n";
$resexectd = 0;
exec($commandcheck, $output_arrtd, $resexectd);
@ -254,19 +254,20 @@ foreach (array('proj', 'dep') as $source) {
}
// Get stats on nb of commits
/*
$nbofmonth = 2;
$delay = (3600 * 24 * 30 * $nbofmonth);
// Get stats on nb of commits
$commandcheck = "git log --all --shortstat --no-renames --no-merges --use-mailmap --pretty=".escapeshellarg('format:%cI;%H;%aN;%aE;%ce;%s')." --since=".dol_print_date(dol_now() - $delay, '%Y-%m-%d'); // --since= --until=...
print 'Execute git log to get list of commits: '.$commandcheck."\n";
$output_arrglpu = array();
$resexecglpu = 0;
//exec($commandcheck, $output_arrglpu, $resexecglpu);
*/
// Get git information for security alerts
$nbofmonth = 3;
$nbofmonth = 6;
$delay = (3600 * 24 * 30 * $nbofmonth);
$arrayofalerts = array();
@ -275,14 +276,14 @@ print 'Execute git log to get commits related to security: '.$commandcheck."\n";
$output_arrglpu = array();
$resexecglpu = 0;
exec($commandcheck, $output_arrglpu, $resexecglpu);
foreach ($output_arrglpu as $val) {
foreach ($output_arrglpu as $valgitlog) { // The most recent lines are first.
// Parse the line to split interesting data
$tmpval = cleanVal2($val);
$tmpval = cleanVal2($valgitlog);
if (preg_match('/(#yogosha|CVE|Sec:|Sec\s|Sec$)/i', $tmpval['title'])) { // Recommended git comment: "Sec: Fix #..."
if (preg_match('/(#yogosha|CVE[\s\-]*\d|Sec:|Sec\s|Sec$)/i', $tmpval['title'])) { // Recommended git comment: "Sec: Fix #..."
$alreadyfound = '';
$alreadyfoundcommitid = '';
foreach ($arrayofalerts as $val) {
foreach ($arrayofalerts as $val) { // Loop on already found alerts
if ($val['issueidyogosha'] && $val['issueidyogosha'] == $tmpval['issueidyogosha']) { // Already in list
$alreadyfound = 'yogosha';
$alreadyfoundcommitid = $val['commitid'];
@ -298,7 +299,9 @@ foreach ($output_arrglpu as $val) {
$alreadyfoundcommitid = $val['commitid'];
break;
}
if ($val['title'] && $val['title'] == $tmpval['title']) { // Already in list
if ($val['title'] && $tmpval['title'] &&
(strpos($val['title'], $tmpval['title']) === 0 || strpos($val['title'], $tmpval['title']) > 0
|| strpos($tmpval['title'], $val['title']) === 0 || strpos($tmpval['title'], $val['title']) > 0)) { // Already in list
$alreadyfound = 'title';
$alreadyfoundcommitid = $val['commitid'];
break;
@ -346,70 +349,22 @@ foreach ($output_arrglpu as $val) {
/*var_dump($tmpval['commitid'].' '.$alreadyfoundcommitid);
var_dump($arrayofalerts[$alreadyfoundcommitid]['branch']);
var_dump($tmpval);*/
$arrayofalerts[$alreadyfoundcommitid]['commitidbis'][] = $tmpval['commitid']; // Concat the new commitid to the list of commitidbis array of the already found case.
if (empty($arrayofalerts[$alreadyfoundcommitid]['issueid']) && !empty($tmpval['issueid'])) { // If not Github was defined, we set it.
$arrayofalerts[$alreadyfoundcommitid]['issueid'] = $tmpval['issueid'];
}
if ($arrayofalerts[$alreadyfoundcommitid]['title'] != $tmpval['title']) { // Concat label of the new line to the already found one (if it differs)
$arrayofalerts[$alreadyfoundcommitid]['title'] .= ', '.preg_replace('/\.$/', '', $tmpval['title']);
}
$arrayofalerts[$alreadyfoundcommitid]['branch'] = array_merge($arrayofalerts[$alreadyfoundcommitid]['branch'], $tmpval['branch']);
$arrayofalerts[$alreadyfoundcommitid]['commitidbis'][] = $tmpval['commitid'];
}
}
}
/*
//$urlgit = 'https://api.github.com/search/issues?q=is:pr+repo:Dolibarr/dolibarr+created:>'.dol_print_date(dol_now() - $delay, "%Y-%m");
$urlgit = 'https://api.github.com/search/commits?q=repo:Dolibarr/dolibarr+yogosha+created:>'.dol_print_date(dol_now() - $delay, "%Y-%m");
// Count lines of code of application
$newurl = $urlgit.'+CVE';
$result = getURLContent($newurl);
print 'Execute GET on github for '.$newurl."\n";
if ($result && $result['http_code'] == 200) {
$arrayofalerts1 = json_decode($result['content']);
foreach ($arrayofalerts1->items as $val) {
$tmpval = cleanVal($val);
if (preg_match('/CVE/i', $tmpval['title'])) {
$arrayofalerts[$tmpval['number']] = $tmpval;
}
}
} else {
print 'Error: failed to get github response';
exit(-1);
}
$newurl = $urlgit.'+yogosha';
$result = getURLContent($newurl);
print 'Execute GET on github for '.$newurl."\n";
if ($result && $result['http_code'] == 200) {
$arrayofalerts2 = json_decode($result['content']);
foreach ($arrayofalerts2->items as $val) {
$tmpval = cleanVal($val);
if (preg_match('/yogosha:/i', $tmpval['title'])) {
$arrayofalerts[$tmpval['number']] = $tmpval;
}
}
} else {
print 'Error: failed to get github response';
exit(-1);
}
$newurl = $urlgit.'+Sec:';
$result = getURLContent($newurl);
print 'Execute GET on github for '.$newurl."\n";
if ($result && $result['http_code'] == 200) {
$arrayofalerts3 = json_decode($result['content']);
foreach ($arrayofalerts3->items as $val) {
$tmpval = cleanVal($val);
if (preg_match('/Sec:/i', $tmpval['title'])) {
$arrayofalerts[$tmpval['number']] = $tmpval;
}
}
} else {
print 'Error: failed to get github response';
exit(-1);
}
*/
$timeend = time();
@ -616,7 +571,7 @@ $html .= '<th class="right">Lines</th>';
$html .= '<th></th>';
$html .= '<th class="right">Blanks</th>';
$html .= '<th class="right">Comments</th>';
$html .= '<th class="right">Code</th>';
$html .= '<th class="right nowrap">Code (SLOC)</th>';
//$html .= '<td class="right">'.$val['Complexity'].'</td>';
$html .= '</tr>';
foreach (array('proj', 'dep') as $source) {
@ -733,12 +688,6 @@ $html .= <<<END
END;
$html .= '<!-- ';
foreach ($output_arrglpu as $line) {
$html .= $line."\n";
}
$html .= ' -->';
$html .= '</div>';
$html .= '</section>'."\n";
@ -793,19 +742,19 @@ $html .= '</div>';
$html .= '</section>'."\n";
// Project value
// Project value (COCOMO Model, use Basic / Semi-detached
$html .= '<section class="chapter" id="projectvalue">'."\n";
$html .= '<h2><span class="fas fa-dollar-sign pictofixedwidth"></span>Project value</h2>'."\n";
$html .= '<div class="boxallwidth">'."\n";
$html .= '<div class="box inline-box back1">';
$html .= 'COCOMO value<br><span class="small opacitymedium">(Basic organic model)</span><br>';
$html .= 'COCOMO value<br><span class="small opacitymedium">(Basic/Semi-detached model)</span><br>';
$html .= '<b>$'.formatNumber((empty($arraycocomo['proj']['currency']) ? 0 : $arraycocomo['proj']['currency']) + (empty($arraycocomo['dep']['currency']) ? 0 : $arraycocomo['dep']['currency']), 2).'</b>';
$html .= '</div>';
if (array_key_exists('proj', $arraycocomo)) {
$html .= '<div class="box inline-box back2">';
$html .= 'COCOMO effort<br><span class="small opacitymedium">(Basic organic model)</span><br>';
$html .= 'COCOMO effort<br><span class="small opacitymedium">(Basic/Semi-detached model)</span><br>';
$html .= '<b>'.formatNumber($arraycocomo['proj']['people'] * $arraycocomo['proj']['effort'] + $arraycocomo['dep']['people'] * $arraycocomo['dep']['effort']);
$html .= ' months people</b>';
$html .= '</div>';
@ -886,7 +835,7 @@ if (count($output_phan_json) != 0) {
$title_security_short = "Last security issues";
$title_security = ($project ? "[".$project."] " : "").$title_security_short;
$html .= '<section class="chapter" id="linesofcode">'."\n";
$html .= '<section class="chapter" id="securityalerts">'."\n";
$html .= '<h2><span class="fas fa-code pictofixedwidth"></span>'.$title_security_short.' <span class="opacitymedium">(last '.($nbofmonth != 1 ? $nbofmonth.' months' : 'month').')</span></h2>'."\n";
$html .= '<div class="boxallwidth">'."\n";
@ -962,7 +911,7 @@ foreach ($arrayofalerts as $key => $alert) {
}
$html .= '</td>';
// Description
// Title - Description
$html .= '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($alert['title']).'">'.dol_escape_htmltag($alert['title']).'</td>';
// Branches
@ -983,7 +932,7 @@ $html .= '</div>';
$html .= '</div>';
$html .= '<br>';
$html .= 'Note:Search is done in git repository on regexstring #yogosha|CVE|Sec:|Sec\s<br>';
$html .= 'Note:Search is done in git repository on regex string "#yogosha|CVE[\s\-]*\d|Sec:|Sec\s" (not case sensitive)<br>';
$html .= 'You can use this URL for RSS notifications: <a href="/'.$outputfilerss.'">'.$outputfilerss.'</a><br><br>';
$html .= '</section>';
@ -1188,7 +1137,7 @@ function cleanVal2($val)
$tmpval['issueid'] = '';
$tmpval['issueidyogosha'] = '';
$tmpval['issueidcve'] = '';
$tmpval['title'] = array_key_exists(5, $tmp) ? $tmp[5] : '';
$tmpval['title'] = array_key_exists(5, $tmp) ? preg_replace('/\.$/', '', $tmp[5]) : '';
$tmpval['created_at'] = array_key_exists(0, $tmp) ? $tmp[0] : '';
$tmpval['updated_at'] = '';
@ -1197,7 +1146,7 @@ function cleanVal2($val)
$tmpval['issueid'] = $reg[1];
}
if (preg_match('/CVE([0-9\-\s]+)/', $tmpval['title'], $reg)) {
$tmpval['issueidcve'] = preg_replace('/^\-/', '', trim($reg[1]));
$tmpval['issueidcve'] = preg_replace('/^\-/', '', preg_replace('/\s+/', '-', trim($reg[1])));
}
if (preg_match('/#yogosha(\d+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidyogosha'] = $reg[1];

View file

@ -9,42 +9,28 @@
*/
return [
// # Issue statistics:
// PhanUndeclaredProperty : 440+ occurrences
// PhanUndeclaredProperty : 420+ occurrences
// PhanTypeMismatchProperty : 100+ occurrences
// PhanTypeMismatchArgument : 80+ occurrences
// PhanUndeclaredGlobalVariable : 75+ occurrences
// PhanTypeMismatchArgumentNullable : 30+ occurrences
// PhanTypeExpectedObjectPropAccess : 20+ occurrences
// PhanTypeInvalidDimOffset : 20+ occurrences
// PhanTypeMismatchArgument : 70+ occurrences
// PhanUndeclaredGlobalVariable : 65+ occurrences
// PhanTypeMismatchArgumentNullable : 40+ occurrences
// PhanTypeInvalidDimOffset : 15+ occurrences
// PhanTypeMismatchDimFetch : 15+ occurrences
// PhanTypeMismatchArgumentProbablyReal : 9 occurrences
// PhanUndeclaredMethod : 9 occurrences
// PhanPossiblyUndeclaredGlobalVariable : 6 occurrences
// PhanTypeArraySuspiciousNull : 6 occurrences
// PhanTypeComparisonFromArray : 6 occurrences
// PhanParamTooMany : 4 occurrences
// PhanTypeExpectedObjectPropAccess : 5 occurrences
// PhanTypeMismatchArgumentProbablyReal : 5 occurrences
// PhanPluginDuplicateArrayKey : 4 occurrences
// PhanPluginDuplicateExpressionBinaryOp : 4 occurrences
// PhanPluginUndeclaredVariableIsset : 4 occurrences
// PhanTypeMismatchDimAssignment : 2 occurrences
// PhanTypeSuspiciousStringExpression : 2 occurrences
// PhanParamTooMany : 3 occurrences
// PhanPluginUndeclaredVariableIsset : 3 occurrences
// PhanPossiblyUndeclaredVariable : 1 occurrence
// PhanTypeExpectedObjectPropAccessButGotNull : 1 occurrence
// PhanTypeMismatchArgumentNullableInternal : 1 occurrence
// PhanTypeMismatchReturn : 1 occurrence
// Currently, file_suppressions and directory_suppressions are the only supported suppressions
'file_suppressions' => [
'htdocs/asset/class/asset.class.php' => ['PhanPluginUndeclaredVariableIsset', 'PhanTypeInvalidDimOffset'],
'htdocs/asset/tpl/depreciation_options_edit.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/asset/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/barcode/printsheet.php' => ['PhanPluginDuplicateExpressionBinaryOp'],
'htdocs/bom/bom_card.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/bom/tpl/objectline_create.tpl.php' => ['PhanTypeMismatchArgumentProbablyReal'],
'htdocs/bom/tpl/objectline_edit.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/bom/tpl/objectline_view.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/bookcal/availabilities_card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/bookcal/calendar_card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/bookcal/class/availabilities.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'],
'htdocs/bookcal/class/calendar.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'],
'htdocs/categories/viewcat.php' => ['PhanUndeclaredProperty'],
@ -55,12 +41,9 @@ return [
'htdocs/comm/mailing/index.php' => ['PhanUndeclaredProperty'],
'htdocs/comm/mailing/targetemailing.php' => ['PhanUndeclaredProperty'],
'htdocs/comm/propal/list.php' => ['PhanUndeclaredProperty'],
'htdocs/comm/propal/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/commande/class/api_orders.class.php' => ['PhanTypeMismatchArgument'],
'htdocs/commande/class/commande.class.php' => ['PhanUndeclaredProperty'],
'htdocs/commande/list.php' => ['PhanUndeclaredProperty'],
'htdocs/commande/list_det.php' => ['PhanTypeInvalidDimOffset'],
'htdocs/commande/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/bank/account_statement_document.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/bank/class/account.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/bank/class/paymentvarious.class.php' => ['PhanTypeMismatchArgument'],
@ -68,16 +51,13 @@ return [
'htdocs/compta/bank/various_payment/card.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/bank/various_payment/document.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/compta/bank/various_payment/info.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/compta/cashcontrol/cashcontrol_card.php' => ['PhanPluginDuplicateExpressionBinaryOp'],
'htdocs/compta/clients.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/facture/card.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanTypeMismatchArgumentProbablyReal'],
'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/facture/class/facture.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/localtax/card.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/localtax/clients.php' => ['PhanTypeExpectedObjectPropAccess'],
'htdocs/compta/localtax/index.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/localtax/list.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/paiement/card.php' => ['PhanUndeclaredProperty'],
@ -102,7 +82,7 @@ return [
'htdocs/core/class/canvas.class.php' => ['PhanParamTooMany', 'PhanUndeclaredMethod'],
'htdocs/core/class/ccountry.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/cgenericdic.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/commonobject.class.php' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonobject.class.php' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonpeople.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/conf.class.php' => ['PhanTypeMismatchArgumentNullableInternal', 'PhanTypeMismatchProperty'],
'htdocs/core/class/ctyperesource.class.php' => ['PhanUndeclaredProperty'],
@ -119,14 +99,12 @@ return [
'htdocs/core/lib/company.lib.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/lib/files.lib.php' => ['PhanUndeclaredProperty'],
'htdocs/core/lib/functions2.lib.php' => ['PhanUndeclaredProperty'],
'htdocs/core/lib/pdf.lib.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/lib/pdf.lib.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/lib/product.lib.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/lib/project.lib.php' => ['PhanUndeclaredProperty'],
'htdocs/core/lib/xcal.lib.php' => ['PhanUndeclaredProperty'],
'htdocs/core/menus/standard/auguria.lib.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/asset/mod_asset_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/barcode/mod_barcode_product_standard.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/bom/mod_bom_advanced.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/modules/cheque/doc/pdf_blochet.class.php' => ['PhanTypeMismatchArgumentProbablyReal'],
'htdocs/core/modules/cheque/modules_chequereceipts.php' => ['PhanTypeMismatchArgument'],
@ -176,7 +154,6 @@ return [
'htdocs/core/tpl/resource_view.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php' => ['PhanUndeclaredProperty'],
'htdocs/datapolicy/class/datapolicycron.class.php' => ['PhanTypeMismatchArgument'],
'htdocs/delivery/class/delivery.class.php' => ['PhanUndeclaredProperty'],
'htdocs/don/admin/donation.php' => ['PhanUndeclaredMethod'],
'htdocs/don/class/don.class.php' => ['PhanParamTooMany'],
@ -192,18 +169,14 @@ return [
'htdocs/expedition/class/expedition.class.php' => ['PhanUndeclaredProperty'],
'htdocs/expensereport/card.php' => ['PhanUndeclaredProperty'],
'htdocs/expensereport/class/expensereport.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'],
'htdocs/expensereport/payment/card.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/expensereport/payment/info.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/expensereport/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/externalsite/frames.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/fichinter/card-rec.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/fichinter/class/api_interventions.class.php' => ['PhanUndeclaredProperty'],
'htdocs/fichinter/class/fichinterrec.class.php' => ['PhanUndeclaredProperty'],
'htdocs/fichinter/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/filefunc.inc.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/fourn/class/api_supplier_orders.class.php' => ['PhanTypeMismatchArgumentProbablyReal'],
'htdocs/fourn/class/fournisseur.commande.class.php' => ['PhanUndeclaredProperty'],
'htdocs/fourn/commande/card.php' => ['PhanTypeMismatchDimAssignment', 'PhanTypeSuspiciousStringExpression', 'PhanUndeclaredProperty'],
'htdocs/fourn/commande/card.php' => ['PhanUndeclaredProperty'],
'htdocs/fourn/facture/card-rec.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/fourn/facture/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchProperty'],
'htdocs/fourn/facture/rapport.php' => ['PhanTypeMismatchArgument'],
@ -211,7 +184,6 @@ return [
'htdocs/holiday/card_group.php' => ['PhanTypeMismatchArgument'],
'htdocs/holiday/list.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/hrm/class/evaluation.class.php' => ['PhanUndeclaredProperty'],
'htdocs/hrm/class/evaluationdet.class.php' => ['PhanUndeclaredProperty'],
'htdocs/hrm/class/job.class.php' => ['PhanUndeclaredProperty'],
'htdocs/hrm/class/position.class.php' => ['PhanUndeclaredProperty'],
'htdocs/hrm/class/skill.class.php' => ['PhanUndeclaredProperty'],
@ -258,7 +230,6 @@ return [
'htdocs/projet/tasks.php' => ['PhanTypeMismatchArgument'],
'htdocs/projet/tasks/time.php' => ['PhanTypeInvalidDimOffset', 'PhanUndeclaredProperty'],
'htdocs/projet/tasks/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'],
'htdocs/public/eventorganization/subscriptionok.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/public/members/new.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/public/payment/newpayment.php' => ['PhanUndeclaredProperty'],
'htdocs/public/payment/paymentok.php' => ['PhanTypeMismatchArgumentProbablyReal'],
@ -308,18 +279,7 @@ return [
'htdocs/webportal/class/html.formcardwebportal.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/webportal/class/html.formlistwebportal.class.php' => ['PhanUndeclaredProperty'],
'htdocs/webportal/class/webportalpropal.class.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_actioncomm.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_category.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_contact.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_invoice.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_order.php' => ['PhanTypeInvalidDimOffset', 'PhanTypeMismatchArgument', 'PhanTypeSuspiciousStringExpression', 'PhanUndeclaredProperty'],
'htdocs/webservices/server_payment.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_productorservice.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_project.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_supplier_invoice.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_thirdparty.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_user.php' => ['PhanUndeclaredProperty'],
'htdocs/website/websiteaccount_card.php' => ['PhanUndeclaredProperty'],
],
// 'directory_suppressions' => ['src/directory_name' => ['PhanIssueName1', 'PhanIssueName2']] can be manually added if needed.
// (directory_suppressions will currently be ignored by subsequent calls to --save-baseline, but may be preserved in future Phan releases)

View file

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This is the phan config file used by .github/workflows/phan.yml
*/
@ -35,7 +35,8 @@ $sanitizeRegex
'restricthtmlallowclass',
'restricthtmlallowunvalid',
'restricthtmlnolink',
'restricthtmlallowlinkscript'
'restricthtmlallowlinkscript',
'url',
)
).')*$/';

View file

@ -23,7 +23,6 @@ parameters:
- htdocs/install/doctemplates/*
- htdocs/langs/*
- htdocs/modulebuilder/template/test/*
- htdocs/support/*
analyse:
- htdocs/includes/geoPHP/*
- htdocs/includes/markrogoyski/*

View file

@ -16,15 +16,15 @@ composer install
#### Usage
##### To make changes (Add --dry-run for test mode only)
##### To make changes (remove --dry-run for real run)
```shell
cd dev/tools/rector
./vendor/bin/rector process --dry-run
./vendor/bin/rector process --debug --dry-run
```
##### To make changes on a given directory
```shell
cd dev/tools/rector
./vendor/bin/rector process [--dry-run] [--clear-cache] ../../../htdocs/core/
./vendor/bin/rector process --debug [--dry-run] [--clear-cache] ../../../htdocs/core/
```

View file

@ -18,7 +18,7 @@
/**
* \file dev/tools/rector/rector.php
* \ingroup core
* \brief Toolt to run rector
* \brief Tool to run rector
*
* cd dev/tools/rector
* ./vendor/bin/rector process [--dry-run] [--clear-cache] ../../../htdocs/core/
@ -33,17 +33,22 @@ use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->phpVersion(PhpVersion::PHP_71);
//$rectorConfig->indent(' ', 4);
$rectorConfig->indent(' ', 4);
// Traits seems not supported correctly by rector without declaring them as bootstrapFiles
$arrayoftraitfiles = array(
__DIR__ . '/../../../htdocs/core/class/commonincoterm.class.php',
__DIR__ . '/../../../htdocs/core/class/commonpeople.class.php',
__DIR__ . '/../../../htdocs/core/class/commonsocialnetworks.class.php'
__DIR__ . '/../../../htdocs/core/class/commonsignedobject.class.php',
__DIR__ . '/../../../htdocs/core/class/commonsocialnetworks.class.php',
__DIR__ . '/../../../htdocs/core/class/commontrigger.class.php',
__DIR__ . '/../../../htdocs/core/class/doldeprecationhandler.class.php',
__DIR__ . '/../../../htdocs/subtotals/class/commonsubtotal.class.php',
);
$rectorConfig->bootstrapFiles($arrayoftraitfiles);
$rectorConfig->paths([
__DIR__ . '/../../../dev/',
__DIR__ . '/../../../htdocs/',
__DIR__ . '/../../../scripts/',
__DIR__ . '/../../../test/phpunit/',
@ -54,7 +59,8 @@ return static function (RectorConfig $rectorConfig): void {
'**/custom/**',
'**/vendor/**',
'**/rector/**', // Disable this line to test the "test.php" file.
__DIR__ . '/../../../htdocs/custom/',
__DIR__ . '/../../../dev/tools/phan/stubs/*',
__DIR__ . '/../../../htdocs/custom/*',
__DIR__ . '/../../../htdocs/install/doctemplates/*'
//'test.php',
]);
@ -82,12 +88,18 @@ return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(Dolibarr\Rector\Renaming\EmptyUserRightsToFunction::class);
$rectorConfig->rule(Dolibarr\Rector\Renaming\GlobalToFunction::class);
$rectorConfig->rule(Dolibarr\Rector\Renaming\UserRightsToFunction::class);
//$rectorConfig->rule(Dolibarr\Rector\Renaming\UsePositiveExit::class);
$rectorConfig->rule(Dolibarr\Rector\Renaming\UsePositiveExit::class);
// This fix <> into != but it breaks other rules, so added at end.
$rectorConfig->rule(Rector\CodeQuality\Rector\NotEqual\CommonNotEqualRector::class);
//$rectorConfig->rule(Rector\CodeQuality\Rector\NotEqual\CommonNotEqualRector::class);
/*
$rectorConfig->skip([
Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser::class,
Dolibarr\Rector\Renaming\GlobalToFunction::class
]);
*/
// Add all predefined rules to migrate to up to php 71.
// Warning this break tab spacing of arrays on several lines

View file

@ -63,7 +63,7 @@ class GlobalToFunction extends AbstractRector
'Change $conf->global to getDolGlobal in context (1) conf->global Operator Value or (2) function(conf->global...)',
[new CodeSample(
'$conf->global->CONSTANT',
'getDolGlobalInt(\'CONSTANT\')'
'getDolGlobalString|Int(\'CONSTANT\')'
)]
);
}
@ -228,14 +228,36 @@ class GlobalToFunction extends AbstractRector
return new Concat($leftConcat, $rightConcat);
}
// If a && b and a or b is conf->global, we replace a or/and b
if ($node instanceof BooleanAnd) {
$nodes = $this->resolveTwoNodeMatch($node);
if (!isset($nodes)) {
return;
// Transformation sur le nœud gauche
$changedone = 0;
if ($this->isGlobalVar($node->left)) {
$constName = $this->getConstName($node->left);
if (empty($constName)) {
return;
}
$node->left = new FuncCall(
new Name('getDolGlobalString'),
[new Arg($constName)]
);
$changedone++;
}
if ($this->isGlobalVar($node->right)) {
$constName = $this->getConstName($node->right);
if (empty($constName)) {
return;
}
$node->right = new FuncCall(
new Name('getDolGlobalString'),
[new Arg($constName)]
);
$changedone++;
}
/** @var Equal $node */
$node = $nodes->getFirstExpr();
if ($changedone) {
return $node;
}
}
@ -270,9 +292,42 @@ class GlobalToFunction extends AbstractRector
return;
}
// Now we process a comparison
$isconfglobal = $this->isGlobalVar($node->left);
if (!$isconfglobal) {
// The left side is not conf->global->xxx, so we leave
$isconfglobal = $this->isGlobalVar($node->right);
if (!$isconfglobal) {
// The left side and right side is not conf->global->xxx, so we leave
return;
}
// Right side is conf->global->xxx, but we can't know if we must use getDolGlobalInt or String,
// so we use getDolGlobalString if comparison is ==
if ($typeofcomparison == 'Equal') {
$constName = $this->getConstName($node->right);
if (empty($constName)) {
return;
}
// Test the type after the comparison conf->global->xxx to know the name of function
$typeleft = $node->left->getType();
switch ($typeleft) {
case 'Scalar_LNumber':
$funcName = 'getDolGlobalInt';
break;
case 'Scalar_String':
$funcName = 'getDolGlobalString';
break;
default: // Can be Expr_FuncCall
$funcName = 'getDolGlobalString';
break;
}
$node->right = new FuncCall(
new Name($funcName),
[new Arg($constName)]
);
return $node;
}
return;
}
@ -360,36 +415,6 @@ class GlobalToFunction extends AbstractRector
}
}
/**
* Get nodes with check empty
*
* @param BooleanAnd $booleanAnd A BooleandAnd
* @return TwoNodeMatch|null
*/
private function resolveTwoNodeMatch(BooleanAnd $booleanAnd): ?TwoNodeMatch
{
return $this->binaryOpManipulator->matchFirstAndSecondConditionNode(
$booleanAnd,
// Function to check if we are in the case $conf->global->... == $value
function (Node $node): bool {
if (!$node instanceof Equal) {
return \false;
}
return $this->isGlobalVar($node->left);
},
// !empty(...) || isset(...)
function (Node $node): bool {
if ($node instanceof BooleanNot && $node->expr instanceof Empty_) {
return $this->isGlobalVar($node->expr->expr);
}
if (!$node instanceof Isset_) {
return $this->isGlobalVar($node);
}
return \true;
}
);
}
/**
* Check if node is a global access with format conf->global->XXX
*

View file

@ -96,8 +96,6 @@ AADE_WEBSERVICE_USER
API
Accept
AccountancyErrorMismatchLetteringCode
AccountingAccount
AccountingCode
AccountingJournalType
ActionAC_
ActionAC_ALL_
@ -147,14 +145,12 @@ Banque
Barcode
BarcodeDesc
BarcodeStickersMask
BatchInformationNotfound
BillOfMaterialsLine
BlockLogNeedAmountsValue
BlockLogNeedElement
BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote
BlockedLogAuthorityUrl
BlockedLogSetup
BookCalSystem
Bookings
BoxTitleLast
BoxTitleLatest
@ -202,8 +198,6 @@ ConfirmActionMyObject
ConfirmActionTarget
ConfirmCloneMyObject
ConfirmCloneTask
ConfirmCreateAdherent
ConfirmDeleteAdherent
ConfirmDeleteIndividual
ConfirmDeleteReport
ConfirmDeleteWebsiteAccount
@ -291,7 +285,6 @@ EmailcollectorFilter
EmailingTargetSelector
Empty
End
EnterAnIP
EnterNameOfDictionnaryToDeleteDesc
Entries
ErrSCAAuthentication
@ -361,7 +354,6 @@ ErrorTechnicalError
ErrorThirdPartyIdIsMandatory
ErrorTicketIsNotValid
ErrorTitreAlreadyExists
ErrorUpdatingUsersCP
ErrorUserFetch
ErrorValueMustBeInteger
ErrorValueTooHigh
@ -433,7 +425,6 @@ Gzip
HTTPBasicPassword
HelpAbandonProductReturned
HideVersionLink
HolidayStarted
Hook
Hooks
IBANNotDefined
@ -619,7 +610,6 @@ PaymentCondition
PaymentConditionShort
PaymentDonation
PaymentHigherThanReminderToPaySupplier
PaymentSalary
PaymentSendToStripeTerminal
PaymentType
PaymentTypeShort
@ -643,10 +633,7 @@ PrintModule
PrintUserConfDesc
PrinterId
PrinterIdEmpty
PrinterLocation
PrinterNameEmpty
PrinterParameterEmpty
Printers
Printing
ProductCodeDesc
ProductFournisseurPrice
@ -810,7 +797,6 @@ Templates
TestPrinterTemplate
TestTemplateToPrinter
Theme
ThirdpartyHasNoDefaultBanAccount
ThisIsInformationOnDocumentToSign
ThisScreenAllowsYouToSignDocFrom
TicketCategoryShort
@ -847,8 +833,6 @@ UpdateUser
UpgradeHasBeenUnlocked
Url
Use of API for currency update is disabled by option MULTICURRENCY_DISABLE_SYNC_CURRENCYLAYER
UserRemovedFromGroup
UserSetInGroup
VCard
Vacant
ValidateAndSign
@ -874,7 +858,6 @@ Widgets
Windows
WorkingBoard
Workload
WrongAmount
XDebug
XmlCorrupted
Y
@ -1031,10 +1014,6 @@ PDF/A-3b
PartnershipSentByEMail
PdfTitle
ProcessingError
PurchaseOrder
PurchaseOrders
ReceptionSentByEMail
ReceptionValidated
Recruited
Ref. Product
RefNewContract
@ -1042,7 +1021,6 @@ Stable
Suggested
TicketMessageMailSignatureText
TicketSetupPage
Tiers
Timeline
Transfer
TryAnotherConnectionMode

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

1
htdocs/.gitignore vendored
View file

@ -21,7 +21,6 @@
/cabinetmed*
/webmail*
/conf/conf.php
/subtotal*
/abricot*
/nomenclature*
/of/

View file

@ -61,7 +61,7 @@ $search_import_key = GETPOST('search_import_key', 'alpha');
$search_reconcilable = GETPOST("search_reconcilable", 'int');
$search_centralized = GETPOST("search_centralized", 'int');
$search_active = GETPOST("search_active", 'int');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$confirm = GETPOST('confirm', 'alpha');
@ -98,20 +98,22 @@ if (!$sortorder) {
$sortorder = "ASC";
}
$object = new AccountingAccount($db);
$arrayfields = array(
'aa.account_number' => array('label' => "AccountNumber", 'checked' => '1'),
'aa.label' => array('label' => "Label", 'checked' => '1'),
'aa.labelshort' => array('label' => "LabelToShow", 'checked' => '1'),
'aa.labelshort' => array('label' => "ShortLabel", 'checked' => '1'),
'aa.account_parent' => array('label' => "Accountparent", 'checked' => '1'),
'aa.pcg_type' => array('label' => "Pcgtype", 'checked' => '1', 'help' => 'PcgtypeDesc'),
'categories' => array('label' => "AccountingCategories", 'checked' => '-1', 'help' => 'AccountingCategoriesDesc'),
'aa.reconcilable' => array('label' => "Reconcilable", 'checked' => '1'),
'aa.centralized' => array('label' => "Centralized", 'checked' => '1'),
'aa.centralized' => array('label' => "Centralized", 'checked' => '1', 'help' => 'CentralizedAccountHelp'),
'aa.import_key' => array('label' => "ImportId", 'checked' => '-1', 'help' => ''),
'aa.active' => array('label' => "Activated", 'checked' => '1')
);
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
if (!getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) {
unset($arrayfields['categories']);
unset($arrayfields['aa.reconcilable']);
}
@ -557,12 +559,10 @@ if ($resql) {
}
// Reconcilable
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print '<td class="liste_titre center">';
print $form->selectyesno('search_reconcilable', $search_reconcilable, 1, false, 1, 1, 'search_status onrightofpage width75');
print '</td>';
}
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print '<td class="liste_titre center">';
print $form->selectyesno('search_reconcilable', $search_reconcilable, 1, false, 1, 1, 'search_status onrightofpage width75');
print '</td>';
}
// Centralized
@ -574,10 +574,11 @@ if ($resql) {
// Active
if (!empty($arrayfields['aa.active']['checked'])) {
print '<td class="liste_titre center">';
print '<td class="liste_titre center parentonrightofpage">';
print $form->selectyesno('search_active', $search_active, 1, false, 1, 1, 'search_status onrightofpage width75');
print '</td>';
}
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre center maxwidthsearch">';
@ -614,12 +615,14 @@ if ($resql) {
print_liste_field_titre($arrayfields['aa.account_parent']['label'], $_SERVER["PHP_SELF"], "aa.account_parent", "", $param, '', $sortfield, $sortorder, 'left ');
$totalarray['nbfield']++;
}
// Main group
if (!empty($arrayfields['aa.pcg_type']['checked'])) {
print_liste_field_titre($arrayfields['aa.pcg_type']['label'], $_SERVER["PHP_SELF"], 'aa.pcg_type,aa.account_number', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.pcg_type']['help'], 1);
print_liste_field_titre($arrayfields['aa.pcg_type']['label'], $_SERVER["PHP_SELF"], 'aa.pcg_type,aa.account_number', '', $param, '', $sortfield, $sortorder, 'right ', $arrayfields['aa.pcg_type']['help'].'::-1', 1);
$totalarray['nbfield']++;
}
// Number of custom groups
if (!empty($arrayfields['categories']['checked'])) {
print_liste_field_titre($arrayfields['categories']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '', $arrayfields['categories']['help'], 1);
print_liste_field_titre($arrayfields['categories']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '', $arrayfields['categories']['help'].'::-1', 1);
$totalarray['nbfield']++;
}
@ -629,21 +632,19 @@ if ($resql) {
print $hookmanager->resPrint;
if (!empty($arrayfields['aa.import_key']['checked'])) {
print_liste_field_titre($arrayfields['aa.import_key']['label'], $_SERVER["PHP_SELF"], 'aa.import_key', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.import_key']['help'], 1);
print_liste_field_titre($arrayfields['aa.import_key']['label'], $_SERVER["PHP_SELF"], 'aa.import_key', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.import_key']['help'].'::-1', 1);
$totalarray['nbfield']++;
}
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print_liste_field_titre($arrayfields['aa.reconcilable']['label'], $_SERVER["PHP_SELF"], 'aa.reconcilable', '', $param, '', $sortfield, $sortorder, 'center ');
$totalarray['nbfield']++;
}
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print_liste_field_titre($arrayfields['aa.reconcilable']['label'], $_SERVER["PHP_SELF"], 'aa.reconcilable', '', $param, '', $sortfield, $sortorder, 'center ');
$totalarray['nbfield']++;
}
if (!empty($arrayfields['aa.centralized']['checked'])) {
print_liste_field_titre($arrayfields['aa.centralized']['label'], $_SERVER["PHP_SELF"], 'aa.centralized', '', $param, '', $sortfield, $sortorder);
print_liste_field_titre($arrayfields['aa.centralized']['label'], $_SERVER["PHP_SELF"], 'aa.centralized', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.centralized']['help'].'::-1', 1);
$totalarray['nbfield']++;
}
if (!empty($arrayfields['aa.active']['checked'])) {
print_liste_field_titre($arrayfields['aa.active']['label'], $_SERVER["PHP_SELF"], 'aa.active', '', $param, '', $sortfield, $sortorder);
print_liste_field_titre($arrayfields['aa.active']['label'], $_SERVER["PHP_SELF"], 'aa.active', '', $param, '', $sortfield, $sortorder, 'center ');
$totalarray['nbfield']++;
}
// Action column
@ -759,7 +760,7 @@ if ($resql) {
}
// Custom accounts
if (!empty($arrayfields['categories']['checked'])) {
print "<td>";
print '<td class="right">';
// TODO Get all custom groups labels the account is in
print dol_escape_htmltag($obj->fk_accounting_category);
print "</td>\n";
@ -783,23 +784,21 @@ if ($resql) {
}
}
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
// Activated or not reconciliation on an accounting account
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print '<td class="center">';
if (empty($obj->reconcilable)) {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$obj->rowid.'&action=enable&mode=1&token='.newToken().'">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print '</a>';
} else {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$obj->rowid.'&action=disable&mode=1&token='.newToken().'">';
print img_picto($langs->trans("Activated"), 'switch_on');
print '</a>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
// Activated or not reconciliation on an accounting account
if (!empty($arrayfields['aa.reconcilable']['checked'])) {
print '<td class="center">';
if (empty($obj->reconcilable)) {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$obj->rowid.'&action=enable&mode=1&token='.newToken().'">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print '</a>';
} else {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$obj->rowid.'&action=disable&mode=1&token='.newToken().'">';
print img_picto($langs->trans("Activated"), 'switch_on');
print '</a>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}

View file

@ -12,7 +12,7 @@
* Copyright (C) 2015 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -92,6 +92,8 @@ $search_country_id = GETPOST('search_country_id', 'int');
if ($user->socid > 0) {
accessforbidden();
}
$permissiontoeditchart = $user->hasRight('accounting', 'chartofaccount');
if (!$user->hasRight('accounting', 'chartofaccount')) {
accessforbidden();
}
@ -143,7 +145,6 @@ $tabhelp = array();
$tabhelp[31] = array('pcg_version' => $langs->trans("EnterAnyCode"));
/*
* Actions
*/
@ -198,32 +199,15 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Si verif ok et action add, on ajoute la ligne
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
if ($tabrowid[$id]) {
// Get free id for insert
$sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") as newid FROM ".$db->sanitize($tabname[$id]);
$result = $db->query($sql);
if ($result) {
$obj = $db->fetch_object($result);
$newid = ($obj->newid + 1);
} else {
dol_print_error($db);
}
}
// Add new entry
$sql = "INSERT INTO ".$db->sanitize($tabname[$id])." (";
// List of fields
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
$sql .= $db->sanitize($tabrowid[$id]).",";
}
$sql .= $db->sanitize($tabfieldinsert[$id]);
$sql .= ",active)";
$sql .= " VALUES(";
// List of values
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) {
$sql .= $newid.",";
}
$i = 0;
foreach ($listfieldinsert as $f => $value) {
if ($value == 'price' || preg_match('/^amount/i', $value) || $value == 'taux') {
@ -259,19 +243,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Si verif ok et action modify, on modifie la ligne
if ($ok && GETPOST('actionmodify', 'alpha')) {
if ($tabrowid[$id]) {
$rowidcol = $tabrowid[$id];
} else {
$rowidcol = "rowid";
}
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modifie valeur des champs
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
}
$i = 0;
foreach ($listfieldmodify as $field) {
if ($field == 'price' || preg_match('/^amount/i', $field) || $field == 'taux') {
@ -290,7 +265,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
$i++;
}
$sql .= " WHERE ".$rowidcol." = ".((int) $rowid);
$sql .= " WHERE rowid = ".((int) $rowid);
dol_syslog("actionmodify", LOG_DEBUG);
//print $sql;
@ -301,14 +276,9 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
if ($action == 'confirm_delete' && $confirm == 'yes') { // delete
if ($tabrowid[$id]) {
$rowidcol = $tabrowid[$id];
} else {
$rowidcol = "rowid";
}
$sql = "DELETE from ".$db->sanitize($tabname[$id])." WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid);
// delete
if ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontoeditchart) {
$sql = "DELETE from ".$db->sanitize($tabname[$id])." WHERE rowid = ".((int) $rowid);
dol_syslog("delete", LOG_DEBUG);
$result = $db->query($sql);
@ -322,7 +292,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete
}
// activate
if ($action == 'activate') {
if ($action == 'activate' && $permissiontoeditchart) {
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE rowid = ".((int) $rowid);
$result = $db->query($sql);
if (!$result) {
@ -331,7 +301,7 @@ if ($action == 'activate') {
}
// disable
if ($action == $acts[1]) {
if ($action == $acts[1] && $permissiontoeditchart) {
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE rowid = ".((int) $rowid);
$result = $db->query($sql);
if (!$result) {
@ -359,7 +329,7 @@ print load_fiche_titre($titre, $linkback, 'title_accountancy');
// Confirmation de la suppression de la ligne
if ($action == 'delete') {
print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.urlencode((string) ($page)).'&' : '').'sortfield='.urlencode((string) ($sortfield)).'&sortorder='.urlencode((string) ($sortorder)).'&rowid='.urlencode((string) ($rowid)).'&code='.urlencode((string) ($code)).'&id='.urlencode((string) ($id)), $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
print $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['page'=> $page, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'rowid' => $rowid, 'code' => $code, 'id' => $id]), $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
}
@ -607,36 +577,34 @@ if ($resql) {
}
}
// Can an entry be erased or disabled ?
$iserasable = 1;
$canbedisabled = 1;
$canbemodified = 1; // true by default
// $url = $_SERVER["PHP_SELF"].'?token='.newToken().($page ? '&page='.$page : '').'&sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')).'&code='.(!empty($obj->code) ? urlencode($obj->code) : '');
// $url .= '&'.$param.'&';
$url = $_SERVER["PHP_SELF"].'?token='.newToken().($page ? '&page='.$page : '').'&sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')).'&code='.(!empty($obj->code) ? urlencode($obj->code) : '');
$url .= '&'.$param.'&';
$query = [];
// decode and add param to query
parse_str($param, $query);
$query = array_merge($query, [
'action' => '',
'page' => $page,
'sortfield' => $sortfield,
'sortorder' => $sortorder,
'rowid' => (!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')),
'code' => $obj->code,
]);
// Active
print '<td class="center nowrap">';
if ($canbedisabled) {
print '<a href="'.$url.'action='.$acts[$obj->active].'">'.$actl[$obj->active].'</a>';
} else {
print $langs->trans("AlwaysActive");
}
$query['action'] = $acts[$obj->active];
print '<a href="'.dolBuildUrl($_SERVER["PHP_SELF"], $query, true).'">'.$actl[$obj->active].'</a>';
print "</td>";
// Modify link
if ($canbemodified) {
print '<td class="center"><a class="reposition editfielda" href="'.$url.'action=edit&token='.newToken().'">'.img_edit().'</a></td>';
} else {
print '<td>&nbsp;</td>';
}
$query['action'] = 'edit';
print '<td class="center"><a class="reposition editfielda" href="'.dolBuildUrl($_SERVER["PHP_SELF"], $query, true).'">'.img_edit().'</a></td>';
// Delete link
if ($iserasable) {
print '<td class="center"><a href="'.$url.'action=delete&token='.newToken().'">'.img_delete().'</a></td>';
} else {
print '<td>&nbsp;</td>';
}
$query['action'] = 'delete';
print '<td class="center"><a href="'.dolBuildUrl($_SERVER["PHP_SELF"], $query, true).'">'.img_delete().'</a></td>';
print "</tr>\n";
}
@ -700,16 +668,8 @@ function fieldListAccountModel($fieldlist, $obj = null, $tabname = '', $context
print '</td>';
}
} elseif ($fieldlist[$field] == 'type_cdr') {
if ($fieldlist[$field] == 'type_cdr') {
print '<td class="center">';
} else {
print '<td>';
}
if ($fieldlist[$field] == 'type_cdr') {
print $form->selectarray($fieldlist[$field], array(0 => $langs->trans('None'), 1 => $langs->trans('AtEndOfMonth'), 2 => $langs->trans('CurrentNext')), (!empty($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]} : ''));
} else {
print $form->selectyesno($fieldlist[$field], (!empty($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]} : ''), 1);
}
print '<td class="center">';
print $form->selectarray($fieldlist[$field], array(0 => $langs->trans('None'), 1 => $langs->trans('AtEndOfMonth'), 2 => $langs->trans('CurrentNext')), (!empty($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]} : ''));
print '</td>';
} elseif ($fieldlist[$field] == 'code' && isset($obj->{$fieldlist[$field]})) {
print '<td><input type="text" class="flat" value="'.(!empty($obj->{$fieldlist[$field]}) ? $obj->{$fieldlist[$field]} : '').'" size="10" name="'.$fieldlist[$field].'"></td>';

View file

@ -1,9 +1,9 @@
<?php
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 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
@ -77,7 +77,7 @@ if (GETPOST('cancel', 'alpha')) {
exit;
}
if ($action == 'add' && $user->hasRight('accounting', 'chartofaccount')) {
if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // already checked */) {
if (!$cancel) {
if (!$account_number) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
@ -132,7 +132,7 @@ if ($action == 'add' && $user->hasRight('accounting', 'chartofaccount')) {
}
}
}
} elseif ($action == 'edit' && $user->hasRight('accounting', 'chartofaccount')) {
} elseif ($action == 'edit' /* && $user->hasRight('accounting', 'chartofaccount') // already checked */) {
if (!$cancel) {
if (!$account_number) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
@ -245,7 +245,7 @@ if ($action == 'create') {
print '<td><input name="label" size="70" value="'.$object->label.'"></td></tr>';
// Label short
print '<tr><td>'.$langs->trans("LabelToShow").'</td>';
print '<tr><td>'.$langs->trans("ShortLabel").'</td>';
print '<td><input name="labelshort" size="70" value="'.$object->labelshort.'"></td></tr>';
// Account parent
@ -314,15 +314,15 @@ if ($action == 'create') {
// Account number
print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("AccountNumber").'</span></td>';
print '<td><input name="account_number" size="30" value="'.$object->account_number.'"></td></tr>';
print '<td><input class="minwidth300" name="account_number" value="'.$object->account_number.'"></td></tr>';
// Label
print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td>';
print '<td><input name="label" size="70" value="'.$object->label.'"></td></tr>';
print '<td><input class="minwidth500" name="label" value="'.$object->label.'"></td></tr>';
// Label short
print '<tr><td>'.$langs->trans("LabelToShow").'</td>';
print '<td><input name="labelshort" size="70" value="'.$object->labelshort.'"></td></tr>';
print '<tr><td>'.$langs->trans("ShortLabel").'</td>';
print '<td><input class="minwidth300" name="labelshort" value="'.$object->labelshort.'"></td></tr>';
// Account parent
print '<tr><td>'.$langs->trans("Accountparent").'</td>';
@ -386,7 +386,7 @@ if ($action == 'create') {
print '<td colspan="2">'.$object->label.'</td></tr>';
// Label to show
print '<tr><td class="titlefield">'.$langs->trans("LabelToShow").'</td>';
print '<tr><td class="titlefield">'.$langs->trans("ShortLabel").'</td>';
print '<td colspan="2">'.$object->labelshort.'</td></tr>';
// Account parent
@ -419,11 +419,11 @@ if ($action == 'create') {
*/
print '<div class="tabsAction">';
if ($user->hasRight('accounting', 'chartofaccount')) {
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Modify').'</a>';
} else {
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Modify').'</a>';
}
// if ($user->hasRight('accounting', 'chartofaccount')) { // already checked
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Modify').'</a>';
// } else {
// print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Modify').'</a>';
// }
// Delete
$permissiontodelete = $user->hasRight('accounting', 'chartofaccount');

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
/* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify

View file

@ -202,7 +202,7 @@ if ($result) {
if (getDolGlobalString('ACCOUNTANCY_FISCALYEAR_DEFAULT') == (int) $fiscalyearstatic->ref) {
print img_picto($langs->trans("Default"), 'on');
} else {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=setdefault&token='.newToken().'&value='.urlencode($fiscalyearstatic->ref).'&label='.urlencode($fiscalyearstatic->label).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("SetAsDefault"), 'off').'</a>';
print '<a class="reposition" href="'.dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'setdefault', 'value' => $fiscalyearstatic->ref, 'label'=>$fiscalyearstatic->label], true).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("SetAsDefault"), 'off').'</a>';
}
print '</td>';

View file

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2014-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@ -82,7 +82,7 @@ $permissiontoadd = $user->hasRight('accounting', 'fiscalyear', 'write');
if ($user->socid > 0) {
accessforbidden();
}
if (!$permissiontoadd) {
if (!$permissiontoadd) { // after this test $permissiontoadd is always true
accessforbidden();
}
@ -97,7 +97,7 @@ if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
if ($action == 'confirm_delete' && $confirm == "yes" && $permissiontoadd) {
if ($action == 'confirm_delete' && $confirm == "yes" /* && $permissiontoadd // always true */) {
$result = $object->delete($user);
if ($result >= 0) {
header("Location: fiscalyear.php");
@ -105,7 +105,7 @@ if ($action == 'confirm_delete' && $confirm == "yes" && $permissiontoadd) {
} else {
setEventMessages($object->error, $object->errors, 'errors');
}
} elseif ($action == 'add' && $permissiontoadd) {
} elseif ($action == 'add' /* && $permissiontoadd // always true */) {
if (!GETPOST('cancel', 'alpha')) {
$error = 0;
@ -147,7 +147,7 @@ if ($action == 'confirm_delete' && $confirm == "yes" && $permissiontoadd) {
header("Location: ./fiscalyear.php");
exit();
}
} elseif ($action == 'update' && $permissiontoadd) {
} elseif ($action == 'update' /* && $permissiontoadd // always true */) {
// Update record
if (!GETPOST('cancel', 'alpha')) {
$result = $object->fetch($id);
@ -169,7 +169,7 @@ if ($action == 'confirm_delete' && $confirm == "yes" && $permissiontoadd) {
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit();
}
} elseif ($action == 'reopen' && $permissiontoadd && getDolGlobalString('ACCOUNTING_CAN_REOPEN_CLOSED_PERIOD')) {
} elseif ($action == 'reopen' /* && $permissiontoadd // always true */ && getDolGlobalString('ACCOUNTING_CAN_REOPEN_CLOSED_PERIOD')) {
$result = $object->fetch($id);
$object->status = GETPOSTINT('status');

View file

@ -8,7 +8,7 @@
* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
* Copyright (C) 2017 Laurent Destailleur <eldy@destailleur.fr>
* Copyright (C) 2021 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -69,6 +69,7 @@ $formSetup = new FormSetup($db);
// Main options
$formSetup->newItem('BANK_DISABLE_DIRECT_INPUT')->setAsYesNo();
$formSetup->newItem('ACCOUNTANCY_COMBO_FOR_AUX')->setAsYesNo();
$item = $formSetup->newItem('ACCOUNTING_MANAGE_ZERO')->setAsYesNo();
@ -179,75 +180,73 @@ if ($action == 'updatemode') {
if ($action == 'update2') {
$error = 0;
if (!$error) {
foreach ($list as $constname) {
$constvalue = GETPOST($constname, 'alpha');
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
if ($error) {
setEventMessages($langs->trans("Error"), null, 'errors');
}
// option in section binding
foreach ($list_binding as $constname) {
$constvalue = GETPOST($constname, 'alpha');
if ($constname == 'ACCOUNTING_DATE_START_BINDING') {
$constvalue = dol_mktime(0, 0, 0, GETPOSTINT($constname.'month'), GETPOSTINT($constname.'day'), GETPOSTINT($constname.'year'));
}
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
// options in section other
if (GETPOSTISSET('ACCOUNTING_LETTERING_NBLETTERS')) {
if (!dolibarr_set_const($db, 'ACCOUNTING_LETTERING_NBLETTERS', GETPOST('ACCOUNTING_LETTERING_NBLETTERS'), 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
// Export options
$modelcsv = GETPOSTINT('ACCOUNTING_EXPORT_MODELCSV');
if (!empty($modelcsv)) {
if (!dolibarr_set_const($db, 'ACCOUNTING_EXPORT_MODELCSV', $modelcsv, 'chaine', 0, '', $conf->entity)) {
$error++;
}
//if ($modelcsv==AccountancyExport::$EXPORT_TYPE_QUADRATUS || $modelcsv==AccountancyExport::$EXPORT_TYPE_CIEL) {
// dolibarr_set_const($db, 'ACCOUNTING_EXPORT_FORMAT', 'txt', 'chaine', 0, '', $conf->entity);
//}
} else {
foreach ($list as $constname) {
$constvalue = GETPOST($constname, 'alpha');
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
if ($error) {
setEventMessages($langs->trans("Error"), null, 'errors');
}
foreach ($main_option as $constname) {
$constvalue = GETPOST($constname, 'alpha');
// option in section binding
foreach ($list_binding as $constname) {
$constvalue = GETPOST($constname, 'alpha');
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
if ($constname == 'ACCOUNTING_DATE_START_BINDING') {
$constvalue = dol_mktime(0, 0, 0, GETPOSTINT($constname.'month'), GETPOSTINT($constname.'day'), GETPOSTINT($constname.'year'));
}
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
// options in section other
if (GETPOSTISSET('ACCOUNTING_LETTERING_NBLETTERS')) {
if (!dolibarr_set_const($db, 'ACCOUNTING_LETTERING_NBLETTERS', GETPOST('ACCOUNTING_LETTERING_NBLETTERS'), 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
// Export options
$modelcsv = GETPOSTINT('ACCOUNTING_EXPORT_MODELCSV');
if (!empty($modelcsv)) {
if (!dolibarr_set_const($db, 'ACCOUNTING_EXPORT_MODELCSV', $modelcsv, 'chaine', 0, '', $conf->entity)) {
$error++;
}
//if ($modelcsv==AccountancyExport::$EXPORT_TYPE_QUADRATUS || $modelcsv==AccountancyExport::$EXPORT_TYPE_CIEL) {
// dolibarr_set_const($db, 'ACCOUNTING_EXPORT_FORMAT', 'txt', 'chaine', 0, '', $conf->entity);
//}
} else {
$error++;
}
foreach ($main_option as $constname) {
$constvalue = GETPOST($constname, 'alpha');
if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
foreach ($listparam[$modelcsv] as $key => $value) {
$constante = $key;
if (strpos($constante, 'ACCOUNTING') !== false) {
$constvalue = GETPOST($key, 'alpha');
if (!dolibarr_set_const($db, $constante, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
}
foreach ($listparam[$modelcsv] as $key => $value) {
$constante = $key;
if (strpos($constante, 'ACCOUNTING') !== false) {
$constvalue = GETPOST($key, 'alpha');
if (!dolibarr_set_const($db, $constante, $constvalue, 'chaine', 0, '', $conf->entity)) {
$error++;
}
}
}
if (!$error) {
// reload
$configuration = $accountancyexport->getTypeConfig();
$listparam = $configuration['param'];
}
if (!$error) {
// reload
$configuration = $accountancyexport->getTypeConfig();
$listparam = $configuration['param'];
}
if (!$error) {
@ -460,9 +459,10 @@ if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 1) {
}
// Show form main options
// Show form for main parameters
print $formSetup->generateOutput(true);
print '<br><br><br>';
@ -498,7 +498,7 @@ foreach ($list_binding as $key) {
1=>$langs->trans("ThirdPartyName") . ' - ' . $langs->trans("NumPiece"),
2=>$langs->trans("ThirdPartyName")
);
print $form->selectarray($key, $array, getDolGlobalInt('ACCOUNTING_LABEL_OPERATION_ON_TRANSFER', 0), 0, 0, 0, '', 0, 0, 0, '', 'onrightofpage width200');
print $form->selectarray($key, $array, getDolGlobalInt('ACCOUNTING_LABEL_OPERATION_ON_TRANSFER', 0), 0, 0, 0, '', 0, 0, 0, '', 'onrightofpage width300');
} else {
print '<input type="text" class="maxwidth100" id="'.$key.'" name="'.$key.'" value="'.getDolGlobalString($key).'">';
}
@ -579,8 +579,10 @@ print '</div>';
print '<div class="center"><input type="submit" class="button reposition" value="'.dol_escape_htmltag($langs->trans('Save')).'" name="button"></div>';
// Show numbering options
print '<br><br>';
print '<br><br><br>';
// Accountancy Numbering model
$dirmodels = array_merge(array('/'), $conf->modules_parts['models']);
@ -695,7 +697,8 @@ print '</div>';
// Show advanced options
print '<br><br>';
print '<br><br><br>';
// Advanced params
print '<div class="div-table-responsive-no-min">';
@ -786,7 +789,8 @@ print '</div>';
print '<div class="center"><input type="submit" class="button button-edit reposition" name="button" value="'.$langs->trans('Save').'"></div>';
print '<br><br>';
print '<br><br><br>';
// Export options

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2017-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -366,12 +366,9 @@ llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-adm
$titre = $langs->trans("DictionarySetup");
$linkback = '';
if ($id) {
$titre .= ' - '.$langs->trans($tablib[$id]);
$titlepicto = 'title_accountancy';
} else {
$titlepicto = '';
}
$titre .= ' - '.$langs->trans($tablib[$id]);
$titlepicto = 'title_accountancy';
print load_fiche_titre($titre, $linkback, $titlepicto);
@ -384,309 +381,297 @@ if ($action == 'delete') {
/*
* Show a dictionary
*/
if ($id) {
// Complete requete recherche valeurs avec critere de tri
$sql = $tabsql[$id];
$sql .= " WHERE a.entity = ".((int) $conf->entity);
// If sort order is "country", we use country_code instead
if ($sortfield == 'country') {
$sortfield = 'country_code';
}
$sql .= $db->order($sortfield, $sortorder);
$sql .= $db->plimit($listlimit + 1, $offset);
// Complete requete recherche valeurs avec critere de tri
$sql = $tabsql[$id];
$sql .= " WHERE a.entity = ".((int) $conf->entity);
// If sort order is "country", we use country_code instead
if ($sortfield == 'country') {
$sortfield = 'country_code';
}
$sql .= $db->order($sortfield, $sortorder);
$sql .= $db->plimit($listlimit + 1, $offset);
$fieldlist = explode(',', $tabfield[$id]);
print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="from" value="'.dol_escape_htmltag(GETPOST('from', 'alpha')).'">';
print '<div class="div-table-responsive">';
print '<table class="noborder centpercent">';
// Form to add a new line
if ($tabname[$id]) {
$fieldlist = explode(',', $tabfield[$id]);
print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="from" value="'.dol_escape_htmltag(GETPOST('from', 'alpha')).'">';
// Line for title
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$class = "left";
if ($fieldlist[$field] == 'code') {
$valuetoshow = $langs->trans("Code");
}
if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
$valuetoshow = $langs->trans("Label");
}
if ($fieldlist[$field] == 'nature') {
$valuetoshow = $langs->trans("NatureOfJournal");
}
print '<div class="div-table-responsive">';
print '<table class="noborder centpercent">';
// Form to add a new line
if ($tabname[$id]) {
$fieldlist = explode(',', $tabfield[$id]);
// Line for title
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$class = "left";
if ($fieldlist[$field] == 'code') {
$valuetoshow = $langs->trans("Code");
}
if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
$valuetoshow = $langs->trans("Label");
}
if ($fieldlist[$field] == 'nature') {
$valuetoshow = $langs->trans("NatureOfJournal");
if ($valuetoshow != '') {
print '<td class="'.$class.'">';
if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
print '<a href="'.$tabhelp[$id][$value].'">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
} elseif (!empty($tabhelp[$id][$value])) {
print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]);
} else {
print $valuetoshow;
}
print '</td>';
}
}
if ($valuetoshow != '') {
print '<td class="'.$class.'">';
if (!empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i', $tabhelp[$id][$value])) {
print '<a href="'.$tabhelp[$id][$value].'">'.$valuetoshow.' '.img_help(1, $valuetoshow).'</a>';
} elseif (!empty($tabhelp[$id][$value])) {
print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]);
} else {
print $valuetoshow;
print '<td>';
print '<input type="hidden" name="id" value="'.$id.'">';
print '</td>';
print '<td></td>';
print '<td></td>';
print '<td></td>';
print '</tr>';
// Line to enter new values
print '<tr class="oddeven nodrag nodrop nohover">';
$obj = new stdClass();
// If data was already input, we define them in obj to populate input fields.
if (GETPOST('actionadd', 'alpha')) {
foreach ($fieldlist as $key => $val) {
if (GETPOST($val) != '') {
$obj->$val = GETPOST($val);
}
}
}
$tmpaction = 'create';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('createDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
if (empty($reshook)) {
fieldListJournal($fieldlist, $obj, $tabname[$id], 'add');
}
print '<td colspan="4" class="right">';
print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'">';
print '</td>';
print "</tr>";
print '<tr><td colspan="7">&nbsp;</td></tr>'; // Keep &nbsp; to have a line with enough height
}
// List of available record in database
dol_syslog("htdocs/admin/dict", LOG_DEBUG);
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
$param = '&id='.((int) $id);
if ($search_country_id > 0) {
$param .= '&search_country_id='.urlencode((string) ($search_country_id));
}
$paramwithsearch = $param;
$paramwithsearch .= '&sortorder='.$sortorder;
$paramwithsearch .= '&sortfield='.$sortfield;
if (GETPOST('from', 'alpha')) {
$paramwithsearch .= '&from='.GETPOST('from', 'alpha');
}
// There is several pages
if ($num > $listlimit) {
print '<tr class="none"><td class="right" colspan="'.(3 + count($fieldlist)).'">';
print_fleche_navigation($page, $_SERVER["PHP_SELF"], $paramwithsearch, ($num > $listlimit ? 1 : 0), '<li class="pagination"><span>'.$langs->trans("Page").' '.($page + 1).'</span></li>');
print '</td></tr>';
}
// Title line with search boxes
/*print '<tr class="liste_titre_filter liste_titre_add">';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre center">';
$searchpicto=$form->showFilterButtons();
print $searchpicto;
print '</td>';
print '</tr>';
*/
// Title of lines
print '<tr class="liste_titre liste_titre_add">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$class = "left";
$sortable = 1;
$valuetoshow = '';
/*
$tmparray=getLabelOfField($fieldlist[$field]);
$valuetoshow=$tmp['valuetoshow'];
$align=$tmp['align'];
$sortable=$tmp['sortable'];
*/
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
if ($fieldlist[$field] == 'code') {
$valuetoshow = $langs->trans("Code");
}
if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
$valuetoshow = $langs->trans("Label");
}
if ($fieldlist[$field] == 'nature') {
$valuetoshow = $langs->trans("NatureOfJournal");
}
// Affiche nom du champ
print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable ? $fieldlist[$field] : ''), ($page ? 'page='.$page.'&' : ''), $param, "", $sortfield, $sortorder, $class.' ');
}
print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $param, '', $sortfield, $sortorder, 'center ');
print getTitleFieldOfList('');
print getTitleFieldOfList('');
print getTitleFieldOfList('');
print '</tr>';
if ($num) {
// Lines with values
while ($i < $num) {
$obj = $db->fetch_object($resql);
//print_r($obj);
print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
if ($action == 'edit' && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) {
$tmpaction = 'edit';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('editDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
// Show fields
if (empty($reshook)) {
fieldListJournal($fieldlist, $obj, $tabname[$id], 'edit');
}
print '<td class="center" colspan="4">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
print '<input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">';
print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
print '</td>';
} else {
$tmpaction = 'view';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('viewDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
if (empty($reshook)) {
$langs->load("accountancy");
foreach ($fieldlist as $field => $value) {
$class = "left";
$tmpvar = $fieldlist[$field];
$valuetoshow = $obj->$tmpvar;
if ($valuetoshow == 'all') {
$valuetoshow = $langs->trans('All');
} elseif ($fieldlist[$field] == 'nature' && $tabname[$id] == MAIN_DB_PREFIX.'accounting_journal') {
$key = $langs->trans("AccountingJournalType".strtoupper($obj->nature));
$valuetoshow = ($obj->nature && $key != "AccountingJournalType".strtoupper($langs->trans($obj->nature)) ? $key : $obj->{$fieldlist[$field]});
} elseif ($fieldlist[$field] == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'accounting_journal') {
$valuetoshow = $langs->trans($obj->label);
}
$class = 'tddict';
// Show value for field
print '<!-- '.$fieldlist[$field].' --><td class="'.$class.'">'.dol_escape_htmltag($valuetoshow).'</td>';
}
}
// Can an entry be erased or disabled ?
$iserasable = 1;
$canbedisabled = 1;
$canbemodified = 1; // true by default
if (isset($obj->code) && $id != 10) {
if (($obj->code == '0' || $obj->code == '' || preg_match('/unknown/i', $obj->code))) {
$iserasable = 0;
$canbedisabled = 0;
}
}
$canbemodified = $iserasable;
$url = $_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')).'&code='.(!empty($obj->code) ? urlencode($obj->code) : '');
$url .= '&'.$param;
$url .= '&';
// Active
print '<td class="nowrap center">';
if ($canbedisabled) {
print '<a href="'.$url.'action='.$acts[$obj->active].'&token='.newToken().'">'.$actl[$obj->active].'</a>';
} else {
print $langs->trans("AlwaysActive");
}
print "</td>";
// Modify link
if ($canbemodified) {
print '<td class="center"><a class="reposition editfielda" href="'.$url.'action=edit&token='.newToken().'">'.img_edit().'</a></td>';
} else {
print '<td>&nbsp;</td>';
}
// Delete link
if ($iserasable) {
print '<td class="center">';
if ($user->admin) {
print '<a href="'.$url.'action=delete&token='.newToken().'">'.img_delete().'</a>';
}
//else print '<a href="#">'.img_delete().'</a>'; // Some dictionary can be edited by other profile than admin
print '</td>';
} else {
print '<td>&nbsp;</td>';
}
print '<td></td>';
print '</td>';
}
print "</tr>\n";
$i++;
}
print '<td>';
print '<input type="hidden" name="id" value="'.$id.'">';
print '</td>';
print '<td></td>';
print '<td></td>';
print '<td></td>';
print '</tr>';
// Line to enter new values
print '<tr class="oddeven nodrag nodrop nohover">';
$obj = new stdClass();
// If data was already input, we define them in obj to populate input fields.
if (GETPOST('actionadd', 'alpha')) {
foreach ($fieldlist as $key => $val) {
if (GETPOST($val) != '') {
$obj->$val = GETPOST($val);
}
}
}
$tmpaction = 'create';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('createDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
if (empty($reshook)) {
fieldListJournal($fieldlist, $obj, $tabname[$id], 'add');
}
print '<td colspan="4" class="right">';
print '<input type="submit" class="button button-add" name="actionadd" value="'.$langs->trans("Add").'">';
print '</td>';
print "</tr>";
print '<tr><td colspan="7">&nbsp;</td></tr>'; // Keep &nbsp; to have a line with enough height
}
// List of available record in database
dol_syslog("htdocs/admin/dict", LOG_DEBUG);
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
$param = '&id='.((int) $id);
if ($search_country_id > 0) {
$param .= '&search_country_id='.urlencode((string) ($search_country_id));
}
$paramwithsearch = $param;
if ($sortorder) {
$paramwithsearch .= '&sortorder='.$sortorder;
}
if ($sortfield) {
$paramwithsearch .= '&sortfield='.$sortfield;
}
if (GETPOST('from', 'alpha')) {
$paramwithsearch .= '&from='.GETPOST('from', 'alpha');
}
// There is several pages
if ($num > $listlimit) {
print '<tr class="none"><td class="right" colspan="'.(3 + count($fieldlist)).'">';
print_fleche_navigation($page, $_SERVER["PHP_SELF"], $paramwithsearch, ($num > $listlimit ? 1 : 0), '<li class="pagination"><span>'.$langs->trans("Page").' '.($page + 1).'</span></li>');
print '</td></tr>';
}
// Title line with search boxes
/*print '<tr class="liste_titre_filter liste_titre_add">';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre"></td>';
print '<td class="liste_titre center">';
$searchpicto=$form->showFilterButtons();
print $searchpicto;
print '</td>';
print '</tr>';
*/
// Title of lines
print '<tr class="liste_titre liste_titre_add">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$showfield = 1; // By default
$class = "left";
$sortable = 1;
$valuetoshow = '';
/*
$tmparray=getLabelOfField($fieldlist[$field]);
$showfield=$tmp['showfield'];
$valuetoshow=$tmp['valuetoshow'];
$align=$tmp['align'];
$sortable=$tmp['sortable'];
*/
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
if ($fieldlist[$field] == 'code') {
$valuetoshow = $langs->trans("Code");
}
if ($fieldlist[$field] == 'libelle' || $fieldlist[$field] == 'label') {
$valuetoshow = $langs->trans("Label");
}
if ($fieldlist[$field] == 'nature') {
$valuetoshow = $langs->trans("NatureOfJournal");
}
// Affiche nom du champ
if ($showfield) {
print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable ? $fieldlist[$field] : ''), ($page ? 'page='.$page.'&' : ''), $param, "", $sortfield, $sortorder, $class.' ');
}
}
print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "active", ($page ? 'page='.$page.'&' : ''), $param, '', $sortfield, $sortorder, 'center ');
print getTitleFieldOfList('');
print getTitleFieldOfList('');
print getTitleFieldOfList('');
print '</tr>';
if ($num) {
// Lines with values
while ($i < $num) {
$obj = $db->fetch_object($resql);
//print_r($obj);
print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
if ($action == 'edit' && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) {
$tmpaction = 'edit';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('editDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
// Show fields
if (empty($reshook)) {
fieldListJournal($fieldlist, $obj, $tabname[$id], 'edit');
}
print '<td class="center" colspan="4">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
print '<input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">';
print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
print '</td>';
} else {
$tmpaction = 'view';
$parameters = array('fieldlist' => $fieldlist, 'tabname' => $tabname[$id]);
$reshook = $hookmanager->executeHooks('viewDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks
$error = $hookmanager->error;
$errors = $hookmanager->errors;
if (empty($reshook)) {
$langs->load("accountancy");
foreach ($fieldlist as $field => $value) {
$showfield = 1;
$class = "left";
$tmpvar = $fieldlist[$field];
$valuetoshow = $obj->$tmpvar;
if ($valuetoshow == 'all') {
$valuetoshow = $langs->trans('All');
} elseif ($fieldlist[$field] == 'nature' && $tabname[$id] == MAIN_DB_PREFIX.'accounting_journal') {
$key = $langs->trans("AccountingJournalType".strtoupper($obj->nature));
$valuetoshow = ($obj->nature && $key != "AccountingJournalType".strtoupper($langs->trans($obj->nature)) ? $key : $obj->{$fieldlist[$field]});
} elseif ($fieldlist[$field] == 'label' && $tabname[$id] == MAIN_DB_PREFIX.'accounting_journal') {
$valuetoshow = $langs->trans($obj->label);
}
$class = 'tddict';
// Show value for field
if ($showfield) {
print '<!-- '.$fieldlist[$field].' --><td class="'.$class.'">'.dol_escape_htmltag($valuetoshow).'</td>';
}
}
}
// Can an entry be erased or disabled ?
$iserasable = 1;
$canbedisabled = 1;
$canbemodified = 1; // true by default
if (isset($obj->code) && $id != 10) {
if (($obj->code == '0' || $obj->code == '' || preg_match('/unknown/i', $obj->code))) {
$iserasable = 0;
$canbedisabled = 0;
}
}
$canbemodified = $iserasable;
$url = $_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')).'&code='.(!empty($obj->code) ? urlencode($obj->code) : '');
if ($param) {
$url .= '&'.$param;
}
$url .= '&';
// Active
print '<td class="nowrap center">';
if ($canbedisabled) {
print '<a href="'.$url.'action='.$acts[$obj->active].'&token='.newToken().'">'.$actl[$obj->active].'</a>';
} else {
print $langs->trans("AlwaysActive");
}
print "</td>";
// Modify link
if ($canbemodified) {
print '<td class="center"><a class="reposition editfielda" href="'.$url.'action=edit&token='.newToken().'">'.img_edit().'</a></td>';
} else {
print '<td>&nbsp;</td>';
}
// Delete link
if ($iserasable) {
print '<td class="center">';
if ($user->admin) {
print '<a href="'.$url.'action=delete&token='.newToken().'">'.img_delete().'</a>';
}
//else print '<a href="#">'.img_delete().'</a>'; // Some dictionary can be edited by other profile than admin
print '</td>';
} else {
print '<td>&nbsp;</td>';
}
print '<td></td>';
print '</td>';
}
print "</tr>\n";
$i++;
}
}
} else {
dol_print_error($db);
}
print '</table>';
print '</div>';
print '</form>';
} else {
dol_print_error($db);
}
print '</table>';
print '</div>';
print '</form>';
print '<br>';
// End of page

View file

@ -352,7 +352,7 @@ if ($action != 'export') {
$newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
}
$newcardbutton .= dolGetButtonTitle($langs->trans('ExportToCsv'), '', 'fa fa-file-csv paddingleft', $_SERVER['PHP_SELF'], 'exportcsvbutton', 1, array('morecss' => 'marginleftonly'));
$newcardbutton .= dolGetButtonTitle($langs->trans("Export").' (' . getDolGlobalString('ACCOUNTING_EXPORT_FORMAT').')', '', 'fa fa-file-csv paddingleft', $_SERVER['PHP_SELF'], 'exportcsvbutton', 1, array('morecss' => 'marginleftonly'));
print '<script type="text/javascript">
jQuery(document).ready(function() {

View file

@ -55,7 +55,7 @@ $langs->loadLangs(array("accountancy", "compta"));
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepinglist';
$socid = GETPOSTINT('socid');

View file

@ -63,7 +63,7 @@ $massdate = dol_mktime(0, 0, 0, GETPOSTINT('massdatemonth'), GETPOSTINT('massdat
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php'));
// Search Parameters

View file

@ -60,7 +60,7 @@ $socid = GETPOSTINT('socid');
$mode = (GETPOST('mode', 'alpha') ? GETPOST('mode', 'alpha') : 'customer'); // Only for tab view
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$type = GETPOST('type', 'alpha');
if ($type == 'sub') {
$context_default = 'bookkeepingbysubaccountlist';
@ -463,11 +463,17 @@ if (empty($reshook)) {
// Actions
if ($action === 'exporttopdf' && $permissiontoadd) {
$object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
if ($type == "sub") {
$object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
} else {
$object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
}
require_once DOL_DOCUMENT_ROOT . '/core/modules/accountancy/doc/pdf_ledger.modules.php';
$pdf = new pdf_ledger($db);
$pdf->fromDate = $search_date_start;
$pdf->toDate = $search_date_end;
$pdf->ledgerType = $type;
$result = $pdf->write_file($object, $langs);
if ($result < 0) {
@ -895,7 +901,7 @@ if (empty($reshook)) {
$newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
}
}
$newcardbutton .= dolGetButtonTitle($langs->trans('ExportToPdf'), '', 'fa fa-file-pdf paddingleft', $_SERVER['PHP_SELF'] . '?action=exporttopdf&' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
$newcardbutton .= dolGetButtonTitle($langs->trans('ExportToPdf'), '', 'fa fa-file-pdf paddingleft', $_SERVER['PHP_SELF'] . '?action=exporttopdf'.(!empty($type) ? '&type=sub' : '').'&' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
$newcardbutton .= dolGetButtonTitleSeparator();

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2016 Jamal Elbaz <jamelbaz@gmail.pro>
* Copyright (C) 2016-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@ -69,47 +69,47 @@ class AccountancyCategory // extends CommonObject
public $id;
/**
* @var string Accountancy code
* @var ?string Accountancy code
*/
public $code;
/**
* @var string Accountancy Category label
* @var ?string Accountancy Category label
*/
public $label;
/**
* @var string Accountancy range account
* @var ?string Accountancy range account
*/
public $range_account;
/**
* @var int Sens of the account: 0: credit - debit, 1: debit - credit
* @var ?int Sens of the account: 0: credit - debit, 1: debit - credit
*/
public $sens;
/**
* @var int Category type of accountancy
* @var ?int Category type of accountancy
*/
public $category_type;
/**
* @var string Formula
* @var ?string Formula
*/
public $formula;
/**
* @var int Position
* @var ?int Position
*/
public $position;
/**
* @var int country id
* @var ?int country id
*/
public $fk_country;
/**
* @var int Is active
* @var ?int Is active
*/
public $active;
@ -399,7 +399,6 @@ class AccountancyCategory // extends CommonObject
*/
public function delete($user, $notrigger = 0)
{
global $conf, $langs;
$error = 0;
$sql = "DELETE FROM ".$this->db->prefix().$this->table_element;
@ -438,6 +437,7 @@ class AccountancyCategory // extends CommonObject
public function display($id)
{
global $conf;
$sql = "SELECT t.rowid, t.account_number, t.label";
$sql .= " FROM ".$this->db->prefix()."accounting_account as t";
$sql .= " WHERE t.fk_accounting_category = ".((int) $id);

View file

@ -1412,14 +1412,14 @@ class AccountancyExport
$invoice = new Facture($this->db);
$invoice->fetch($line->fk_doc);
$refInvoice = $invoice->ref;
$refInvoice = (string) $invoice->ref;
} elseif ($line->doc_type == 'supplier_invoice') {
// Supplier invoice
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
$invoice = new FactureFournisseur($this->db);
$invoice->fetch($line->fk_doc);
$refInvoice = $invoice->ref_supplier;
$refInvoice = (string) $invoice->ref_supplier;
}
$tab = array();
@ -1632,14 +1632,14 @@ class AccountancyExport
$invoice = new Facture($this->db);
$invoice->fetch($line->fk_doc);
$refInvoice = $invoice->ref;
$refInvoice = (string) $invoice->ref;
} elseif ($line->doc_type == 'supplier_invoice') {
// Supplier invoice
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
$invoice = new FactureFournisseur($this->db);
$invoice->fetch($line->fk_doc);
$refInvoice = $invoice->ref_supplier;
$refInvoice = (string) $invoice->ref_supplier;
}
$tab = array();

View file

@ -1,5 +1,6 @@
<?php
/* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
/* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -66,22 +67,22 @@ class AccountancyReport // extends CommonObject
public $id;
/**
* @var string Accountancy code
* @var ?string Accountancy code
*/
public $code;
/**
* @var string Accountancy Category label
* @var ?string Accountancy Category label
*/
public $label;
/**
* @var int country id
* @var ?int country id
*/
public $fk_country;
/**
* @var int Is active
* @var ?int Is active
*/
public $active;
@ -229,7 +230,6 @@ class AccountancyReport // extends CommonObject
*/
public function update($user = null, $notrigger = 0)
{
global $conf, $langs;
$error = 0;
// Clean parameters

View file

@ -1,11 +1,11 @@
<?php
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2013-2021 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2013-2021 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 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
@ -80,17 +80,17 @@ class AccountingAccount extends CommonObject
public $datec;
/**
* @var string pcg version
* @var ?string pcg version
*/
public $fk_pcg_version;
/**
* @var string pcg type
* @var ?string pcg type
*/
public $pcg_type;
/**
* @var string account number
* @var ?string account number
*/
public $account_number;
@ -115,12 +115,12 @@ class AccountingAccount extends CommonObject
public $status;
/**
* @var string Label of account
* @var ?string Label of account
*/
public $label;
/**
* @var string Label short of account
* @var ?string Label short of account
*/
public $labelshort;
@ -358,7 +358,7 @@ class AccountingAccount extends CommonObject
$sql = "UPDATE " . $this->db->prefix() . $this->table_element;
$sql .= " SET fk_pcg_version = " . ($this->fk_pcg_version ? "'" . $this->db->escape($this->fk_pcg_version) . "'" : "null");
$sql .= " , pcg_type = " . ($this->pcg_type ? "'" . $this->db->escape($this->pcg_type) . "'" : "null");
$sql .= " , pcg_type = '" . $this->db->escape($this->pcg_type) . "'";
$sql .= " , account_number = '" . $this->db->escape($this->account_number) . "'";
$sql .= " , account_parent = " . (int) $this->account_parent;
$sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "''");
@ -436,16 +436,14 @@ class AccountingAccount extends CommonObject
if ($result > 0) {
$this->db->begin();
if (!$error) {
$sql = "DELETE FROM " . $this->db->prefix() . $this->table_element;
$sql .= " WHERE rowid=" . ((int) $this->id);
$sql = "DELETE FROM " . $this->db->prefix() . $this->table_element;
$sql .= " WHERE rowid=" . ((int) $this->id);
dol_syslog(get_class($this) . "::delete sql=" . $sql);
$resql = $this->db->query($sql);
if (!$resql) {
$error++;
$this->errors[] = "Error " . $this->db->lasterror();
}
dol_syslog(get_class($this) . "::delete sql=" . $sql);
$resql = $this->db->query($sql);
if (!$resql) {
$error++;
$this->errors[] = "Error " . $this->db->lasterror();
}
// Commit or rollback
@ -737,7 +735,7 @@ class AccountingAccount extends CommonObject
* @param FactureLigne|SupplierInvoiceLine $factureDet Facture Det
* @param array<string,int> $accountingAccount Array of Accounting account
* @param string $type Customer / Supplier
* @return array{suggestedaccountingaccountbydefaultfor:string,suggestedaccountingaccountfor:string,suggestedid:?int,code_l:string,code_p:string,code_t:string}|int<-1,-1> Array of accounting accounts suggested or < 0 if technical error.
* @return array{suggestedaccountingaccountbydefaultfor:''|'eec'|'eecwithoutvatnumber'|'eecwithvat'|'export',suggestedaccountingaccountfor:'deposit'|'eec'|'eecwithoutvatnumber'|'eecwithvat'|'export'|'prodserv'|'thirdparty',suggestedid:?int,code_l:string,code_p:?string,code_t:string}|int<-1,-1> Array of accounting accounts suggested or < 0 if technical error.
* 'suggestedaccountingaccountbydefaultfor'=>Will be used for the label to show on tooltip for account by default on any product
* 'suggestedaccountingaccountfor'=>Is the account suggested for this product
*/
@ -889,10 +887,10 @@ class AccountingAccount extends CommonObject
return -1;
}
$code_l = $accountdeposittoventilated->ref;
$code_l = (string) $accountdeposittoventilated->ref;
$code_p = '';
$code_t = '';
$suggestedid = $accountdeposittoventilated->rowid;
$suggestedid = (int) $accountdeposittoventilated->rowid;
$suggestedaccountingaccountfor = 'deposit';
}
@ -908,10 +906,10 @@ class AccountingAccount extends CommonObject
} elseif ($type == 'supplier') {
$accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
}
$code_l = $accountdeposittoventilated->ref;
$code_l = (string) $accountdeposittoventilated->ref;
$code_p = '';
$code_t = '';
$suggestedid = $accountdeposittoventilated->rowid;
$suggestedid = (int) $accountdeposittoventilated->rowid;
$suggestedaccountingaccountfor = 'deposit';
}
}

View file

@ -49,11 +49,6 @@ class BookKeeping extends CommonObject
*/
public $table_element = 'accounting_bookkeeping';
/**
* @var int Entity
*/
public $entity;
/**
* @var BookKeepingLine[] Lines
*/
@ -75,27 +70,27 @@ class BookKeeping extends CommonObject
public $date_lim_reglement;
/**
* @var string Doc type
* @var ?string Doc type
*/
public $doc_type;
/**
* @var string Doc ref
* @var ?string Doc ref
*/
public $doc_ref;
/**
* @var int ID
* @var ?int ID
*/
public $fk_doc;
/**
* @var int ID
* @var ?int ID
*/
public $fk_docdet;
/**
* @var string Thirdparty code
* @var ?string Thirdparty code
*/
public $thirdparty_code;
@ -110,69 +105,69 @@ class BookKeeping extends CommonObject
public $subledger_label;
/**
* @var string doc_type
* @var ?string doc_type
*/
public $numero_compte;
/**
* @var string label compte
* @var ?string label compte
*/
public $label_compte;
/**
* @var string label operation
* @var ?string label operation
*/
public $label_operation;
/**
* @var float FEC:Debit
* @var ?float FEC:Debit
*/
public $debit;
/**
* @var float FEC:Credit
* @var ?float FEC:Credit
*/
public $credit;
/**
* @var float FEC:Amount (Not necessary)
* @var ?float FEC:Amount (Not necessary)
* @deprecated No more used (we have info into debit/credit and sens)
*/
public $montant;
/**
* @var float FEC:Amount (Not necessary)
* @var ?float FEC:Amount (Not necessary)
* @deprecated No more used (we have info into debit/credit and sens)
*/
public $amount;
/**
* @var string FEC:Sens (Not necessary)
* @var ?string FEC:Sens (Not necessary)
*/
public $sens;
/**
* @var int ID
* @var ?int ID
*/
public $fk_user_author;
/**
* @var string key for import
* @var ?string key for import
*/
public $import_key;
/**
* @var string code journal
* @var ?string code journal
*/
public $code_journal;
/**
* @var string label journal
* @var ?string label journal
*/
public $journal_label;
/**
* @var int accounting transaction id
* @var ?int accounting transaction id
*/
public $piece_num;
@ -1016,23 +1011,23 @@ class BookKeeping extends CommonObject
} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
$sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
} elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
$sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($this->db->escapeforlike($value)).'%\'';
$sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($this->db->escapeforlike($value))."%'";
} elseif ($key == 't.date_creation>=') {
$sqlwhere[] = 't.date_creation >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_creation >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_creation<=') {
$sqlwhere[] = 't.date_creation <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_creation <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_export>=') {
$sqlwhere[] = 't.date_export >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_export >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_export<=') {
$sqlwhere[] = 't.date_export <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_export <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_validated>=') {
$sqlwhere[] = 't.date_validated >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_validated >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_validated<=') {
$sqlwhere[] = 't.date_validated <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_validated <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_lim_reglement>=') {
$sqlwhere[] = 't.date_lim_reglement>=\''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_lim_reglement>='".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_lim_reglement<=') {
$sqlwhere[] = 't.date_lim_reglement<=\''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_lim_reglement<='".$this->db->idate((int) $value)."'";
} elseif ($key == 't.credit' || $key == 't.debit') {
$sqlwhere[] = natural_search($key, $value, 1, 1);
} elseif ($key == 't.reconciled_option') {
@ -1044,7 +1039,7 @@ class BookKeeping extends CommonObject
$sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
}
} elseif ($key == 't.search_accounting_code_in' && !empty($value)) {
$sqlwhere[] = 't.numero_compte IN ('.$this->db->sanitize($value, 1).')';
$sqlwhere[] = "t.numero_compte IN (".$this->db->sanitize($value, 1).")";
} else {
$sqlwhere[] = natural_search($key, $value, 0, 1);
}
@ -1060,7 +1055,7 @@ class BookKeeping extends CommonObject
$sql .= " AND t.subledger_account IS NOT NULL";
$sql .= " AND t.subledger_account <> ''";
$sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
} else {
$sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
@ -1198,7 +1193,7 @@ class BookKeeping extends CommonObject
if (count($filter) > 0) {
foreach ($filter as $key => $value) {
if ($key == 't.doc_date') {
$sqlwhere[] = $this->db->sanitize($key).' = \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.doc_date>=') {
$sqlwhere[] = "t.doc_date >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.doc_date<=') {
@ -1218,23 +1213,23 @@ class BookKeeping extends CommonObject
} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
$sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
} elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
$sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($value).'%\'';
$sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($value)."%'";
} elseif ($key == 't.date_creation>=') {
$sqlwhere[] = 't.date_creation >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_creation >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_creation<=') {
$sqlwhere[] = 't.date_creation <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_creation <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.tms>=') {
$sqlwhere[] = 't.tms >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.tms >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.tms<=') {
$sqlwhere[] = 't.tms <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.tms <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_export>=') {
$sqlwhere[] = 't.date_export >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_export >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_export<=') {
$sqlwhere[] = 't.date_export <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_export <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_validated>=') {
$sqlwhere[] = 't.date_validated >= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_validated >= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.date_validated<=') {
$sqlwhere[] = 't.date_validated <= \''.$this->db->idate((int) $value).'\'';
$sqlwhere[] = "t.date_validated <= '".$this->db->idate((int) $value)."'";
} elseif ($key == 't.credit' || $key == 't.debit') {
$sqlwhere[] = natural_search($key, $value, 1, 1);
} elseif ($key == 't.code_journal' && !empty($value)) {
@ -1251,7 +1246,7 @@ class BookKeeping extends CommonObject
}
}
if (count($sqlwhere) > 0) {
$sql .= ' AND '.implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
$sql .= " AND ".implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
}
$filter = '';
@ -1421,16 +1416,15 @@ class BookKeeping extends CommonObject
$sql .= " AND t.subledger_account <> ''";
$sql .= " GROUP BY t.numero_compte, t.subledger_account, t.subledger_label";
$sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
} else {
$sql .= ' GROUP BY t.numero_compte';
$sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : '');
$sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
}
if (!empty($sortfield)) {
$sql .= $this->db->order($sortfield, $sortorder);
}
$sql .= $this->db->order($sortfield, $sortorder);
if (!empty($limit)) {
$sql .= $this->db->plimit($limit + 1, $offset);
}
@ -1828,7 +1822,7 @@ class BookKeeping extends CommonObject
$this->db->begin();
// Call triggers
if (! $error && ! $notrigger) {
if (!$notrigger) {
$result = $this->call_trigger('BOOKKEEPING_DELETE', $user);
if ($result < 0) {
$error++;
@ -2301,14 +2295,12 @@ class BookKeeping extends CommonObject
}
}
} elseif ($direction == 1) {
if (!$error) {
$sql = 'DELETE FROM '.$this->db->prefix().$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
$resql = $this->db->query($sql);
if (!$resql) {
$error++;
$this->errors[] = 'Error '.$this->db->lasterror();
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
}
$sql = 'DELETE FROM '.$this->db->prefix().$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
$resql = $this->db->query($sql);
if (!$resql) {
$error++;
$this->errors[] = 'Error '.$this->db->lasterror();
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
}
if (!$error) {

View file

@ -29,7 +29,14 @@
* \brief Ventilation page from customers invoices
*/
require '../../main.inc.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Societe $mysoc
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
@ -40,14 +47,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Societe $mysoc
* @var Translate $langs
* @var User $user
*/
// Load translation files required by the page
$langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other", "productbatch", "products"));
@ -55,15 +54,12 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other",
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:aZ09'); // Value can be 'X_Y'
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancycustomerlist'; // To manage different context of search
$optioncss = GETPOST('optioncss', 'alpha');
$default_account = GETPOSTINT('default_account');
// Select Box
$mesCasesCochees = GETPOST('toselect', 'array');
// Search Getpost
$search_societe = GETPOST('search_societe', 'alpha');
$search_lineid = GETPOST('search_lineid', 'alpha'); // Can be '> 100'
@ -206,21 +202,20 @@ if (empty($reshook)) {
if ($massaction == 'ventil' && $user->hasRight('accounting', 'bind', 'write')) {
$msg = '';
//print '<div><span style="color:red">' . $langs->trans("Processing") . '...</span></div>';
if (!empty($mesCasesCochees)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
if (!empty($toselect)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($toselect).'</div>';
$msg .= '<div class="detail">';
$cpt = 0;
$ok = 0;
$ko = 0;
foreach ($mesCasesCochees as $maLigneCochee) {
foreach ($toselect as $maLigneCochee) {
$maLigneCourante = explode("_", $maLigneCochee);
$monId = $maLigneCourante[0];
$monCompte = GETPOSTINT('codeventil'.$monId);
if ($monCompte <= 0) {
$msg .= '<div><span style="color:red">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</span></div>';
$msg .= '<div><span class="error">'.$langs->trans("Lineofinvoice").' '.$monId.' - '.$langs->trans("NoAccountSelected").'</span></div>';
$ko++;
} else {
$sql = " UPDATE ".MAIN_DB_PREFIX."facturedet";

View file

@ -51,14 +51,10 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other",
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:aZ09'); // Value can be 'X_Y'
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancyexpensereportlist'; // To manage different context of search
$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
// Select Box
$mesCasesCochees = GETPOST('toselect', 'array');
// Search Getpost
$search_login = GETPOST('search_login', 'alpha');
$search_lineid = GETPOST('search_lineid', 'alpha');
@ -199,14 +195,14 @@ if (empty($reshook)) {
if ($massaction == 'ventil' && $user->hasRight('accounting', 'bind', 'write')) {
$msg = '';
if (!empty($mesCasesCochees)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
if (!empty($toselect)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($toselect).'</div>';
$msg .= '<div class="detail">';
$cpt = 0;
$ok = 0;
$ko = 0;
foreach ($mesCasesCochees as $maLigneCochee) {
foreach ($toselect as $maLigneCochee) {
$maLigneCourante = explode("_", $maLigneCochee);
$monId = $maLigneCourante[0];
$monCompte = GETPOSTINT('codeventil'.$monId);

View file

@ -4,11 +4,12 @@
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2013 Christophe Battarel <christophe.battarel@altairis.fr>
* Copyright (C) 2013-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2017-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2025 Hannes Hieronimi <hannes@innwerk.org>
*
* 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
@ -976,7 +977,7 @@ if ($resql) {
$sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
$sql .= " FROM ".$db->prefix()."subscription as su";
$sql .= " INNER JOIN ".$db->prefix()."adherent as adh ON adh.rowid = su.fk_adherent";
$sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = su.rowid AND bu.type = '".$db->escape($type)."'";
$sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.fk_bank = su.fk_bank AND bu.type = '".$db->escape($type)."'";
// Already in bookkeeping or not
if ($in_bookkeeping == 'already') {
$sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=su.rowid";
@ -1004,7 +1005,7 @@ if ($resql) {
// Add object in payment
if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
$tabpay[$obj->fk_bank]['objects'][$object_key] = array(
'amount' => -$obj->amount_payment,
'amount' => $obj->amount_payment,
'bu_url_id' => $obj->bu_url_id,
);
}

View file

@ -56,15 +56,12 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other",
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$confirm = GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:aZ09'); // Value can be 'X_Y'
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancysupplierlist'; // To manage different context of search
$optioncss = GETPOST('optioncss', 'alpha');
$default_account = GETPOSTINT('default_account');
// Select Box
$mesCasesCochees = GETPOST('toselect', 'array');
// Search Getpost
$search_lineid = GETPOST('search_lineid', 'alpha'); // Can be '> 100'
$search_societe = GETPOST('search_societe', 'alpha');
@ -212,14 +209,14 @@ if (empty($reshook)) {
if ($massaction == 'ventil' && $user->hasRight('accounting', 'bind', 'write')) {
$msg = '';
if (!empty($mesCasesCochees)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($mesCasesCochees).'</div>';
if (!empty($toselect)) {
$msg = '<div>'.$langs->trans("SelectedLines").': '.count($toselect).'</div>';
$msg .= '<div class="detail">';
$cpt = 0;
$ok = 0;
$ko = 0;
foreach ($mesCasesCochees as $maLigneCochee) {
foreach ($toselect as $maLigneCochee) {
$maLigneCourante = explode("_", $maLigneCochee);
$monId = $maLigneCourante[0];
$monCompte = GETPOSTINT('codeventil'.$monId);

View file

@ -1,10 +1,10 @@
<?php
/* Copyright (C) 2015-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2022 Lionel Vessiller <lvessiller@open-dsi.fr>
* Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
* Copyright (C) 2022 Progiseize <a.bisotti@progiseize.fr>
/* Copyright (C) 2015-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2022 Lionel Vessiller <lvessiller@open-dsi.fr>
* Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
* Copyright (C) 2022 Progiseize <a.bisotti@progiseize.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,6 +33,7 @@
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var int $formatexportset
* @var string $type_export
* @var string $filename
@ -89,6 +90,38 @@ if ((substr($accountancyexport->getFormatCode($formatexportset), 0, 3) == 'fec')
$completefilename = ($code ? $code."_" : "").($prefix ? $prefix."_" : "").$filename.($nodateexport ? "" : $date_export).".".$format;
}
// --- Hook: allow external modules to override export filename ---
if (is_object($hookmanager)) {
// Dedicated context (non-blocking if other hooks are already initialized)
$hookmanager->initHooks(array('accountancyexportfilename'));
$parameters = array(
'type_export' => $type_export ?? '',
'format' => $format ?? '',
'format_code' => $accountancyexport->getFormatCode($formatexportset),
'code' => $code ?? '',
'prefix' => $prefix ?? '',
'filename' => $filename ?? '',
'period_start' => $startaccountingperiod ?? '',
'period_end' => $endaccountingperiod ?? '',
'siren' => $siren ?? '',
'ndate_in_filename' => $nodateexport ?? 0,
'now_datetime' => $date_export,
// Value by default
'defaultfilename' => $completefilename
);
// Hook called by modules: setExportFilename
$reshook = $hookmanager->executeHooks('setExportFilename', $parameters, $accountancyexport, $action);
if ($reshook > 0) {
if (!empty($hookmanager->resArray['filename'])) {
$completefilename = $hookmanager->resArray['filename'];
} elseif ($hookmanager->resPrint !== '') {
$completefilename = $hookmanager->resPrint;
}
}
}
if (empty($downloadMode)) {
header('Content-Disposition: attachment;filename=' . $completefilename);
}

View file

@ -37,6 +37,7 @@
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
/**
* @var Conf $conf
@ -76,9 +77,63 @@ $error = 0;
include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
global $conf;
if ($action == 'updateMask') {
$maskconst = GETPOST('maskconst', 'aZ09');
$maskvalue = GETPOST('maskvalue', 'alpha');
if ($action == 'set_default') {
$res = 0;
if ($maskconst && preg_match('/_MASK$/', $maskconst)) {
$res = dolibarr_set_const($db, $maskconst, $maskvalue, 'chaine', 0, '', $conf->entity);
}
if (!($res > 0)) {
$error++;
}
if (!$error) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
} elseif ($action == 'specimen') { // For fiche expensereport
$modele = GETPOST('module', 'alpha');
$adherentspecimen = new Adherent($db);
$adherentspecimen->initAsSpecimen();
$adherentspecimen->status = 0; // Force statut draft to show watermark
// Search template files
$file = '';
$classname = '';
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
foreach ($dirmodels as $reldir) {
$file = dol_buildpath($reldir."core/modules/member/doc/pdf_".$modele.".modules.php", 0);
if (file_exists($file)) {
$classname = "pdf_".$modele;
break;
}
}
if ($classname !== '') {
require_once $file;
$module = new $classname($db);
'@phan-var-force ModelePDFMember $module';
/** @var ModelePDFMember $module */
if ($module->write_file($adherentspecimen, $langs) > 0) {
header("Location: ".DOL_URL_ROOT."/document.php?modulepart=member&file=SPECIMEN.pdf");
return;
} else {
setEventMessages($module->error, $module->errors, 'errors');
dol_syslog($module->error, LOG_ERR);
}
} else {
setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
}
} elseif ($action == 'set_default') {
$ret = addDocumentModel($value, $type, $label, $scandir);
$res = true;
} elseif ($action == 'del_default') {
@ -264,7 +319,7 @@ print ' <td>'.$langs->trans("Name").'</td>';
print ' <td>'.$langs->trans("Description").'</td>';
print ' <td>'.$langs->trans("Example").'</td>';
print ' <td class="center" width="80">'.$langs->trans("Status").'</td>';
print ' <td class="center" width="60">'.$langs->trans("ShortInfo").'</td>';
print ' <td class="center" width="60"></td>';
print "</tr>\n";
$arrayofmodules = array();
@ -286,6 +341,7 @@ foreach ($dirModMember as $dirroot) {
continue;
}
$modCodeMember = new $file();
/** @var ModeleNumRefMembers $modCodeMember */
// Show modules according to features level
if ($modCodeMember->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
continue;
@ -303,6 +359,7 @@ foreach ($dirModMember as $dirroot) {
$arrayofmodules = dol_sort_array($arrayofmodules, 'position');
'@phan-var-force array<string,ModeleNumRefMembers> $arrayofmodules';
/** @var array<string,ModeleNumRefMembers> $arrayofmodules */
foreach ($arrayofmodules as $file => $modCodeMember) {
print '<tr class="oddeven">'."\n";
@ -347,12 +404,14 @@ print "<br>";
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
// Defined model definition table
$def = array();
// TODO Replace with $def = getListOfModels($db, $type);
$sql = "SELECT nom as name";
$sql .= " FROM ".MAIN_DB_PREFIX."document_model";
$sql .= " WHERE type = '".$db->escape($type)."'";
$sql .= " AND entity = ".$conf->entity;
$sql .= " AND entity = ".((int) $conf->entity);
$resql = $db->query($sql);
if ($resql) {
$i = 0;
@ -403,6 +462,7 @@ foreach ($dirmodels as $reldir) {
require_once $dir.'/'.$file;
$module = new $classname($db);
'@phan-var-force doc_generic_member_odt|pdf_standard_member $module';
/** @var doc_generic_member_odt|pdf_standard_member $module */
$modulequalified = 1;
if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) {
@ -629,10 +689,52 @@ print '<input type="hidden" name="page_y" value="">';
print load_fiche_titre($langs->trans("MembersCards"), '', '');
$helptext = '*'.$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
$helptext .= '__DOL_MAIN_URL_ROOT__, __ID__, __FIRSTNAME__, __LASTNAME__, __FULLNAME__, __LOGIN__, __PASSWORD__, ';
$helptext .= '__COMPANY__, __ADDRESS__, __ZIP__, __TOWN__, __COUNTRY__, __EMAIL__, __BIRTH__, __PHOTO__, __TYPE__, ';
$helptext .= '__YEAR__, __MONTH__, __DAY__';
$helptext = $langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
// Set list of substitution variables (must be the same list than into the core/modules/member/doc/pdf_standard_member.class.php
$helptext .= '<small>';
$now = dol_now();
$year = dol_print_date($now, '%Y');
$month = dol_print_date($now, '%m');
$day = dol_print_date($now, '%d');
// List of values to scan for a replacement (Must be samevalues than into adherents/cartes/carte.php and pdf_standard_members.class.php)
$substitutionarray = array(
'__MEMBER_ID__' => 'MemberID',
'__MEMBER_REF__' => 'MemberRef',
'__MEMBER_LOGIN__' => 'MemberLogin',
'__MEMBER_TITLE__' => 'MemberLogin',
'__MEMBER_FIRSTNAME__' => 'MemberFirstname',
'__MEMBER_LASTNAME__' => 'MemberLastname',
'__MEMBER_FULLNAME__' => 'MemberFullname',
'__MEMBER_COMPANY__' => 'Company',
'__MEMBER_ADDRESS__' => 'MemberAddress',
'__MEMBER_ZIP__' => 'MemberZip',
'__MEMBER_TOWN__' => 'MemberTown',
'__MEMBER_COUNTRY__' => 'MemberCountry',
'__MEMBER_COUNTRY_CODE__' =>'MemberCountryCode',
'__MEMBER_EMAIL__' => 'MemberEmail',
'__MEMBER_BIRTH__' => 'MemberBirthdate',
'__MEMBER_TYPE__' => 'MemberType',
'__MEMBER_PHOTO__' => 'MemberPhoto',
'__YEAR__' => $year,
'__MONTH__' => $month,
'__DAY__' => $day,
'__DOL_MAIN_URL_ROOT__' => (string) DOL_MAIN_URL_ROOT,
'__SERVER__' => "https://".$_SERVER["SERVER_NAME"]."/"
);
foreach ($substitutionarray as $key => $val) {
$helptext .= $key.' => '.$val.'<br>';
}
// Make substitutions for new variables
/*
$array_member = $this->getSubstitutionarrayMember($object, $outputlangs);
$array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
$array_other = $this->get_substitutionarray_other($outputlangs);
$substitutionarray = array_merge($substitutionarray, $array_member, $array_soc, $array_other);
*/
$helptext .= '</small>';
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
@ -649,32 +751,32 @@ $arrayoflabels = array();
foreach (array_keys($_Avery_Labels) as $codecards) {
$arrayoflabels[$codecards] = $_Avery_Labels[$codecards]['name'];
}
print $form->selectarray('ADHERENT_CARD_TYPE', $arrayoflabels, getDolGlobalString('ADHERENT_CARD_TYPE') ? getDolGlobalString('ADHERENT_CARD_TYPE') : 'CARD', 1, 0, 0);
print $form->selectarray('ADHERENT_CARD_TYPE', $arrayoflabels, getDolGlobalString('ADHERENT_CARD_TYPE', 'CARD'), 1, 0, 0);
print "</td></tr>\n";
// Text printed on top of member cards
print '<tr class="oddeven"><td>'.$langs->trans("DescADHERENT_CARD_HEADER_TEXT").'</td><td>';
print '<input type="text" class="flat minwidth300" name="ADHERENT_CARD_HEADER_TEXT" value="'.dol_escape_htmltag(getDolGlobalString('ADHERENT_CARD_HEADER_TEXT')).'">';
print '<input type="text" class="flat minwidth300" name="ADHERENT_CARD_HEADER_TEXT" value="'.dol_escape_htmltag(getDolGlobalString('ADHERENT_CARD_HEADER_TEXT')).'" spellcheck="false">';
print "</td></tr>\n";
// Text printed on member cards (align on left)
print '<tr class="oddeven"><td>'.$langs->trans("DescADHERENT_CARD_TEXT").'</td><td>';
print '<textarea class="flat" name="ADHERENT_CARD_TEXT" cols="50" rows="5" wrap="soft">'."\n";
print '<textarea class="flat" name="ADHERENT_CARD_TEXT" cols="50" rows="5" wrap="soft" spellcheck="false">'."\n";
print getDolGlobalString('ADHERENT_CARD_TEXT');
print '</textarea>';
print "</td></tr>\n";
// Text printed on member cards (align on right)
print '<tr class="oddeven"><td>'.$langs->trans("DescADHERENT_CARD_TEXT_RIGHT").'</td><td>';
print '<textarea class="flat" name="ADHERENT_CARD_TEXT_RIGHT" cols="50" rows="5" wrap="soft">'."\n";
print '<textarea class="flat" name="ADHERENT_CARD_TEXT_RIGHT" cols="50" rows="5" wrap="soft" spellcheck="false">'."\n";
print getDolGlobalString('ADHERENT_CARD_TEXT_RIGHT');
print '</textarea>';
print "</td></tr>\n";
// Text printed on bottom of member cards
print '<tr class="oddeven"><td>'.$langs->trans("DescADHERENT_CARD_FOOTER_TEXT").'</td><td>';
print '<input type="text" class="flat minwidth300" name="ADHERENT_CARD_FOOTER_TEXT" value="'.dol_escape_htmltag(getDolGlobalString('ADHERENT_CARD_FOOTER_TEXT')).'">';
print '<input type="text" class="flat minwidth300" name="ADHERENT_CARD_FOOTER_TEXT" value="'.dol_escape_htmltag(getDolGlobalString('ADHERENT_CARD_FOOTER_TEXT')).'" spellcheck="false">';
print "</td></tr>\n";
print '</table>';
@ -698,11 +800,6 @@ print '<input type="hidden" name="page_y" value="">';
print load_fiche_titre($langs->trans("MembersTickets"), '', '');
$helptext = '*'.$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
$helptext .= '__DOL_MAIN_URL_ROOT__, __ID__, __FIRSTNAME__, __LASTNAME__, __FULLNAME__, __LOGIN__, __PASSWORD__, ';
$helptext .= '__COMPANY__, __ADDRESS__, __ZIP__, __TOWN__, __COUNTRY__, __EMAIL__, __BIRTH__, __PHOTO__, __TYPE__, ';
$helptext .= '__YEAR__, __MONTH__, __DAY__';
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
@ -724,7 +821,7 @@ print "</td></tr>\n";
// Text printed on member address sheets
print '<tr class="oddeven"><td>'.$langs->trans("DescADHERENT_ETIQUETTE_TEXT").'</td><td>';
print '<textarea class="flat" name="ADHERENT_ETIQUETTE_TEXT" cols="50" rows="5" wrap="soft">'."\n";
print '<textarea class="flat" name="ADHERENT_ETIQUETTE_TEXT" cols="50" rows="5" wrap="soft" spellcheck="false">'."\n";
print getDolGlobalString('ADHERENT_ETIQUETTE_TEXT');
print '</textarea>';
print "</td></tr>\n";

View file

@ -65,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"))),
'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' => '')
);
@ -166,7 +166,131 @@ print '<input type="hidden" name="action" value="updateall">';
print '<br>';
form_constantes($constantes, 3, '');
// TODO Try to use the formsetup class.
$tableau = $constantes;
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td class="">'.$langs->trans("Description").'</td>';
print '<td>';
print '</td>';
print "</tr>\n";
foreach ($tableau as $key => $const) { // Loop on each param
$label = '';
$type = $const['type'];
$label = $const['label'];
$help = empty($const['help']) ? '' : $const['help'];
$const = $key;
$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 .= " ORDER BY name ASC, entity DESC";
$resql = $db->query($sql);
dol_syslog("List params", LOG_DEBUG);
if ($resql) {
$obj = $db->fetch_object($resql); // Take first result of select
if (empty($obj)) { // If not yet into table
$obj = (object) array('rowid' => '', 'name' => $const, 'value' => '', 'type' => $type, 'note' => '');
}
if ($const == 'ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION' && !getDolGlobalString('MEMBER_REMINDER_EMAIL')) {
continue;
}
print '<tr class="oddeven">';
// Show label of parameter
print '<td>';
print '<input type="hidden" name="rowid[]" value="'.$obj->rowid.'">';
print '<input type="hidden" name="constname[]" value="'.$const.'">';
print '<input type="hidden" name="constnote_'.$obj->name.'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">';
print '<input type="hidden" name="consttype_'.$obj->name.'" value="'.($obj->type ? $obj->type : 'string').'">';
$picto = '';
$tmparray = explode(':', $obj->type);
if (!empty($tmparray[1])) {
$picto = preg_replace('/_send$/', '', $tmparray[1]);
}
if ($picto) {
print img_picto('', $picto, 'class="pictofixedwidth"');
}
if (!empty($tableau[$key]['tooltip'])) {
print $form->textwithpicto($label ? $label : $langs->trans('Desc'.$const), $tableau[$key]['tooltip']);
} else {
print($label ? $label : $langs->trans('Desc'.$const));
}
if (in_array($const, ['ADHERENT_MAIL_FROM', 'ADHERENT_CC_MAIL_FROM'])) {
print ' '.img_help(1, $langs->trans("EMailHelpMsgSPFDKIM"));
}
if ($help) {
print '<br><span class="opacitymedium">';
//print $langs->trans("MEMBER_REMINDER_EMAILHelp");
print $help;
print '</span>';
}
print "</td>\n";
// Value
print '<td>';
print '<input type="hidden" name="consttype_'.$const.'" value="'.($obj->type ? $obj->type : 'string').'">';
print '<input type="hidden" name="constnote_'.$const.'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">';
if ($obj->type == 'textarea') {
print '<textarea class="flat" name="constvalue_'.$const.'" cols="50" rows="5" wrap="soft">'."\n";
print $obj->value;
print "</textarea>\n";
} elseif ($obj->type == 'html') {
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$doleditor = new DolEditor('constvalue_'.$const, $obj->value, '', 160, 'dolibarr_notes', '', false, false, isModEnabled('fckeditor'), ROWS_5, '90%');
$doleditor->Create();
} elseif ($obj->type == 'yesno') {
print $form->selectyesno('constvalue_'.$const, $obj->value, 1, false, 0, 1);
} elseif (preg_match('/emailtemplate/', $obj->type)) {
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
$tmp = explode(':', $obj->type);
$formmail->fetchAllEMailTemplate($tmp[1], $user, null, -1); // We set lang=null to get in priority record with no lang
$arrayofmessagename = array();
if (is_array($formmail->lines_model)) {
foreach ($formmail->lines_model as $modelmail) {
//var_dump($modelmail);
$moreonlabel = '';
if (!empty($arrayofmessagename[$modelmail->label])) {
$moreonlabel = ' <span class="opacitymedium">('.$langs->trans("SeveralLangugeVariatFound").')</span>';
}
// The 'label' is the key that is unique if we exclude the language
$arrayofmessagename[$modelmail->label.':'.$tmp[1]] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)).$moreonlabel;
}
}
//var_dump($arraydefaultmessage);
//var_dump($arrayofmessagename);
print $form->selectarray('constvalue_'.$const, $arrayofmessagename, $obj->value.':'.$tmp[1], 'None', 0, 0, '', 0, 0, 0, '', '', 1);
print '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/mails_templates.php', ['action' => 'create', 'type_template' => $tmp[1], 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"])]).'">'.img_picto('', 'add').'</a>';
} elseif (preg_match('/MAIL_FROM$/i', $const)) {
print img_picto('', 'email', 'class="pictofixedwidth"').'<input type="text" class="flat minwidth300" name="constvalue_'.$const.'" value="'.dol_escape_htmltag($obj->value).'">';
} else { // type = 'string' ou 'chaine'
print '<input type="text" class="flat minwidth300" name="constvalue_'.$const .'" value="'.dol_escape_htmltag($obj->value).'">';
}
print '</td>';
print "</tr>\n";
}
}
print '</table>';
print '</div>';
print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
print '</form>';

View file

@ -4,7 +4,7 @@
* Copyright (C) 2006-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@ -29,21 +29,21 @@
// 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';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Societe $mysoc
* @var Translate $langs
* @var User $user
*
* @var string $dolibarr_main_url_root
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "members"));
@ -100,7 +100,7 @@ if ($action == 'update') {
} else {
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_FORCETYPE", $forcetype, 'chaine', 0, '', $conf->entity);
}
if ($forcemorphy == '-1') {
if (empty($forcemorphy) || $forcemorphy == '-1') {
$res = dolibarr_del_const($db, "MEMBER_NEWFORM_FORCEMORPHY", $conf->entity);
} else {
$res = dolibarr_set_const($db, "MEMBER_NEWFORM_FORCEMORPHY", $forcemorphy, 'chaine', 0, '', $conf->entity);
@ -222,7 +222,7 @@ if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Parameter").'</td>';
print '<td>'.$langs->trans("Value").'</td>';
print '<td></td>';
print "</tr>\n";
// Force Type
@ -233,18 +233,20 @@ if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
$listofval = array();
$listofval += $adht->liste_array(1);
$forcetype = getDolGlobalInt('MEMBER_NEWFORM_FORCETYPE', -1);
print $form->selectarray("MEMBER_NEWFORM_FORCETYPE", $listofval, $forcetype, count($listofval) > 1 ? 1 : 0);
print $form->selectarray("MEMBER_NEWFORM_FORCETYPE", $listofval, $forcetype, $langs->trans("No"), 0, 0, '', 0, 0, 0, '', 'width200');
print "</td></tr>\n";
// Force nature of member (mor/phy)
$morphys = array();
$morphys["phy"] = $langs->trans("Physical");
$morphys["mor"] = $langs->trans("Moral");
$morphys = [
"phy" => $langs->trans("Physical"),
"mor" => $langs->trans("Moral"),
];
print '<tr class="oddeven drag" id="trforcenature"><td>';
print $langs->trans("ForceMemberNature");
print '</td><td>';
$forcenature = getDolGlobalInt('MEMBER_NEWFORM_FORCEMORPHY', 0);
print $form->selectarray("MEMBER_NEWFORM_FORCEMORPHY", $morphys, $forcenature, 1);
$forcenature = getDolGlobalString('MEMBER_NEWFORM_FORCEMORPHY'); // 'phy' or 'mor'
print $form->selectarray("MEMBER_NEWFORM_FORCEMORPHY", $morphys, $forcenature, $langs->trans("No"), 0, 0, '', 0, 0, 0, '', 'width200');
print "</td></tr>\n";
// Amount
@ -252,6 +254,7 @@ if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
print $langs->trans("DefaultAmount");
print '</td><td>';
print '<input type="text" class="right width50" id="MEMBER_NEWFORM_AMOUNT" name="MEMBER_NEWFORM_AMOUNT" value="'.getDolGlobalString('MEMBER_NEWFORM_AMOUNT').'">';
print ' <span class="opacitymedium">'.$langs->getCurrencySymbol($mysoc->currency_code).'</span>';
print "</td></tr>\n";
// Min amount
@ -259,6 +262,7 @@ if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
print $langs->trans("MinimumAmount");
print '</td><td>';
print '<input type="text" class="right width50" id="MEMBER_MIN_AMOUNT" name="MEMBER_MIN_AMOUNT" value="'.getDolGlobalString('MEMBER_MIN_AMOUNT').'">';
print ' <span class="opacitymedium">'.$langs->getCurrencySymbol($mysoc->currency_code).'</span>';
print "</td></tr>\n";
// SHow counter of validated members publicly

View file

@ -6,7 +6,7 @@
* Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
* Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -158,7 +158,7 @@ if ($object->id > 0) {
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref);

View file

@ -1,7 +1,8 @@
<?php
/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2012 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2012 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -249,7 +250,7 @@ abstract class ActionsAdherentCardCommon
array('label' => $langs->trans("LoginToCreate"), 'type' => 'text', 'name' => 'login', 'value' => $login),
array('label' => $langs->trans("Password"), 'type' => 'text', 'name' => 'password', 'value' => $password));
$this->tpl['action_create_user'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("CreateDolibarrLogin"), $langs->trans("ConfirmCreateAdherent"), "confirm_create_user", $formquestion, 'no');
$this->tpl['action_create_user'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("CreateDolibarrLogin"), $langs->trans("ConfirmCreateMember"), "confirm_create_user", $formquestion, 'no');
}
}
@ -269,8 +270,8 @@ abstract class ActionsAdherentCardCommon
$this->object->fk_soc = GETPOSTINT("fk_soc");
$this->object->socid = GETPOSTINT("fk_soc");
$this->object->lastname = GETPOST("lastname");
$this->object->firstname = GETPOST("firstname");
$this->object->lastname = GETPOST("lastname");
$this->object->firstname = GETPOST("firstname");
$this->object->civility_id = GETPOST("civility_id");
$this->object->address = GETPOST("address");
$this->object->zip = GETPOST("zipcode");

View file

@ -2,6 +2,7 @@
/* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012-2018 Philippe Grand <philippe.grand@atoo-net.com>
* Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -112,7 +113,7 @@ class ActionsAdherentCardDefault extends ActionsAdherentCardCommon
} else {
// Confirm delete contact
if ($action == 'delete' && $user->hasRight('adherent', 'supprimer')) {
$this->tpl['action_delete'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("DeleteAdherent"), $langs->trans("ConfirmDeleteAdherent"), "confirm_delete", '', 0, 1);
$this->tpl['action_delete'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("DeleteAdherent"), $langs->trans("ConfirmDeleteMember"), "confirm_delete", '', 0, 1);
}
}
}

View file

@ -88,6 +88,7 @@ if (isModEnabled('mailmanspip')) {
$object = new Adherent($db);
$extrafields = new ExtraFields($db);
$upload_dir = null;
// fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);
@ -240,6 +241,7 @@ if (empty($reshook)) {
$tmpuser = dol_clone($object, 2);
if (GETPOST('internalorexternal', 'aZ09') == 'internal') {
$tmpuser->fk_soc = 0;
$tmpuser->socid = 0;
}
$result = $nuser->create_from_member($tmpuser, GETPOST('login', 'alphanohtml'));
@ -272,6 +274,29 @@ if (empty($reshook)) {
setEventMessages($object->error, $object->errors, 'errors');
}
}
if ($action == 'confirm_merge' && $confirm == 'yes' && $user->hasRight('adherent', 'creer')) {
$member_origin_id = GETPOSTINT('member_origin');
$member_origin = new Adherent($db); // The thirdparty that we will delete
if ($member_origin_id <= 0) {
$langs->load('errors');
setEventMessages($langs->trans('MergeOriginMemberIsMAndatory'), null, 'errors');
} else {
if (!$error && $member_origin->fetch($member_origin_id) < 1) {
setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors');
$error++;
}
if (!$error) {
$result = $object->mergeMembers($member_origin_id);
if ($result < 0) {
$error++;
setEventMessages($object->error, $object->errors, 'errors');
} else {
setEventMessages($langs->trans('MemberMergeSuccess'), null, 'mesgs');
}
}
}
}
if ($action == 'update' && !$cancel && $user->hasRight('adherent', 'creer')) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
@ -335,7 +360,7 @@ if (empty($reshook)) {
$object->phone_perso = trim(GETPOST("phone_perso", 'alpha'));
$object->phone_mobile = trim(GETPOST("phone_mobile", 'alpha'));
$object->email = preg_replace('/\s+/', '', GETPOST("member_email", 'alpha'));
$object->url = trim(GETPOST('member_url', 'custom', 0, FILTER_SANITIZE_URL));
$object->url = trim(GETPOST('member_url', 'url'));
$object->socialnetworks = array();
foreach ($socialnetworks as $key => $value) {
if (GETPOSTISSET($key) && GETPOST($key, 'alphanohtml') != '') {
@ -485,7 +510,7 @@ if (empty($reshook)) {
$phone_perso = GETPOST("phone_perso", 'alpha');
$phone_mobile = GETPOST("phone_mobile", 'alpha');
$email = preg_replace('/\s+/', '', GETPOST("member_email", 'aZ09arobase'));
$url = trim(GETPOST('url', 'custom', 0, FILTER_SANITIZE_URL));
$url = trim(GETPOST('url', 'url'));
$login = GETPOST("member_login", 'alphanohtml');
$pass = GETPOST("password", 'password'); // For password, we use 'none'
$photo = GETPOST("photo", 'alphanohtml');
@ -519,18 +544,18 @@ if (empty($reshook)) {
}
}
$object->email = $email;
$object->url = $url;
$object->login = $login;
$object->pass = $pass;
$object->birth = $birthdate;
$object->photo = $photo;
$object->typeid = $typeid;
//$object->note = $comment;
$object->morphy = $morphy;
$object->user_id = $userid;
$object->email = $email;
$object->url = $url;
$object->login = $login;
$object->pass = $pass;
$object->birth = $birthdate;
$object->photo = $photo;
$object->typeid = $typeid;
//$object->note = $comment;
$object->morphy = $morphy;
$object->user_id = $userid;
$object->socid = $socid;
$object->public = $public;
$object->public = $public;
$object->default_lang = $default_lang;
// Fill array 'array_options' with data from add form
$ret = $extrafields->setOptionalsFromPost(null, $object);
@ -594,10 +619,6 @@ if (empty($reshook)) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorBadUrl", $object->url), null, 'errors');
}
$public = 0;
if (isset($public)) {
$public = 1;
}
if (!$error) {
$db->begin();
@ -1051,50 +1072,103 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print '<span class="error">'.$langs->trans("NoTypeDefinedGoToSetup").'</span>';
}
if ($user->hasRight('member', 'configurer')) {
print ' <a href="'.DOL_URL_ROOT.'/adherents/type.php?action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&typeid=--IDFORBACKTOPAGE--').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("NewMemberType").'"></span></a>';
print ' <a href="'.dolBuildUrl(DOL_URL_ROOT.'/adherents/type.php', ['action' => 'create', 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'create', 'typeid' => '--IDFORBACKTOPAGE--'])]).'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("NewMemberType").'"></span></a>';
}
print "</td>\n";
// Morphy
$morphys = array();
$morphys["phy"] = $langs->trans("Physical");
$morphys["mor"] = $langs->trans("Moral");
// Legal entity or natural person
$morphys = [
"phy" => $langs->trans("Physical"),
"mor" => $langs->trans("Moral"),
];
$checkednature = GETPOST("morphy", 'alpha');
$listetype_natures = $adht->morphyByType(1);
$listetype_natures_json = json_encode($listetype_natures);
print '<tr><td class="fieldrequired">'.$langs->trans("MemberNature")."</td><td>\n";
print '<span id="spannature1" class="nonature-back spannature paddinglarge marginrightonly"><label for="phisicalinput" class="valignmiddle">'.$morphys["phy"].'<input id="phisicalinput" class="flat checkforselect marginleftonly valignmiddle" type="radio" name="morphy" value="phy"'.($checkednature == "phy" ? ' checked="checked"' : '').'></label></span>';
print '<span id="spannature2" class="nonature-back spannature paddinglarge marginrightonly"><label for="moralinput" class="valignmiddle">'.$morphys["mor"].'<input id="moralinput" class="flat checkforselect marginleftonly valignmiddle" type="radio" name="morphy" value="mor"'.($checkednature == "mor" ? ' checked="checked"' : '').'></label></span>';
// Add js to manage the background of nature
// Add JS to manage the background of nature
if ($conf->use_javascript_ajax) {
print "<script>
var listetype_natures = $listetype_natures_json;
</script>";
print '<script>
jQuery(function($) {
function refreshNatureCss() {
jQuery(".spannature").each(function( index ) {
console.log(jQuery("#spannature"+(index+1)+" .checkforselect").is(":checked"));
if (jQuery("#spannature"+(index+1)+" .checkforselect").is(":checked")) {
if (index+1 == 1) {
jQuery("#spannature"+(index+1)).addClass("member-individual-back").removeClass("nonature-back");
}
if (index+1 == 2) {
jQuery("#spannature"+(index+1)).addClass("member-company-back").removeClass("nonature-back");
$(".spannature").each(function(index) {
let $span = $("#spannature" + (index + 1));
let checked = $span.find(".checkforselect").is(":checked");
if (checked) {
if (index === 0) {
$span.addClass("member-individual-back").removeClass("nonature-back member-company-back");
} else if (index === 1) {
$span.addClass("member-company-back").removeClass("nonature-back member-individual-back");
}
} else {
jQuery("#spannature"+(index+1)).removeClass("member-individual-back").removeClass("member-company-back").addClass("nonature-back");
$span.removeClass("member-individual-back member-company-back")
.addClass("nonature-back");
}
});
}
jQuery(".spannature").click(function(){
console.log("We click on a nature");
$(".spannature").on("click", function() {
console.log("Nature clicked");
refreshNatureCss();
});
$("#typeid").on("change", function() {
let morphy = listetype_natures[$(this).val()];
let $phyInput = $("#phisicalinput");
let $morInput = $("#moralinput");
let $tdLast = $("#tdlastname");
let $tdFirst = $("#tdfirstname");
let $tdCompany = $("#tdcompany");
let $span1 = $("#spannature1");
let $span2 = $("#spannature2");
switch (morphy) {
case "phy":
$phyInput.prop({disabled: false, checked: true});
$morInput.prop({disabled: true, checked: false});
$span1.addClass("member-individual-back").removeClass("nonature-back");
$span2.removeClass("member-company-back").addClass("nonature-back");
$tdLast.addClass("fieldrequired");
$tdFirst.addClass("fieldrequired");
$tdCompany.removeClass("fieldrequired");
break;
case "mor":
$phyInput.prop({disabled: true, checked: false});
$morInput.prop({disabled: false, checked: true});
$span2.addClass("member-company-back").removeClass("nonature-back");
$span1.removeClass("member-individual-back").addClass("nonature-back");
$tdCompany.addClass("fieldrequired");
$tdLast.removeClass("fieldrequired");
$tdFirst.removeClass("fieldrequired");
break;
default:
$phyInput.prop({disabled: false, checked: false});
$morInput.prop({disabled: false, checked: false});
$span1.removeClass("member-individual-back").addClass("nonature-back");
$span2.removeClass("member-company-back").addClass("nonature-back");
}
});
// Initial state
refreshNatureCss();
</script>';
});
</script>';
}
print "</td>\n";
// Company
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td><input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET('societe') ? GETPOST('societe', 'alphanohtml') : $soc->name).'"></td></tr>';
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td>'.img_picto('', 'company', 'class="pictofixedwidth"').'<input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET('societe') ? GETPOST('societe', 'alphanohtml') : $soc->name).'"></td></tr>';
// Civility
print '<tr><td>'.$langs->trans("UserTitle").'</td><td>';
@ -1118,11 +1192,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// EMail
print '<tr><td>'.(getDolGlobalString('ADHERENT_MAIL_REQUIRED') ? '<span class="fieldrequired">' : '').$langs->trans("EMail").(getDolGlobalString('ADHERENT_MAIL_REQUIRED') ? '</span>' : '').'</td>';
print '<td>'.img_picto('', 'object_email').' <input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOSTISSET('member_email') ? GETPOST('member_email', 'alpha') : $soc->email).'"></td></tr>';
print '<td>'.img_picto('', 'object_email', 'class="pictofixedwidth"').' <input type="text" name="member_email" class="minwidth300" maxlength="255" value="'.(GETPOSTISSET('member_email') ? GETPOST('member_email', 'alpha') : $soc->email).'"></td></tr>';
// Website
print '<tr><td>'.$form->editfieldkey('Web', 'member_url', GETPOST('member_url', 'alpha'), $object, 0).'</td>';
print '<td>'.img_picto('', 'globe').' <input type="text" class="maxwidth500 widthcentpercentminusx" name="member_url" id="member_url" value="'.(GETPOSTISSET('member_url') ? GETPOST('member_url', 'alpha') : $object->url).'"></td></tr>';
print '<td>'.img_picto('', 'globe', 'class="pictofixedwidth"').' <input type="text" class="maxwidth500 widthcentpercentminusx" name="member_url" id="member_url" value="'.(GETPOSTISSET('member_url') ? GETPOST('member_url', 'alpha') : $object->url).'"></td></tr>';
// Address
print '<tr><td class="tdtop">'.$langs->trans("Address").'</td><td>';
@ -1328,7 +1402,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print "</td></tr>";
// Company
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td><input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET("societe") ? GETPOST("societe", 'alphanohtml', 2) : $object->company).'"></td></tr>';
print '<tr><td id="tdcompany">'.$langs->trans("Company").'</td><td>'.img_picto('', 'company', 'class="pictofixedwidth"').'<input type="text" name="societe" class="minwidth300" maxlength="128" value="'.(GETPOSTISSET("societe") ? GETPOST("societe", 'alphanohtml', 2) : $object->company).'"></td></tr>';
// Civility
print '<tr><td>'.$langs->trans("UserTitle").'</td><td>';
@ -1615,10 +1689,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnValid()), $substitutionarray, $outputlangs);
$tmp = $langs->trans("SendingAnEMailToMember");
$tmp .= '<br>'.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM').'</b>, ';
$tmp .= '<br>'.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'</b>, ';
$tmp .= '<br>'.$langs->trans("MailRecipient").': <b>'.$object->email.'</b>';
$helpcontent = '';
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM').'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailRecipient").'</b>: '.$object->email.'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("Subject").'</b>:<br>'."\n";
$helpcontent .= $subjecttosend."\n";
@ -1679,10 +1753,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnResiliate()), $substitutionarray, $outputlangs);
$tmp = $langs->trans("SendingAnEMailToMember");
$tmp .= '<br>('.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM').'</b>, ';
$tmp .= '<br>('.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'</b>, ';
$tmp .= $langs->trans("MailRecipient").': <b>'.$object->email.'</b>)';
$helpcontent = '';
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM').'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailRecipient").'</b>: '.$object->email.'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("Subject").'</b>:<br>'."\n";
$helpcontent .= $subjecttosend."\n";
@ -1740,10 +1814,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnExclude()), $substitutionarray, $outputlangs);
$tmp = $langs->trans("SendingAnEMailToMember");
$tmp .= '<br>('.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM').'</b>, ';
$tmp .= '<br>('.$langs->trans("MailFrom").': <b>'.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'</b>, ';
$tmp .= $langs->trans("MailRecipient").': <b>'.$object->email.'</b>)';
$helpcontent = '';
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM').'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailRecipient").'</b>: '.$object->email.'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("Subject").'</b>:<br>'."\n";
$helpcontent .= $subjecttosend."\n";
@ -1777,6 +1851,21 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
if ($action == 'add_spip') {
print $form->formconfirm("card.php?rowid=".$id, $langs->trans('AddIntoSpip'), $langs->trans('AddIntoSpipConfirmation'), 'confirm_add_spip');
}
// Confirm merge
if ($action == 'merge') {
$formquestion = array(
array(
'name' => 'member_origin',
'label' => $langs->trans('MergeOriginMember'),
'type' => 'other',
'value' => $form->selectMembers('', 'member_origin', '', 0, 1, '', 0, array(), 0, 'SelectMember', 0, 'minwidth200', array(), 1, array($object->id))
)
);
print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("MergeMembers"), $langs->trans("ConfirmMergeMembers"), "confirm_merge", $formquestion, 'no', 1, 300);
}
// Confirm removed from spip
if ($action == 'del_spip') {
print $form->formconfirm("card.php?rowid=$id", $langs->trans('DeleteIntoSpip'), $langs->trans('DeleteIntoSpipConfirmation'), 'confirm_del_spip');
@ -1793,7 +1882,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
@ -2087,6 +2176,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
}
// Merge
print dolGetButtonAction($langs->trans('MergeMembers'), $langs->trans('Merge'), 'danger', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=merge&token='.newToken(), '', $user->hasRight('adherent', 'supprimer'));
// Delete
if ($user->hasRight('adherent', 'supprimer')) {
print '<a class="butActionDelete" href="card.php?rowid='.((int) $object->id).'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>'."\n";

View file

@ -1,10 +1,10 @@
<?php
/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (C) 2006-2013 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
/* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (C) 2006-2013 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 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
* it under the terms of the GNU General Public License as published by
@ -26,22 +26,22 @@
* \brief Page to output members business cards
*/
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/member/modules_cards.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/printsheet/modules_labels.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*
* @var array<string,array{name:string,paper-size:string|array{0:float,1:float},orientation:string,metric:string,marginLeft:float,marginTop:float,NX:int,NY:int,SpaceX:float,SpaceY:float,width:float,height:float,font-size:int,custom_x:float,custom_y:float}> $_Avery_Labels
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
/** @var array<string,array{name:string,paper-size:string|array{0:float,1:float},orientation:string,metric:string,marginLeft:float,marginTop:float,NX:int,NY:int,SpaceX:float,SpaceY:float,width:float,height:float,font-size:int,custom_x:float,custom_y:float}> $_Avery_Labels */
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/member/modules_cards.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/printsheet/modules_labels.php';
$langs->loadLangs(array("members", "errors"));
// Choice of printing year or current year.
@ -136,6 +136,12 @@ if ((!empty($foruserid) || !empty($foruserlogin) || !empty($mode)) && !$mesg) {
}
}
$now = dol_now();
$year = dol_print_date($now, '%Y');
$month = dol_print_date($now, '%m');
$day = dol_print_date($now, '%d');
// List of values to scan for a replacement
$substitutionarray = array(
'__MEMBER_ID__' => $objp->rowid,
@ -163,6 +169,28 @@ if ((!empty($foruserid) || !empty($foruserlogin) || !empty($mode)) && !$mesg) {
foreach ($adherentstatic->array_options as $key => $val) {
$substitutionarray['__'.strtoupper($key).'__'] = $val;
}
// Add old values for backward compatibility (need upgrade of member setup to be removed)
$substitutionarrayold = array(
'__ID__' => $objp->rowid,
'__REF__' => $objp->ref,
'__LOGIN__' => empty($objp->login) ? '' : $objp->login,
'__TITLE__' => empty($objp->civility) ? '' : $langs->trans("Civility".$objp->civility),
'__FIRSTNAME__' => empty($objp->firstname) ? '' : $objp->firstname,
'__LASTNAME__' => empty($objp->lastname) ? '' : $objp->lastname,
'__FULLNAME__' => $adherentstatic->getFullName($langs),
'__COMPANY__' => empty($objp->company) ? '' : $objp->company,
'__ADDRESS__' => empty($objp->address) ? '' : $objp->address,
'__ZIP__' => empty($objp->zip) ? '' : $objp->zip,
'__TOWN__' => empty($objp->town) ? '' : $objp->town,
'__COUNTRY__' => empty($objp->country) ? '' : $objp->country,
'__COUNTRY_CODE__' => empty($objp->country_code) ? '' : $objp->country_code,
'__EMAIL__' => empty($objp->email) ? '' : $objp->email,
'__BIRTH__' => dol_print_date($objp->birth, 'day'),
'__TYPE__' => empty($objp->type) ? '' : $objp->type,
);
$substitutionarray = array_merge($substitutionarray, $substitutionarrayold);
complete_substitutions_array($substitutionarray, $langs, $adherentstatic);
// For business cards
@ -237,7 +265,7 @@ if ((!empty($foruserid) || !empty($foruserlogin) || !empty($mode)) && !$mesg) {
$mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DescADHERENT_CARD_TYPE"));
}
if (!$mesg) {
$result = members_card_pdf_create($db, $arrayofmembers, $modelcard, $outputlangs, '', 'standard', 'tmp_cards');
$result = members_card_pdf_create($db, $arrayofmembers, $modelcard, $outputlangs, '', 'standard_member', 'tmp_cards');
}
} elseif ($mode == 'cardlogin') {
if (!count($arrayofmembers)) {
@ -247,7 +275,7 @@ if ((!empty($foruserid) || !empty($foruserlogin) || !empty($mode)) && !$mesg) {
$mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DescADHERENT_CARD_TYPE"));
}
if (!$mesg) {
$result = members_card_pdf_create($db, $arrayofmembers, $model, $outputlangs, '', 'standard', 'tmp_cards_login');
$result = members_card_pdf_create($db, $arrayofmembers, $model, $outputlangs, '', 'standard_member', 'tmp_cards_login');
}
} elseif ($mode == 'label') {
if (!count($arrayofmembers)) {

View file

@ -175,7 +175,7 @@ class Adherent extends CommonObject
public $morphy;
/**
* @var int<0,1> Info can be public
* @var ?int<0,1> Info can be public
*/
public $public;
@ -283,12 +283,12 @@ class Adherent extends CommonObject
public $last_subscription_date_start;
/**
* @var int|string date
* @var int|string|null date
*/
public $last_subscription_date_end;
/**
* @var int|string date
* @var null|float|string date, null until set
*/
public $last_subscription_amount;
@ -338,7 +338,7 @@ class Adherent extends CommonObject
* 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
* 'noteditable' says if field is not editable (1 or 0)
* 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0')
* 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
* 'default' is a default value for creation (can still be overwritten by the Setup of Default Values if the field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
* 'index' if we want an index in database.
* 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
* 'searchall' is 1 if we want to search in this field when making a search from the quick search button.
@ -505,11 +505,8 @@ class Adherent extends CommonObject
$texttosend = dol_htmlentitiesbr($texttosend);
}
// Envoi mail confirmation
$from = $conf->email_from;
if (getDolGlobalString('ADHERENT_MAIL_FROM')) {
$from = getDolGlobalString('ADHERENT_MAIL_FROM');
}
// Send mail confirmation
$from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
$trackid = 'mem'.$this->id;
@ -662,7 +659,7 @@ class Adherent extends CommonObject
*/
public function create($user, $notrigger = 0)
{
global $conf, $langs, $mysoc;
global $langs, $mysoc;
$error = 0;
@ -827,6 +824,7 @@ class Adherent extends CommonObject
// $this->note_private = ($this->note_private ? $this->note_private : $this->note_private);
$this->url = $this->url ? clean_url($this->url, 0) : '';
$this->setUpperOrLowerCase();
// Check parameters
if (getDolGlobalString('ADHERENT_MAIL_REQUIRED') && !isValidEmail((string) $this->email)) {
$langs->load("errors");
@ -838,6 +836,7 @@ class Adherent extends CommonObject
$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
$sql .= " ref = '".$this->db->escape($this->ref)."'";
$sql .= ", ref_ext = ".(empty($this->ref_ext) ? "null" : "'".$this->db->escape($this->ref_ext)."'");
$sql .= ", civility = ".($this->civility_id ? "'".$this->db->escape($this->civility_id)."'" : "null");
$sql .= ", firstname = ".($this->firstname ? "'".$this->db->escape($this->firstname)."'" : "null");
$sql .= ", lastname = ".($this->lastname ? "'".$this->db->escape($this->lastname)."'" : "null");
@ -904,11 +903,9 @@ class Adherent extends CommonObject
$action = 'update';
// Actions on extra fields
if (!$error) {
$result = $this->insertExtraFields();
if ($result < 0) {
$error++;
}
$result = $this->insertExtraFields();
if ($result < 0) {
$error++;
}
// Update password
@ -951,7 +948,7 @@ class Adherent extends CommonObject
if (!$error && $nbrowsaffected) { // If something has change in main data
// Update information on linked user if it is an update
if (!$error && $this->user_id > 0 && !$nosyncuser) {
if ($this->user_id > 0 && !$nosyncuser) {
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
dol_syslog(get_class($this)."::update update linked user");
@ -1003,7 +1000,7 @@ class Adherent extends CommonObject
}
// Update information on linked thirdparty if it is an update
if (!$error && $this->fk_soc > 0 && !$nosyncthirdparty) {
if (!$error && $this->socid > 0 && !$nosyncthirdparty) {
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
dol_syslog(get_class($this)."::update update linked thirdparty");
@ -1011,7 +1008,7 @@ class Adherent extends CommonObject
// This member is linked with a thirdparty, so we also update thirdparty information
// if this is an update.
$lthirdparty = new Societe($this->db);
$result = $lthirdparty->fetch($this->fk_soc);
$result = $lthirdparty->fetch($this->socid);
if ($result > 0) {
$lthirdparty->address = $this->address;
@ -1025,7 +1022,7 @@ class Adherent extends CommonObject
//$lthirdparty->phone_mobile=$this->phone_mobile;
$lthirdparty->default_lang = $this->default_lang;
$result = $lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
$result = $lthirdparty->update($this->socid, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
if ($result < 0) {
$this->error = $lthirdparty->error;
@ -1133,7 +1130,7 @@ class Adherent extends CommonObject
$this->db->begin();
if (!$error && !$notrigger) {
if (!$notrigger) {
// Call trigger
$result = $this->call_trigger('MEMBER_DELETE', $user);
if ($result < 0) {
@ -1205,6 +1202,150 @@ class Adherent extends CommonObject
}
}
/**
* Merge a member with current one, deleting the given company $member_origin_id.
* The member given in parameter will be removed.
* This is called for example by the adherent/card.php file.
* It calls the method replaceMember() of each object with relation with member,
* including hook 'replaceMember' for external modules.
*
* @param int $member_origin_id Member to merge the data from
* @return int -1 if error, >=0 if OK
*/
public function mergeMembers($member_origin_id)
{
global $conf, $langs, $hookmanager, $user, $action;
$error = 0;
$member_origin = new Adherent($this->db); // The member that we will delete
dol_syslog("mergeMembers merge member id=".$member_origin_id." (will be deleted) into the member id=".$this->id);
if ($member_origin->fetch($member_origin_id) < 1) {
$this->error = $langs->trans('ErrorRecordNotFound');
$error++;
}
if (!$error) {
$this->db->begin();
$listofproperties = array(
'ref_ext', 'civility', 'lastname', 'firstname', 'morphy', 'societe', 'socid', 'user_id','address',
'zip', 'town', 'state_id', 'country', 'phone', 'phone_perso', 'phone_mobile', 'email',
'url', 'socialnetworks', 'birth', 'gender', 'photo', 'public', 'datefin', 'default_lang',
'canvas', 'model_pdf', 'import_key'
);
foreach ($listofproperties as $property) {
if (empty($this->$property)) {
$this->$property = $member_origin->$property;
}
}
// Concat some data
$listofproperties = array(
'note_public', 'note_private'
);
foreach ($listofproperties as $property) {
$this->$property = dol_concatdesc($this->$property, $member_origin->$property);
}
// Merge extrafields
if (is_array($member_origin->array_options)) {
foreach ($member_origin->array_options as $key => $val) {
if (empty($this->array_options[$key])) {
$this->array_options[$key] = $val;
}
}
}
// Merge categories
include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
$static_cat = new Categorie($this->db);
$custcats_ori = $static_cat->containing($member_origin->id, 'member', 'id');
$custcats = $static_cat->containing($this->id, 'member', 'id');
$custcats = array_merge($custcats, $custcats_ori);
$this->setCategories($custcats);
$result = $this->update($user, 1, 1, 1, 1, 'merge');
if ($result < 0) {
$error++;
}
// Merge subscriptions
if (!$error && $member_origin->fetch_subscriptions() < 1) {
$error++;
}
if (!$error) {
foreach ($member_origin->subscriptions as $key => $subscription) {
$subscription->fk_adherent = $this->id;
$result = $subscription->update($user);
if ($result < 0) {
$error++;
break;
}
}
}
// External modules should update their ones too
if (!$error) {
$parameters = array('member_origin' => $member_origin->id, 'member_dest' => $this->id);
$reshook = $hookmanager->executeHooks('replaceMember', $parameters, $this, $action);
if ($reshook < 0) {
$this->setErrorsFromObject($hookmanager);
$error++;
}
}
if (!$error) {
$this->context = array('merge' => 1, 'mergefromid' => $member_origin->id);
// Call trigger
$result = $this->call_trigger('MEMBER_MODIFY', $user);
if ($result < 0) {
$error++;
}
// End call triggers
}
if (!$error) {
// We finally remove the old member
if ($member_origin->delete($user) < 1) {
$this->setErrorsFromObject($member_origin);
$error++;
}
}
if (!$error) {
// Move files from the dir of the third party to delete into the dir of the third party to keep
if (!empty($conf->adherent->multidir_output[$this->entity])) {
$srcdir = $conf->adherent->multidir_output[$this->entity]."/".$member_origin->id;
$destdir = $conf->adherent->multidir_output[$this->entity]."/".$this->id;
if (dol_is_dir($srcdir)) {
$dirlist = dol_dir_list($srcdir, 'files', 1);
foreach ($dirlist as $filetomove) {
$destfile = $destdir.'/'.$filetomove['relativename'];
$result = dol_move($filetomove['fullname'], $destfile, '0', 0, 0, 1);
if (!$result) {
$error++;
}
}
}
}
}
if (!$error) {
$this->db->commit();
return 0;
} else {
$langs->load("errors");
$this->error = $langs->trans('ErrorMembersMerge');
$this->db->rollback();
return -1;
}
}
return -1;
}
/**
* Change password of a user
@ -1447,23 +1588,23 @@ class Adherent extends CommonObject
*
* @param int $rowid Id of object to load
* @param string $ref To load member from its ref
* @param int $fk_soc To load member from its link to third party
* @param int $socid To load member from its link to third party
* @param string $ref_ext External reference
* @param bool $fetch_optionals To load optionals (extrafields)
* @param bool $fetch_subscriptions To load member subscriptions
* @return int >0 if OK, 0 if not found, <0 if KO
*/
public function fetch($rowid, $ref = '', $fk_soc = 0, $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
public function fetch($rowid, $ref = '', $socid = 0, $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
{
global $langs;
$sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,";
$sql .= " d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
$sql .= " d.societe as company, d.fk_soc as socid, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
$sql .= " d.note_public,";
$sql .= " d.email, d.url, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
$sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
$sql .= " d.datec as datec,";
$sql .= " d.tms as datem,";
$sql .= " GREATEST(d.tms, aef.tms) as datem,";
$sql .= " d.datefin as datefin, d.default_lang,";
$sql .= " d.birth as birthday,";
$sql .= " d.datevalid as datev,";
@ -1475,18 +1616,19 @@ class Adherent extends CommonObject
$sql .= " t.libelle as type, t.subscription as subscription,";
$sql .= " u.rowid as user_id, u.login as user_login";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'adherent_extrafields as aef ON aef.fk_object = d.rowid';
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
$sql .= " WHERE d.fk_adherent_type = t.rowid";
if ($rowid) {
$sql .= " AND d.rowid=".((int) $rowid);
} elseif ($ref || $fk_soc) {
} elseif ($ref || $socid) {
$sql .= " AND d.entity IN (".getEntity('adherent').")";
if ($ref) {
$sql .= " AND d.ref='".$this->db->escape($ref)."'";
} elseif ($fk_soc > 0) {
$sql .= " AND d.fk_soc=".((int) $fk_soc);
} elseif ($socid > 0) {
$sql .= " AND d.fk_soc=".((int) $socid);
}
} elseif ($ref_ext) {
$sql .= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
@ -1513,8 +1655,8 @@ class Adherent extends CommonObject
$this->login = $obj->login;
$this->societe = $obj->company;
$this->company = $obj->company;
$this->socid = $obj->fk_soc;
$this->fk_soc = $obj->fk_soc; // For backward compatibility
$this->socid = $obj->socid;
$this->fk_soc = $obj->socid; // For backward compatibility
$this->address = $obj->address;
$this->zip = $obj->zip;
$this->town = $obj->town;
@ -1606,8 +1748,6 @@ class Adherent extends CommonObject
public function fetch_subscriptions()
{
// phpcs:enable
global $langs;
require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
$sql = "SELECT c.rowid, c.fk_adherent, c.fk_type, c.subscription, c.note as note_public, c.fk_bank,";
@ -1635,13 +1775,13 @@ class Adherent extends CommonObject
$this->last_subscription_date = $this->db->jdate($obj->datec);
$this->last_subscription_date_start = $this->db->jdate($obj->dateh);
$this->last_subscription_date_end = $this->db->jdate($obj->datef);
$this->last_subscription_amount = $obj->subscription;
$this->last_subscription_amount = (float) $obj->subscription;
$subscription = new Subscription($this->db);
$subscription->id = $obj->rowid;
$subscription->fk_adherent = $obj->fk_adherent;
$subscription->fk_type = $obj->fk_type;
$subscription->amount = $obj->subscription;
$subscription->amount = (float) $obj->subscription;
$subscription->note = $obj->note_public;
$subscription->note_public = $obj->note_public;
$subscription->fk_bank = $obj->fk_bank;
@ -1670,8 +1810,6 @@ class Adherent extends CommonObject
*/
public function fetchPartnerships($mode)
{
global $langs;
require_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php';
@ -1688,15 +1826,16 @@ class Adherent extends CommonObject
* @param double $amount Amount of subscription (0 accepted for some members)
* @param int $accountid Id bank account. NOT USED.
* @param string $operation Code of payment mode (if Id bank account provided). Example: 'CB', ... NOT USED.
* @param string $label Label operation (if Id bank account provided).
* @param string $num_chq Numero cheque (if Id bank account provided)
* @param string $label Label operation stored into public note.
* @param string $num_chq Numero cheque (if Id bank account provided). NOT USED.
* @param string $emetteur_nom Name of cheque writer
* @param string $emetteur_banque Name of bank of cheque
* @param int $datesubend Date end subscription
* @param int $fk_type Member type id
* @param string $ref_ext To save an external ref
* @return int rowid of record added, <0 if KO
*/
public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0, $fk_type = null)
public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0, $fk_type = null, $ref_ext = '')
{
global $user;
@ -1725,9 +1864,10 @@ class Adherent extends CommonObject
$subscription->dateh = $date; // Date of new subscription
$subscription->datef = $datefin; // End data of new subscription
$subscription->amount = $amount;
$subscription->note = $label; // deprecated
$subscription->note_public = $label;
$subscription->note_private = '';
$subscription->fk_type = $fk_type;
$subscription->ref_ext = $ref_ext;
if (empty($subscription->user_creation_id)) {
$subscription->user_creation_id = $user->id;
@ -1744,6 +1884,8 @@ class Adherent extends CommonObject
$this->last_subscription_date_start = $date;
$this->last_subscription_date_end = $datefin;
$this->last_subscription_amount = $amount;
} else {
$error++;
}
if (!$error) {
@ -1834,7 +1976,7 @@ class Adherent extends CommonObject
$customer = new Societe($this->db);
if (!$error) {
if (!($this->fk_soc > 0)) { // If not yet linked to a company
if (!($this->socid > 0)) { // If not yet linked to a company
if ($autocreatethirdparty) {
// Create a linked thirdparty to member
$companyalias = '';
@ -1859,6 +2001,7 @@ class Adherent extends CommonObject
$error++;
} else {
$this->fk_soc = $result;
$this->socid = $result;
}
} else {
$langs->load("errors");
@ -1869,7 +2012,7 @@ class Adherent extends CommonObject
}
}
if (!$error) {
$result = $customer->fetch($this->fk_soc);
$result = $customer->fetch($this->socid);
if ($result <= 0) {
$this->error = $customer->error;
$this->errors = $customer->errors;
@ -1890,7 +2033,7 @@ class Adherent extends CommonObject
$this->errors[] = $this->error;
}
}
$invoice->socid = $this->fk_soc;
$invoice->socid = $this->socid;
// set customer's payment bank account on the invoice
if (!empty($customer->fk_account)) {
$invoice->fk_account = $customer->fk_account;
@ -1913,8 +2056,7 @@ class Adherent extends CommonObject
$result = $invoice->create($user);
if ($result <= 0) {
$this->error = $invoice->error;
$this->errors = $invoice->errors;
$this->setErrorsFromObject($invoice);
$error++;
} else {
$this->invoice = $invoice;
@ -1936,8 +2078,7 @@ class Adherent extends CommonObject
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition
$result = $invoice->addline($label, 0, 1, $vattouse, 0, 0, $idprodsubscription, 0, $datesubscription, '', 0, 0, 0, 'TTC', $amount, 1);
if ($result <= 0) {
$this->error = $invoice->error;
$this->errors = $invoice->errors;
$this->setErrorsFromObject($invoice);
$error++;
}
}
@ -1946,8 +2087,7 @@ class Adherent extends CommonObject
// Validate invoice
$result = $invoice->validate($user);
if ($result <= 0) {
$this->error = $invoice->error;
$this->errors = $invoice->errors;
$this->setErrorsFromObject($invoice);
$error++;
}
}
@ -1975,22 +2115,18 @@ class Adherent extends CommonObject
$paiement->ext_payment_id = $ext_payment_id;
$paiement->ext_payment_site = $ext_payment_site;
if (!$error) {
// Create payment line for invoice
$paiement_id = $paiement->create($user);
if (!($paiement_id > 0)) {
$this->error = $paiement->error;
$this->errors = $paiement->errors;
$error++;
}
// Create payment line for invoice
$paiement_id = $paiement->create($user);
if (!($paiement_id > 0)) {
$this->setErrorsFromObject($paiement);
$error++;
}
if (!$error) {
// Add transaction into bank account
$bank_line_id = $paiement->addPaymentToBank($user, 'payment', '(SubscriptionPayment)', $accountid, $emetteur_nom, $emetteur_banque);
if (!($bank_line_id > 0)) {
$this->error = $paiement->error;
$this->errors = $paiement->errors;
$this->setErrorsFromObject($paiement);
$error++;
}
}
@ -2409,10 +2545,11 @@ class Adherent extends CommonObject
$label = implode($this->getTooltipContentArray($params));
}
$url = DOL_URL_ROOT.'/adherents/card.php?rowid='.((int) $this->id);
$baseurl = DOL_URL_ROOT . '/adherents/card.php';
if ($option == 'subscription') {
$url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.((int) $this->id);
$baseurl = DOL_URL_ROOT . '/adherents/subscription.php';
}
$query = ['rowid' => $this->id];
if ($option != 'nolink') {
// Add param to save lastsearch_values or not
@ -2421,9 +2558,10 @@ class Adherent extends CommonObject
$add_save_lastsearch_values = 1;
}
if ($add_save_lastsearch_values) {
$url .= '&save_lastsearch_values=1';
$query = array_merge($query, ['save_lastsearch_values' => 1]);
}
}
$url = dolBuildUrl($baseurl, $query);
$linkstart .= '<a href="'.$url.'"';
$linkclose = "";
@ -2443,16 +2581,15 @@ class Adherent extends CommonObject
$result .= $linkstart;
if ($withpictoimg) {
$paddafterimage = '';
if (abs($withpictoimg) == 1 || abs($withpictoimg) == 4) {
$morecss .= ' paddingrightonly';
}
// Only picto
if ($withpictoimg > 0) {
$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : $dataparams), 0, 0, $notooltip ? 0 : 1).'</span>';
$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.img_object('', 'user', ' '.($notooltip ? '' : $dataparams), 0, 0, $notooltip ? 0 : 1).'</span>';
} else {
// Picto must be a photo
$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">';
$picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.(($withpictoimg == -3 || $withpictoimg == -4) ? 'small' : ''), 'mini', 0, 1);
$picto .= '</span>';
}
@ -2460,7 +2597,7 @@ class Adherent extends CommonObject
}
if (($withpictoimg > -2 && $withpictoimg != 2) || $withpictoimg == -4) {
if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
$result .= '<span class="nopadding valignmiddle'.((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled').
$result .= '<span class="nopadding valignmiddle'.((!isset($this->status) || $this->status) ? '' : ' strikefordisabled').
($morecss ? ' usertext'.$morecss : '').'">';
}
if ($mode == 'login') {
@ -2973,9 +3110,10 @@ class Adherent extends CommonObject
{
$sql = 'SELECT a.rowid, a.datec as datec,';
$sql .= ' a.datevalid as datev,';
$sql .= ' a.tms as datem,';
$sql .= ' GREATEST(a.tms, aef.tms) as datem,';
$sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
$sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'adherent_extrafields as aef ON aef.fk_object = a.rowid';
$sql .= ' WHERE a.rowid = '.((int) $id);
dol_syslog(get_class($this)."::info", LOG_DEBUG);
@ -3015,7 +3153,7 @@ class Adherent extends CommonObject
$resql = $this->db->query($sql);
if ($resql) {
$obj = $this->db->fetch_object($resql);
$nb = $obj->nb;
$nb = (int) $obj->nb;
$this->db->free($resql);
return $nb;
@ -3186,7 +3324,7 @@ class Adherent extends CommonObject
$subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
$msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
$from = getDolGlobalString('ADHERENT_MAIL_FROM');
$from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
$to = $adherent->email;
$cc = getDolGlobalString('ADHERENT_CC_MAIL_FROM');
@ -3220,9 +3358,9 @@ class Adherent extends CommonObject
if ($message) {
$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($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));
}
// if ($sendtocc) {
// $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
// }
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
$actionmsg = dol_concatdesc($actionmsg, $message);
@ -3290,10 +3428,31 @@ class Adherent extends CommonObject
} else {
$this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
$this->output .= ' Send email successfully to '.$nbok.' members';
if (is_array($listofmembersok)) {
$listofids = '';
$i = 0;
foreach ($listofmembersok as $idmember) {
if ($i > 100) {
$listofids .= ', ...';
break;
}
if (empty($listofids)) {
$listofids .= ' [';
} else {
$listofids .= ', ';
}
$listofids .= $idmember;
$i++;
}
if ($listofids) {
$listofids .= ']';
}
$this->output .= ($listofids ? ' ids='.$listofids : '');
if ($nbko) {
$this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
$listofids = '';
$i = 0;
foreach ($listofmembersok as $idmember) {
foreach ($listofmembersko as $idmember) {
if ($i > 100) {
$listofids .= ', ...';
break;
@ -3309,33 +3468,8 @@ class Adherent extends CommonObject
if ($listofids) {
$listofids .= ']';
}
$this->output .= ($listofids ? ' ids='.$listofids : '');
}
if ($nbko) {
$this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
if (is_array($listofmembersko)) {
$listofids = '';
$i = 0;
foreach ($listofmembersko as $idmember) {
if ($i > 100) {
$listofids .= ', ...';
break;
}
if (empty($listofids)) {
$listofids .= ' [';
} else {
$listofids .= ', ';
}
$listofids .= $idmember;
$i++;
}
if ($listofids) {
$listofids .= ']';
}
$this->output .= ($listofids ? ' ids='.$listofids : '');
}
}
}
return $nbko;
@ -3355,25 +3489,23 @@ class Adherent extends CommonObject
$return = '<div class="box-flex-item box-flex-grow-zero">';
$return .= '<div class="info-box info-box-sm">';
$return .= '<span class="info-box-icon bg-infobox-action">';
if (property_exists($this, 'photo') || !empty($this->photo)) {
if (!empty($this->photo)) {
$return .= Form::showphoto('memberphoto', $this, 0, 60, 0, 'photokanban photowithmargin photologintooltip', 'small', 0, 1);
} else {
$return .= img_picto('', 'user');
}
$return .= '</span>';
$return .= '<div class="info-box-content">';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl() . '</span>';
if ($selected >= 0) {
$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
$return .= '<br><span class="info-box-label paddingright">'.$this->getmorphylib('', 2).'</span>';
$return .= '<span class="info-box-label opacitymedium">'.$this->type.'</span>';
if (method_exists($this, 'getLibStatut')) {
$return .= '<br><div class="info-box-status paddingtop">';
$return .= $this->LibStatut($this->status, $this->need_subscription, $this->datefin, 5);
$return .= '</div>';
}
$return .= '<br><div class="info-box-status paddingtop">';
$return .= $this->LibStatut($this->status, $this->need_subscription, $this->datefin, 5);
$return .= '</div>';
$return .= '</div>';
$return .= '</div>';
$return .= '</div>';

View file

@ -5,7 +5,7 @@
* Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
* Copyright (C) 2018-2019 Thibault Foucart <support@ptibogxiv.net>
* Copyright (C) 2021 Waël Almoman <info@almoman.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@ -84,7 +84,7 @@ class AdherentType extends CommonObject
* 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
* 'noteditable' says if field is not editable (1 or 0)
* 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0')
* 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
* 'default' is a default value for creation (can still be overwritten by the Setup of Default Values if the field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
* 'index' if we want an index in database.
* 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
* 'searchall' is 1 if we want to search in this field when making a search from the quick search button.
@ -141,7 +141,7 @@ class AdherentType extends CommonObject
public $morphy;
/**
* @var string
* @var ?string
*/
public $duration;
@ -156,7 +156,7 @@ class AdherentType extends CommonObject
public $duration_unit;
/**
* @var int<0,1> Subscription required (0 or 1)
* @var null|'0'|'1' Subscription required (0 or 1) default '1' in DB, null until value is fetched
*/
public $subscription;
@ -180,7 +180,7 @@ class AdherentType extends CommonObject
public $note_public;
/**
* @var int<0,1> Can vote
* @var null|int<0,1> Can vote, null until fetched
*/
public $vote;
@ -516,11 +516,9 @@ class AdherentType extends CommonObject
}
// Actions on extra fields
if (!$error) {
$result = $this->insertExtraFields();
if ($result < 0) {
$error++;
}
$result = $this->insertExtraFields();
if ($result < 0) {
$error++;
}
if (!$error && !$notrigger) {
@ -709,6 +707,81 @@ class AdherentType extends CommonObject
return $amountbytype;
}
/**
* Return the array of morphy per membership type id
*
* @param int $status Filter on status of type
* @return array<int,string> Array of membership type
*/
public function morphyByType($status = null)
{
$morphybytype = array();
$sql = "SELECT rowid, morphy";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type";
$sql .= " WHERE entity IN (".getEntity('member_type').")";
if ($status !== null) {
$sql .= " AND statut = ".((int) $status);
}
$resql = $this->db->query($sql);
if ($resql) {
$nump = $this->db->num_rows($resql);
if ($nump) {
$i = 0;
while ($i < $nump) {
$obj = $this->db->fetch_object($resql);
$morphybytype[$obj->rowid] = $obj->morphy;
$i++;
}
}
} else {
print $this->db->error();
}
return $morphybytype;
}
/**
* Return the array of caneditamount per membership type id
*
* @param int $status Filter on status of type
* @return array<int,string> Array of membership type
*/
public function caneditamountByType($status = null)
{
$caneditamountbytype = array();
$sql = "SELECT rowid, caneditamount";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type";
$sql .= " WHERE entity IN (".getEntity('member_type').")";
if ($status !== null) {
$sql .= " AND statut = ".((int) $status);
}
$resql = $this->db->query($sql);
if ($resql) {
$nump = $this->db->num_rows($resql);
if ($nump) {
$i = 0;
while ($i < $nump) {
$obj = $this->db->fetch_object($resql);
$caneditamountbytype[$obj->rowid] = $obj->caneditamount;
$i++;
}
}
} else {
print $this->db->error();
}
return $caneditamountbytype;
}
/**
* Return array of Member objects for member type this->id (or all if this->id not defined)
*
@ -795,7 +868,7 @@ class AdherentType extends CommonObject
$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("MemberType").'</u> '.$this->getLibStatut(4);
$datas['label'] = '<br>'.$langs->trans("Label").': '.$this->label;
if (isset($this->subscription)) {
$datas['subscription'] = '<br>'.$langs->trans("SubscriptionRequired").': '.yn($this->subscription);
$datas['subscription'] = '<br>'.$langs->trans("SubscriptionRequired").': '.yn((int) $this->subscription);
}
if (isset($this->vote)) {
$datas['vote'] = '<br>'.$langs->trans("VoteAllowed").': '.yn($this->vote);
@ -803,9 +876,23 @@ class AdherentType extends CommonObject
if (isset($this->duration)) {
$datas['duration'] = '<br>'.$langs->trans("Duration").': '.$this->duration_value;
if ($this->duration_value > 1) {
$dur = array("i" => $langs->trans("Minutes"), "h" => $langs->trans("Hours"), "d" => $langs->trans("Days"), "w" => $langs->trans("Weeks"), "m" => $langs->trans("Months"), "y" => $langs->trans("Years"));
$dur = array(
"i" => $langs->trans("Minutes"),
"h" => $langs->trans("Hours"),
"d" => $langs->trans("Days"),
"w" => $langs->trans("Weeks"),
"m" => $langs->trans("Months"),
"y" => $langs->trans("Years")
);
} elseif ($this->duration_value > 0) {
$dur = array("i" => $langs->trans("Minute"), "h" => $langs->trans("Hour"), "d" => $langs->trans("Day"), "w" => $langs->trans("Week"), "m" => $langs->trans("Month"), "y" => $langs->trans("Year"));
$dur = array(
"i" => $langs->trans("Minute"),
"h" => $langs->trans("Hour"),
"d" => $langs->trans("Day"),
"w" => $langs->trans("Week"),
"m" => $langs->trans("Month"),
"y" => $langs->trans("Year")
);
}
$datas['duration'] .= "&nbsp;" . (!empty($this->duration_unit) && isset($dur[$this->duration_unit]) ? $langs->trans($dur[$this->duration_unit]) : '');
}
@ -826,14 +913,12 @@ class AdherentType extends CommonObject
public function getNomUrl($withpicto = 0, $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
{
$result = '';
$option = '';
$classfortooltip = 'classfortooltip';
$dataparams = '';
$params = [
'id' => $this->id,
'objecttype' => $this->element,
'option' => $option,
'nofetch' => 1,
];
if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
@ -844,17 +929,18 @@ class AdherentType extends CommonObject
$label = implode($this->getTooltipContentArray($params));
}
$url = DOL_URL_ROOT.'/adherents/type.php?rowid='.((int) $this->id);
if ($option != 'nolink') {
// Add param to save lastsearch_values or not
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
$add_save_lastsearch_values = 1;
}
if ($add_save_lastsearch_values) {
$url .= '&save_lastsearch_values=1';
}
$baseurl = DOL_URL_ROOT . '/adherents/type.php';
$query = ['rowid' => $this->id];
// Add param to save lastsearch_values or not
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
$add_save_lastsearch_values = 1;
}
if ($add_save_lastsearch_values) {
$query = array_merge($query, ['save_lastsearch_values' => 1]);
}
$url = dolBuildUrl($baseurl, $query);
$linkstart = '<a href="'.$url.'"';
$linkstart .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
$linkstart .= $dataparams.' class="'.$classfortooltip.'">';
@ -999,7 +1085,7 @@ class AdherentType extends CommonObject
$this->label = 'MEMBERS TYPE SPECIMEN';
$this->note_public = 'This is a public note';
$this->mail_valid = 'This is welcome email';
$this->subscription = 1;
$this->subscription = '1';
$this->caneditamount = 0;
$this->vote = 0;
@ -1092,7 +1178,7 @@ class AdherentType extends CommonObject
$return .= img_picto('', $this->picto);
$return .= '</span>';
$return .= '<div class="info-box-content">';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl() . '</span>';
//$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
@ -1101,20 +1187,14 @@ class AdherentType extends CommonObject
} else {
$return .= '<span class="right">&nbsp;</span>';
}
if (property_exists($this, 'vote')) {
$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("VoteAllowed").' : '.yn($this->vote).'</span>';
}
if (property_exists($this, 'amount')) {
if (is_null($this->amount) || $this->amount === '') {
$return .= '<br>';
} else {
$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("Amount").'</span>';
$return .= '<span class="amount"> : '.price($this->amount).'</span>';
}
}
if (method_exists($this, 'getLibStatut')) {
$return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("VoteAllowed").' : '.yn($this->vote).'</span>';
if (is_null($this->amount) || $this->amount === '') {
$return .= '<br>';
} else {
$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("Amount").'</span>';
$return .= '<span class="amount"> : '.price($this->amount).'</span>';
}
$return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
$return .= '</div>';
$return .= '</div>';
$return .= '</div>';

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2016 Xebax Christy <xebax@wanadoo.fr>
* Copyright (C) 2017 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2020-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2020-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
@ -138,7 +138,7 @@ class Members extends DolibarrApi
throw new RestException(403);
}
$sql = "SELECT rowid, fk_soc, key_account, site, date_creation, tms FROM ".MAIN_DB_PREFIX."societe_account";
$sql = "SELECT rowid, fk_soc as socid, key_account, site, date_creation, tms FROM ".MAIN_DB_PREFIX."societe_account";
$sql .= " WHERE site = '".$this->db->escape($site)."' AND key_account = '".$this->db->escape($key_account)."'";
$sql .= " AND entity IN (".getEntity('adherent').")";
@ -147,7 +147,7 @@ class Members extends DolibarrApi
if ($result && $this->db->num_rows($result) == 1) {
$obj = $this->db->fetch_object($result);
$thirdparty = new Societe($this->db);
$result = $thirdparty->fetch($obj->fk_soc);
$result = $thirdparty->fetch($obj->socid);
if ($result <= 0) {
throw new RestException(404, 'thirdparty not found');
@ -655,14 +655,15 @@ class Members extends DolibarrApi
*
* @throws RestException 403 Access denied
* @throws RestException 404 Member not found
* @throws RestException 422 Malformed data
*/
public function createSubscription($id, $start_date, $end_date, $amount, $label = '')
{
if (!DolibarrApiAccess::$user->hasRight('adherent', 'cotisation', 'creer')) {
throw new RestException(403);
}
if (is_numeric($start_date) || !is_numeric($end_date) || !is_numeric($amount)) {
throw new RestException(422, 'Malformed data');
if (!is_numeric($start_date) || !is_numeric($end_date) || !is_numeric($amount)) {
throw new RestException(422, 'Malformed data: subscription start or end date, or subscription amount, is not numeric');
}
$member = new Adherent($this->db);

View file

@ -139,7 +139,8 @@ class Subscriptions extends DolibarrApi
if ($result) {
$i = 0;
$num = $this->db->num_rows($result);
while ($i < min($limit, $num)) {
$min = min($num, ($limit <= 0 ? $num : $limit));
while ($i < $min) {
$obj = $this->db->fetch_object($result);
$subscription = new Subscription($this->db);
if ($subscription->fetch($obj->rowid)) {

View file

@ -1,8 +1,8 @@
<?php
/* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
/* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 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
* it under the terms of the GNU General Public License as published by
@ -165,12 +165,14 @@ class Subscription extends CommonObject
$type = $this->fk_type;
}
$sql = "INSERT INTO ".MAIN_DB_PREFIX."subscription (fk_adherent, fk_type, datec, dateadh, datef, subscription, note, fk_user_creat)";
$sql = "INSERT INTO ".MAIN_DB_PREFIX."subscription (fk_adherent, fk_type, datec, dateadh, datef, subscription, note, note_private, ref_ext, fk_user_creat)";
$sql .= " VALUES (".((int) $this->fk_adherent).", '".$this->db->escape((string) $type)."', '".$this->db->idate($now)."',";
$sql .= " '".$this->db->idate($this->dateh)."',";
$sql .= " '".$this->db->idate($this->datef)."',";
$sql .= " ".((float) $this->amount).",";
$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 .= ")";
@ -319,7 +321,7 @@ class Subscription extends CommonObject
$result = $member->fetch($this->fk_adherent);
$result = $member->update_end_date($user);
if (!$error && !$notrigger) {
if (!$notrigger) {
$this->context = array('member' => $member);
// Call triggers
$result = $this->call_trigger('MEMBER_SUBSCRIPTION_MODIFY', $user);
@ -365,15 +367,13 @@ class Subscription extends CommonObject
$this->db->begin();
if (!$error) {
if (!$notrigger) {
// Call triggers
$result = $this->call_trigger('MEMBER_SUBSCRIPTION_DELETE', $user);
if ($result < 0) {
$error++;
} // Do also here what you must do to rollback action if trigger fail
// End call triggers
}
if (!$notrigger) {
// Call triggers
$result = $this->call_trigger('MEMBER_SUBSCRIPTION_DELETE', $user);
if ($result < 0) {
$error++;
} // Do also here what you must do to rollback action if trigger fail
// End call triggers
}
if (!$error) {
@ -390,17 +390,10 @@ class Subscription extends CommonObject
if ($this->fk_bank > 0 && is_object($accountline) && $accountline->id > 0) { // If we found bank account line (this means this->fk_bank defined)
$result = $accountline->delete($user); // Return false if refused because line is reconciled
if ($result > 0) {
$this->db->commit();
return 1;
} else {
$this->error = $accountline->error;
$this->db->rollback();
return -1;
if ($result <= 0) {
$this->setErrorsFromObject($accountline);
$error++;
}
} else {
$this->db->commit();
return 1;
}
} else {
$this->db->commit();
@ -452,9 +445,8 @@ class Subscription extends CommonObject
if (!empty($this->datef)) {
$label .= '<br><b>'.$langs->trans('DateEnd').':</b> '.dol_print_date($this->datef, 'day');
}
$url = DOL_URL_ROOT.'/adherents/subscription/card.php?rowid='.((int) $this->id);
$baseurl = DOL_URL_ROOT . '/adherents/subscription/card.php';
$query = ['rowid' => $this->id];
if ($option != 'nolink') {
// Add param to save lastsearch_values or not
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
@ -462,9 +454,10 @@ class Subscription extends CommonObject
$add_save_lastsearch_values = 1;
}
if ($add_save_lastsearch_values) {
$url .= '&save_lastsearch_values=1';
$query = array_merge($query, ['save_lastsearch_values' => 1]);
}
}
$url = dolBuildUrl($baseurl, $query);
$linkstart = '<a href="'.$url.'" class="classfortooltip" title="'.dol_escape_htmltag($label, 1).'">';
$linkend = '</a>';
@ -564,7 +557,7 @@ class Subscription extends CommonObject
if ($selected >= 0) {
$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
if (property_exists($this, 'dateh') || property_exists($this, 'datef')) {
if (!empty($this->dateh) || !empty($this->datef)) {
$return .= '<br><span class="info-box-status opacitymedium small">'.dol_print_date($this->dateh, 'day').' - '.dol_print_date($this->datef, 'day').'</span>';
}
@ -572,15 +565,14 @@ class Subscription extends CommonObject
$return .= '<br><div class="inline-block tdoverflowmax150">'.$arraydata['member']->getNomUrl(-4).'</div>';
}
if (property_exists($this, 'amount')) {
$return .= '<br><span class="amount inline-block">'.price($this->amount).'</span>';
if (!empty($arraydata['bank'])) {
$return .= ' &nbsp; <span class="info-box-label ">'.$arraydata['bank']->getNomUrl(-1).'</span>';
}
$return .= '<br><span class="amount inline-block">'.price($this->amount).'</span>';
if (!empty($arraydata['bank'])) {
$return .= ' &nbsp; <span class="info-box-label ">'.$arraydata['bank']->getNomUrl(-1).'</span>';
}
$return .= '</div>';
$return .= '</div>';
$return .= '</div>';
return $return;
}
}

View file

@ -5,7 +5,7 @@
* Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -150,7 +150,7 @@ if ($id > 0) {
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref);

View file

@ -57,7 +57,7 @@ $massaction = GETPOST('massaction', 'alpha');
$show_files = GETPOSTINT('show_files');
$confirm = GETPOST('confirm', 'alpha');
$cancel = GETPOST('cancel', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'memberslist'; // To manage different context of search
$backtopage = GETPOST('backtopage', 'alpha');
$optioncss = GETPOST('optioncss', 'aZ');
@ -406,7 +406,7 @@ $memberstatic = new Adherent($db);
$now = dol_now();
// Page Header
$title = $langs->trans("Members")." - ".$langs->trans("List");
$title = $langs->trans("Members");
$help_url = 'EN:Module_Foundations|FR:Module_Adh&eacute;rents|ES:M&oacute;dulo_Miembros|DE:Modul_Mitglieder';
$morejs = array();
$morecss = array();
@ -415,7 +415,7 @@ $morecss = array();
// Build and execute select
// --------------------------------------------------------------------
$sql = "SELECT";
$sql .= " d.rowid, d.ref, d.login, d.lastname, d.firstname, d.gender, d.societe as company, d.fk_soc,";
$sql .= " d.rowid, d.ref, d.login, d.lastname, d.firstname, d.gender, d.societe as company, d.fk_soc as socid,";
$sql .= " d.civility, d.datefin, d.address, d.zip, d.town, d.state_id, d.country,";
$sql .= " d.email, d.phone, d.phone_perso, d.phone_mobile, d.birth, d.public, d.photo,";
$sql .= " d.fk_adherent_type as type_id, d.morphy, d.statut as status, d.datec as date_creation, d.tms as date_modification,";
@ -1228,7 +1228,7 @@ while ($i < $imaxinloop) {
$memberstatic->gender = $obj->gender;
$memberstatic->status = $obj->status;
$memberstatic->datefin = $datefin;
$memberstatic->socid = $obj->fk_soc;
$memberstatic->socid = $obj->socid;
$memberstatic->photo = $obj->photo;
$memberstatic->email = $obj->email;
$memberstatic->morphy = $obj->morphy;
@ -1236,7 +1236,7 @@ while ($i < $imaxinloop) {
$memberstatic->note_private = $obj->note_private;
$memberstatic->need_subscription = $obj->subscription;
if (!empty($obj->fk_soc)) {
if (!empty($obj->socid)) {
$memberstatic->fetch_thirdparty();
if ($memberstatic->thirdparty->id > 0) {
$companyname = $memberstatic->thirdparty->name;
@ -1273,7 +1273,7 @@ while ($i < $imaxinloop) {
} else {
// Show line of result
$j = 0;
print '<tr data-rowid="'.$object->id.'" class="oddeven">';
print '<tr data-rowid="'.$object->id.'" class="oddeven row-with-select">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {

View file

@ -6,7 +6,7 @@
* Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
* Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
*
* This program is free software; you can redistribute it and/or modify
@ -147,7 +147,7 @@ print dol_get_fiche_head($head, 'agenda', $langs->trans("Member"), -1, 'user');
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref);

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2015-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2015-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
@ -94,9 +94,11 @@ $hookmanager->initHooks(array('membernote'));
// Security check
$result = restrictedArea($user, 'adherent', $object->id, '', '', 'socid', 'rowid', 0);
/*
* Actions
*/
$parameters = array();
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {
@ -129,7 +131,7 @@ if (is_object($adht)) {
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref);

View file

@ -113,7 +113,7 @@ if (($action == 'update' || $action == 'edit') && $object->status != $object::ST
// Security check
$result = restrictedArea($user, 'adherent', $id, '', '', 'socid', 'rowid', 0);
restrictedArea($user, 'adherent', $id, '', '', 'socid', 'rowid', 0);
/*

View file

@ -49,7 +49,7 @@ if ($user->socid > 0) {
$action = '';
$socid = $user->socid;
}
$result = restrictedArea($user, 'adherent', '', '', 'cotisation');
restrictedArea($user, 'adherent', '', '', 'cotisation');
$year = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));

View file

@ -51,7 +51,7 @@ if ($user->socid > 0) {
$action = '';
$socid = $user->socid;
}
$result = restrictedArea($user, 'adherent', '', '', 'cotisation');
restrictedArea($user, 'adherent', '', '', 'cotisation');
$year = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));

View file

@ -57,7 +57,7 @@ if ($user->socid > 0) {
$action = '';
$socid = $user->socid;
}
$result = restrictedArea($user, 'adherent', '', '', 'cotisation');
restrictedArea($user, 'adherent', '', '', 'cotisation');
$year = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
$startyear = $year - (!getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));

View file

@ -4,7 +4,7 @@
* Copyright (C) 2004-2018 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012-2017 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2015-2024 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2019 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2023 Waël Almoman <info@almoman.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
@ -496,7 +496,7 @@ print dol_get_fiche_head($head, 'subscription', $langs->trans("Member"), -1, 'us
$linkback = '<a href="'.DOL_URL_ROOT.'/adherents/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '<a href="'.DOL_URL_ROOT.'/adherents/vcard.php?id='.$object->id.'" class="refid">';
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard', 'class="valignmiddle marginleftonly paddingrightonly"');
$morehtmlref .= '</a>';
dol_banner_tab($object, 'rowid', $linkback, 1, 'rowid', 'ref', $morehtmlref);
@ -631,7 +631,7 @@ if (isModEnabled('societe')) {
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<table class="nobordernopadding">';
print '<tr><td>';
print $form->select_company($object->fk_soc, 'socid', '', 1);
print $form->select_company($object->socid, 'socid', '', 1);
print '</td>';
print '<td class="left"><input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'"></td>';
print '</tr></table></form>';
@ -1055,11 +1055,11 @@ if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->h
print '<input type="radio" class="moreaction" id="invoiceonly" name="paymentsave" value="invoiceonly"'.(!empty($invoiceonly) ? ' checked' : '');
//if (empty($object->fk_soc)) print ' disabled';
print '><label for="invoiceonly"> '.$langs->trans("MoreActionInvoiceOnly");
if ($object->fk_soc) {
if ($object->socid) {
print ' ('.$langs->trans("ThirdParty").': '.$company->getNomUrl(1).')';
} else {
print ' (';
if (empty($object->fk_soc)) {
if (empty($object->socid)) {
print img_warning($langs->trans("NoThirdPartyAssociatedToMember"));
}
print $langs->trans("NoThirdPartyAssociatedToMember");
@ -1083,7 +1083,7 @@ if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->h
// Add invoice with payments
if (isModEnabled('bank') && isModEnabled('societe') && isModEnabled('invoice')) {
print '<input type="radio" class="moreaction" id="bankviainvoice" name="paymentsave" value="bankviainvoice"'.(!empty($bankviainvoice) ? ' checked' : '');
//if (empty($object->fk_soc)) print ' disabled';
//if (empty($object->socid)) print ' disabled';
print '><label for="bankviainvoice"> '.$langs->trans("MoreActionBankViaInvoice");
if ($object->socid) {
print ' ('.$langs->trans("ThirdParty").': '.$company->getNomUrl(1).')';
@ -1187,7 +1187,7 @@ if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->h
$tmp = '<input name="sendmail" type="checkbox"'.(GETPOST('sendmail', 'alpha') ? ' checked' : (getDolGlobalString('ADHERENT_DEFAULT_SENDINFOBYMAIL') ? ' checked' : '')).'>';
$helpcontent = '';
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM').'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from).'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailRecipient").'</b>: '.$object->email.'<br>'."\n";
$helpcontent .= '<b>'.$langs->trans("MailTopic").'</b>:<br>'."\n";
if ($subjecttosend) {

View file

@ -4,7 +4,7 @@
* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -48,7 +48,7 @@ $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choi
$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
@ -120,7 +120,7 @@ $arrayfields = array(
);
// Security check
$result = restrictedArea($user, 'adherent', '', '', 'cotisation');
restrictedArea($user, 'adherent', '', '', 'cotisation');
$permissiontodelete = $user->hasRight('adherent', 'cotisation', 'creer');
@ -637,7 +637,7 @@ while ($i < $imaxinloop) {
$adht = new AdherentType($db);
$adht->fetch($typeid);
$adherent->need_subscription = $adht->subscription;
$adherent->need_subscription = (int) $adht->subscription;
if ($mode == 'kanban') {
if ($i == 0) {
@ -737,7 +737,7 @@ while ($i < $imaxinloop) {
// Banque
if (!empty($arrayfields['d.bank']['checked'])) {
print '<td class="tdmaxoverflow100">';
print '<td class="tdoverflowmax100">';
if ($obj->fk_account > 0) {
$accountstatic->id = $obj->fk_account;
$accountstatic->fetch($obj->fk_account);

View file

@ -54,7 +54,7 @@ $rowid = GETPOSTINT('rowid');
$action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha');
$cancel = GETPOST('cancel', 'alpha');
$toselect = GETPOST('toselect', 'array');
$toselect = GETPOST('toselect', 'array:int');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
$backtopage = GETPOST('backtopage', 'alpha');
$mode = GETPOST('mode', 'alpha');
@ -172,7 +172,7 @@ if ($action == 'add' && $user->hasRight('adherent', 'configurer')) {
$object->label = trim($label);
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (int) $subscription;
$object->subscription = (string) (int) $subscription;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->caneditamount = $caneditamount;
$object->duration_value = $duration_value;
@ -233,7 +233,7 @@ if ($action == 'update' && $user->hasRight('adherent', 'configurer')) {
$object->label = trim($label);
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (int) $subscription;
$object->subscription = (string) (int) $subscription;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->caneditamount = $caneditamount;
$object->duration_value = $duration_value;
@ -554,10 +554,11 @@ if ($action == 'create') {
print '</td></tr>';
// Morphy
$morphys = array();
$morphys[""] = $langs->trans("MorAndPhy");
$morphys["phy"] = $langs->trans("Physical");
$morphys["mor"] = $langs->trans("Moral");
$morphys = [
"" => $langs->trans("MorAndPhy"), // for empty choice
"phy" => $langs->trans("Physical"),
"mor" => $langs->trans("Moral"),
];
print '<tr><td><span>'.$langs->trans("MembersNature").'</span></td><td>';
print $form->selectarray("morphy", $morphys, GETPOSTISSET("morphy") ? GETPOST("morphy", 'aZ09') : 'morphy');
print "</td></tr>";
@ -639,7 +640,7 @@ if ($rowid > 0) {
print '</tr>';
print '<tr><td>'.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).'</td><td>';
print yn($object->subscription);
print yn((int) $object->subscription);
print '</tr>';
// Amount
@ -696,7 +697,7 @@ if ($rowid > 0) {
// Edit
if ($user->hasRight('adherent', 'configurer')) {
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=edit&token='.newToken().'&rowid='.$object->id.'">'.$langs->trans("Modify").'</a></div>';
print '<div class="inline-block divButAction"><a class="butAction" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'edit', 'rowid' => $object->id], true).'">'.$langs->trans("Modify").'</a></div>';
}
// Add
@ -709,14 +710,14 @@ if ($rowid > 0) {
}
if ($user->hasRight('adherent', 'configurer') && !empty($object->status)) {
print '<div class="inline-block divButAction"><a class="butAction" href="card.php?action=create&token='.newToken().'&typeid='.$object->id.($morphy ? '&morphy='.urlencode($morphy) : '').'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?rowid='.$object->id).'">'.$langs->trans("AddMember").'</a></div>';
print '<div class="inline-block divButAction"><a class="butAction" href="'.dolBuildUrl('card.php', ['action' => 'create', 'typeid' => $object->id, 'morphy' => ($morphy ? $morphy : ''), 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['rowid' => $object->id])], true).'">'.$langs->trans("AddMember").'</a></div>';
} else {
print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NoAddMember")).'">'.$langs->trans("AddMember").'</a></div>';
}
// Delete
if ($user->hasRight('adherent', 'configurer')) {
print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?action=delete&token='.newToken().'&rowid='.$object->id.'">'.$langs->trans("DeleteType").'</a></div>';
print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'delete', 'rowid' => $object->id], true).'">'.$langs->trans("DeleteType").'</a></div>';
}
print "</div>";
@ -828,34 +829,35 @@ if ($rowid > 0) {
$titre .= " (".$membertype->label.")";
}
$param = "&rowid=".urlencode((string) ($object->id));
$query = ['rowid' => $object->id];
if (!empty($mode)) {
$param .= '&mode='.urlencode($mode);
$query+= ['mode' => $mode];
}
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
$param .= '&contextpage='.urlencode($contextpage);
$query += ['contextpage' => $contextpage];
}
if ($limit > 0 && $limit != $conf->liste_limit) {
$param .= '&limit='.((int) $limit);
$query += ['limit' => $limit];
}
if (!empty($status)) {
$param .= "&status=".urlencode($status);
$query += ['status' => $status];
}
if (!empty($search_ref)) {
$param .= "&search_ref=".urlencode($search_ref);
$query += ['search_ref' => $search_ref];
}
if (!empty($search_lastname)) {
$param .= "&search_lastname=".urlencode($search_lastname);
$query += ['search_lastname' => $search_lastname];
}
if (!empty($search_login)) {
$param .= "&search_login=".urlencode($search_login);
$query += ['search_login' => $search_login];
}
if (!empty($search_email)) {
$param .= "&search_email=".urlencode($search_email);
$query += ['search_email' => $search_email];
}
if (!empty($filter)) {
$param .= "&filter=".urlencode($filter);
$query += ['filter' => $filter];
}
$param = '&' . http_build_query($query);
if ($sall) {
print $langs->trans("Filter")." (".$langs->trans("Lastname").", ".$langs->trans("Firstname").", ".$langs->trans("EMail").", ".$langs->trans("Address")." ".$langs->trans("or")." ".$langs->trans("Town")."): ".$sall;
@ -953,10 +955,10 @@ if ($rowid > 0) {
if ($conf->main_checkbox_left_column) {
print '<td class="center">';
if ($user->hasRight('adherent', 'creer')) {
print '<a class="editfielda marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=edit&token='.newToken().'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?rowid='.$object->id).'">'.img_edit().'</a>';
print '<a class="editfielda marginleftonly" href="'.dolBuildUrl('card.php', ['rowid' => $objp->rowid, 'action' => 'edit', 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['rowid' => $object->id])], true).'">'.img_edit().'</a>';
}
if ($user->hasRight('adherent', 'supprimer')) {
print '<a class="marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=resiliate&token='.newToken().'">'.img_picto($langs->trans("Resiliate"), 'disable.png').'</a>';
print '<a class="marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=resiliate&token='.newToken().'">'.img_picto($langs->trans("Resiliate"), 'unlink').'</a>';
}
print "</td>";
}
@ -1021,10 +1023,10 @@ if ($rowid > 0) {
if (!$conf->main_checkbox_left_column) {
print '<td class="center">';
if ($user->hasRight('adherent', 'creer')) {
print '<a class="editfielda marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=edit&token='.newToken().'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?rowid='.$object->id).'">'.img_edit().'</a>';
print '<a class="editfielda marginleftonly" href="'.dolBuildUrl('card.php', ['rowid' => $objp->rowid, 'action' => 'edit', 'backtopage' => dolBuildUrl($_SERVER["PHP_SELF"], ['rowid' => $object->id])], true).'">'.img_edit().'</a>';
}
if ($user->hasRight('adherent', 'supprimer')) {
print '<a class="marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=resiliate&token='.newToken().'">'.img_picto($langs->trans("Resiliate"), 'disable.png').'</a>';
print '<a class="marginleftonly" href="card.php?rowid='.$objp->rowid.'&action=resiliate&token='.newToken().'">'.img_picto($langs->trans("Resiliate"), 'unlink').'</a>';
}
print "</td>";
}

View file

@ -25,12 +25,6 @@
// Load Dolibarr environment
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/ldap.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/ldap.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
@ -38,6 +32,11 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/ldap.lib.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/ldap.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/ldap.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "members", "ldap"));
@ -54,11 +53,11 @@ $result = restrictedArea($user, 'adherent', $id, 'adherent_type');
$object = new AdherentType($db);
$object->fetch($id);
/*
* Actions
*/
$parameters = array();
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {

View file

@ -50,6 +50,8 @@ if (!$user->admin) {
$error = 0;
$object = new stdClass();
/*
* Actions

Some files were not shown because too many files have changed in this diff Show more