Compare commits

..

180 Commits

Author SHA1 Message Date
Laurent Destailleur
b9f5895c68 Automated merge from 22.0 to 23.0 by tool pullmerge.sh 2026-03-12 23:40:02 +01:00
Laurent Destailleur
c76d781e30 Automated merge from 21.0 to 22.0 by tool pullmerge.sh 2026-03-12 23:36:15 +01:00
Laurent Destailleur
488366cf06 Automated merge from 20.0 to 21.0 by tool pullmerge.sh 2026-03-12 23:36:12 +01:00
Laurent Destailleur
584e103ebf Automated merge from 19.0 to 20.0 by tool pullmerge.sh 2026-03-12 23:35:37 +01:00
Laurent Destailleur
058c8ee9b0 Automated merge from 18.0 to 19.0 by tool pullmerge.sh 2026-03-12 23:26:55 +01:00
Laurent Destailleur
f86955fcf9 Automated merge from 17.0 to 18.0 by tool pullmerge.sh 2026-03-12 23:15:12 +01:00
Vincent Maury
1582f1afb9 Fix Inventory bugs #33192 and #35207 (#37405)
* Fix Inventory bugs #33207 and #33292 : when click on "validate and generate movements" quantities not still recorded are not recorded

* Fix Inventory bugs #33207 and #33292 : when click on "validate and generate movements" quantities not still recorded are not recorded

* Fix Inventory bugs #33207 and #33292 : when click on "validate and generate movements" quantities not still recorded are not recorded

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
2026-03-12 23:10:36 +01:00
Laurent Destailleur
f23b1801e5 Revert "Revert "Fix ticket categories dictionay (#37434)""
This reverts commit ff204097e3.
2026-03-12 21:42:20 +01:00
Maxime Kohlhaas
e29b741958 Fix : disabled extrafield should not appear on PDF (#37442) 2026-03-12 14:40:36 +01:00
Laurent Destailleur
ff204097e3 Revert "Fix ticket categories dictionay (#37434)"
This reverts commit a9db2f6dba.
2026-03-12 14:14:17 +01:00
SAINT-PATRICE
b1e693a1ac Update contratligne.class.php for Postgres active_line and close_line (#37477)
* Update contratligne.class.php for Postgres

* Update contratligne.class.php close_line for postgres
2026-03-12 14:02:27 +01:00
Juan Pablo Farber
502bc82815 QUAL Replace $_REQUEST superglobals with GETPOST() in projet and compta/tva (#37456)
* Fix: replace $_REQUEST with GETPOST() in projet/note.php

Use GETPOST('mode', 'alpha') instead of direct $_REQUEST['mode']
access to follow Dolibarr coding conventions for input sanitization.

* Fix: replace $_REQUEST with GETPOSTINT() in compta/tva/clients.php

Use GETPOSTINT('extra_report') instead of direct $_REQUEST access
to follow Dolibarr coding conventions for input sanitization.
2026-03-12 13:51:23 +01:00
Zakaria Boushaba
fd71eba41e FIX: Fix mandatory custom fields JS validation in printCommonFooter (#37469)
* Fix mandatory fields JS: use name selector instead of id, fix undefined buttonName on create, fix HTML entities in alert message

* Update alert message for empty field validation

---------

Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-12 13:47:12 +01:00
lvessiller-opendsi
ea60298eeb FIX show export full documents checkbox on change format in accountancy export (#37468)
* FIX show export full documents checkbox on change format in accountancy export

* FIX remove unused var
2026-03-12 13:46:23 +01:00
Laurent Destailleur
3016301ae8 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-03-12 11:40:07 +01:00
Laurent Destailleur
2065dee731 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-03-12 11:36:14 +01:00
Laurent Destailleur
6689f5bb52 Test 2026-03-12 11:36:05 +01:00
Laurent Destailleur
cd0a4016ff Fix regressions 2026-03-12 11:12:35 +01:00
Eric - CAP-REL
bf77993fc9 Merge pull request #37429 from thomas-Ngr/18_fix_api_warehouse_by_id
FIX API Warehouse : Error 401 when getting warehouse by id (backport from 22)
2026-03-12 10:04:30 +01:00
Laurent Destailleur
d615300b7a Doc 2026-03-12 02:11:48 +01:00
Vincent Penel
d2bbba5a21 Fixing the 'formConfirm' hook on tickets (#37473)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-12 01:20:03 +01:00
Laurent Destailleur
1f952b6969 Fix leftmenu 2026-03-12 00:22:32 +01:00
ATM-NicolasV
ca957917e5 Fix mainmenu redirection in (#37471)
accounting configuration
2026-03-12 00:06:43 +01:00
Vincent de Grandpré
5079e49023 Fix #37465 (#37466) 2026-03-12 00:03:05 +01:00
splohmer
45d862c0e8 FIX Order API: delete order returns wrong http response in case order could not be deleted (#37472) 2026-03-11 23:44:18 +01:00
Laurent Destailleur
02885b4a5b CI 2026-03-11 23:43:00 +01:00
Laurent Destailleur
432361304a FIX Better compatibility for module using condition object-> in tabs 2026-03-11 23:09:50 +01:00
Laurent Destailleur
8e68db2f58 css 2026-03-10 21:15:59 +01:00
Laurent Destailleur
e4d8d3047e FIX translation on multiselect with rich label - Fix CSS public ticket 2026-03-10 19:55:15 +01:00
Laurent Destailleur
8ba2977d58 Trans 2026-03-10 18:27:23 +01:00
Laurent Destailleur
7e7a11cef1 css 2026-03-09 19:02:57 +01:00
Laurent Destailleur
7e203114eb Disable featureof rule for lines date too buggied.
Substitution date are corrupted by bad date values and feature speak
about payments/prepayments when this is just related to date!
2026-03-09 10:38:56 +01:00
Laurent Destailleur
6944c5584f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-03-09 09:52:23 +01:00
Laurent Destailleur
d1e9781403 FIX CSS 2026-03-09 09:52:11 +01:00
hansemschnokeloch
e74a333862 Fix migration script (#37436) 2026-03-09 01:07:40 +01:00
Francis Appels
62cf38f227 Fix migration script (#37433) 2026-03-09 00:38:17 +01:00
Vincent Penel
a9db2f6dba Fix ticket categories dictionay (#37434) 2026-03-09 00:37:22 +01:00
Laurent Destailleur
68c8eded6c FIX update COPYRIGHT file to reflect removed libraries 2026-03-07 18:53:20 +01:00
Laurent Destailleur
8688ee5866 FIX option MAIN_USE_TITLE_FOR_USER was on update and not on create 2026-03-07 18:53:09 +01:00
Laurent Destailleur
2cf8e3809f Removed deprecated file 2026-03-07 18:52:32 +01:00
Laurent Destailleur
6b9d5a59d9 FIX Several trouble with demo docker packages. More secured way to use
the force_password in setup process.
2026-03-07 14:52:53 +01:00
Bahfir Abbes
cf11ecd085 Fix:warehouses table name is entrepot which does not hold an fk_soc field, so _checkAccessToResource returns always false and must be disabled before fix. (#25135)
* Fix:warehouses table name is entrepot which does not hold an fk_soc field, so _checkAccessToResource returns always false and must be disabled before fix.

* Fix:warehouses table name is entrepot which does not hold an fk_soc field, so _checkAccessToResource returns always false and must be disabled before fix.

* Fix check params

It is sufficient to fix check parameters to get  it working

* Update api_warehouses.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-06 14:06:40 +01:00
Laurent Destailleur
f4109abe56 css 2026-03-06 11:20:35 +01:00
Laurent Destailleur
baa1359021 FIX Bad value when entering price with multicurrency included tax.
Debug option PRODUCT_USE_CUSTOMER_PACKAGING not completely implemented
2026-03-06 01:21:04 +01:00
Laurent Destailleur
4646cf8417 Automated merge from 22.0 to 23.0 by tool pullmerge.sh 2026-03-06 00:18:41 +01:00
Laurent Destailleur
d165a8a557 Automated merge from 21.0 to 22.0 by tool pullmerge.sh 2026-03-06 00:18:38 +01:00
Laurent Destailleur
c723aec696 Automated merge from 20.0 to 21.0 by tool pullmerge.sh 2026-03-06 00:18:35 +01:00
Laurent Destailleur
f23d590749 Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2026-03-06 00:18:13 +01:00
Laurent Destailleur
a3d5c0b30b Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-03-06 00:12:01 +01:00
Laurent Destailleur
f4278b2c6f Add missing user modif in import 2026-03-06 00:04:06 +01:00
Laurent Destailleur
a7afc55fde CI 2026-03-05 23:57:07 +01:00
Laurent Destailleur
c449bcf9f4 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-03-05 23:55:56 +01:00
Laurent Destailleur
dea8c0cf0e FIX #37412 Better fix 2026-03-05 23:36:54 +01:00
Henry
ba9f70dc92 Fix: Sales order add line shows 0 when only multicurrency unit price is filled (#37412)
When adding a product line to a sales order in multicurrency mode, if the user
fills only the 'UP currency' (multicurrency_price_ht) and not the local unit
price, the line was saved with price 0. The form values for multicurrency
price were never applied to pu_ht_devise, and pu_ht was not derived from
pu_ht_devise using the order rate.

- Set pu_ht_devise from multicurrency_price_ht when user entered it
- When local price is empty/zero, derive pu_ht from pu_ht_devise / multicurrency_tx
  (same convention as core/lib/price.lib.php calcul_price_total)
- Same for multicurrency_price_ttc -> pu_ttc_devise and pu_ttc

Made-with: Cursor
2026-03-05 22:37:29 +01:00
sonikf
015c9859cc fix broken label and its tooltip in Social or fiscal taxes table (#37401)
* fix label tooltip

* fix broken label and tooltip

* Update chargesociales.class.php

* Update index.php
2026-03-05 22:31:39 +01:00
Laurent Destailleur
e3a0d9fda4 Fix socid not forced for external users 2026-03-05 22:25:57 +01:00
Noé Cendrier
9b54dcf4af FIX: read_supplier_price filter for stock complement (#37417)
* FIX: read_supplier_price filter for stock complement

complements #37119

* FIX: use existing vars

* Update movement_list.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-05 22:25:53 +01:00
Charlène Benke
be2957816a Add alternative element type for facturerec (#37418)
fail on extrafields showinputfield link
2026-03-05 22:25:48 +01:00
Frédéric FRANCE
2070883cfd fix "capital" for mysoc (#37414)
* fix "capital" for mysoc

* Update societe.class.php

* Update societe.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-05 22:25:40 +01:00
Laurent Destailleur
14de760244 Fix install script 2026-03-05 22:14:14 +01:00
Anthony Berton
0eb3c9e68d FIX - Reload page after check holiday for save param (#37410)
Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-03-05 13:46:02 +01:00
Laurent Destailleur
35eb6853fd FIX Fetch of lead status 2026-03-05 12:45:25 +01:00
Laurent Destailleur
6ba163880a Fix filter 2026-03-05 12:34:36 +01:00
Eric Seigne
e049222877 github.event_name is pull_request_target not pull_request 2026-03-05 09:55:51 +01:00
lvessiller-opendsi
c428e079e3 Merge pull request #37057 from ATM-Consulting/FIX/docPreviewInCommCard
FIX - Fix doc preview in comm card
2026-03-05 09:52:24 +01:00
Anthony Berton
418f0c2e30 FIX - Added user filtering for displaying leave in the calendar (#37385)
* FIX - Added user filtering for displaying leave in the calendar

* Add restric

* Save param check_holiday

* Copy

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-03-05 01:16:38 +01:00
Laurent Destailleur
500bd9c1f2 FIX height of confirm popup 2026-03-05 00:46:30 +01:00
Laurent Destailleur
7a8e0ace2e Automated merge from 22.0 to 23.0 by tool pullmerge.sh 2026-03-04 19:50:18 +01:00
Laurent Destailleur
3a15740c73 Automated merge from 21.0 to 22.0 by tool pullmerge.sh 2026-03-04 19:50:16 +01:00
Laurent Destailleur
7bb2713bd9 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-03-04 19:49:33 +01:00
Laurent Destailleur
96205a6a09 Fix CSS 2026-03-04 19:46:06 +01:00
Laurent Destailleur
1650d96091 FIX Pb with import of agendaevents. Date and import id not visible. 2026-03-04 16:52:48 +01:00
Laurent Destailleur
a0b7852d65 Fix missing link to list of events 2026-03-04 14:16:40 +01:00
Laurent Destailleur
cf0ab8d300 Fix label of type 2026-03-04 12:51:56 +01:00
Laurent Destailleur
641333e2ce Fix trans 2026-03-04 11:59:32 +01:00
Laurent Destailleur
9c0cdee7c6 Fix css and truncation on creation of event 2026-03-04 11:52:05 +01:00
Laurent Destailleur
6b73193846 Fix delete datapolicy batch. Bad sql 2026-03-04 11:03:17 +01:00
Laurent Destailleur
9940db94d9 Debug v23 2026-03-04 03:04:31 +01:00
Laurent Destailleur
0e566ac49f Fix restore priority as it is the sorted field 2026-03-04 00:47:40 +01:00
Laurent Destailleur
1f09296717 Debug v23 2026-03-03 21:11:57 +01:00
Laurent Destailleur
d072d1fc0a Fix CSS 2026-03-03 21:06:00 +01:00
Laurent Destailleur
17857b271c Fix regression 2026-03-03 20:30:37 +01:00
Laurent Destailleur
fc19612af0 Fix critical perf trouble making IO scan at each image output 2026-03-03 20:15:57 +01:00
Laurent Destailleur
a4e077a0f7 Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2026-03-03 14:24:43 +01:00
Laurent Destailleur
749b45a16d Fix from may be empty 2026-03-03 14:24:04 +01:00
Laurent Destailleur
fffbf75d33 Fix migration 2026-03-03 13:11:03 +01:00
Günter Lukas
293b5a0778 Fix #37388 Change GETPOSTINT to GETPOST for form question (#37390)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-03-02 20:10:33 +01:00
Laurent Destailleur
61c935b827 Debug v23 2026-03-02 20:07:43 +01:00
Laurent Destailleur
5077058df5 Fix CI 2026-03-02 15:23:26 +01:00
Laurent Destailleur
603e1ff877 Fix phan 2026-03-02 14:58:01 +01:00
Laurent Destailleur
eb778141d6 css 2026-03-02 14:09:11 +01:00
Laurent Destailleur
e0e77b203c Fix script 2026-03-02 06:05:45 +01:00
Laurent Destailleur
57a1f05d49 FIX #37372 FIX #37374 2026-03-02 05:52:05 +01:00
Laurent Destailleur
913d732d7f Trans 2026-03-02 05:20:41 +01:00
Laurent Destailleur
0818f97b96 Doc 2026-03-02 04:37:51 +01:00
Laurent Destailleur
9273cbd919 Clean code 2026-03-02 04:26:03 +01:00
Laurent Destailleur
894c4d8f9e FIX #GHSA-crgg-h74r-2m8r 2026-03-02 04:25:53 +01:00
Laurent Destailleur
d928b816d7 Fix #GHSA-q29x-7fmx-7gq3 2026-03-02 03:58:48 +01:00
Laurent Destailleur
29aceee503 Complete fix of MAIN_DISALLOW_UNSECURED_SELECT_INTO_EXTRAFIELDS_FILTER 2026-03-02 03:17:24 +01:00
Laurent Destailleur
7c2e2f4c82 Add a protection against typo error of user. 2026-03-02 02:53:29 +01:00
Laurent Destailleur
115b1e27b0 Try to reduce false postivie of ia scanner 2026-03-02 02:40:06 +01:00
Laurent Destailleur
26c38c52f9 Clean code 2026-03-02 02:15:10 +01:00
Laurent Destailleur
743c22e57c Sec: Fix #GHSA-2mfj-r695-5h9r 2026-03-02 02:04:30 +01:00
Laurent Destailleur
4bfe5d2d4a Protect includes (in case dol_include is used without harcoded filename) 2026-03-02 01:03:34 +01:00
Laurent Destailleur
58852eaa57 Debug v23 2026-03-01 20:01:01 +01:00
Laurent Destailleur
5f99494fed Debug v23 2026-03-01 19:51:08 +01:00
Laurent Destailleur
8976231f35 Fix trans 2026-03-01 19:29:34 +01:00
Laurent Destailleur
1febc39a56 css 2026-03-01 19:19:58 +01:00
Laurent Destailleur
6f2adf3457 Debug v23 2026-03-01 18:52:35 +01:00
Laurent Destailleur
d1a78bf3ac Debug v23 2026-03-01 18:33:28 +01:00
Laurent Destailleur
5756ba2369 css 2026-03-01 18:27:17 +01:00
Laurent Destailleur
6ba0c37ccd css 2026-03-01 18:23:08 +01:00
Laurent Destailleur
3e95f2b456 Automated merge from 22.0 to 23.0 by tool pullmerge.sh 2026-03-01 15:47:51 +01:00
Laurent Destailleur
518f16aea3 Trans 2026-03-01 14:47:27 +01:00
Laurent Destailleur
2e56f40c39 Trans 2026-03-01 14:26:02 +01:00
Laurent Destailleur
91e5b19541 Trans 2026-03-01 14:21:05 +01:00
Laurent Destailleur
5d1c39440d Fix % 2026-03-01 14:13:19 +01:00
Laurent Destailleur
fc13435730 Debug v23 2026-03-01 14:07:41 +01:00
Laurent Destailleur
53ecd7de15 Debug v23 2026-03-01 14:00:16 +01:00
Laurent Destailleur
271af9f8f7 FIX #37171 2026-03-01 12:01:56 +01:00
Laurent Destailleur
ec8898ac50 Add more param 2026-02-28 19:14:00 +01:00
Laurent Destailleur
011eb736b8 Debug v23 2026-02-28 18:47:22 +01:00
Laurent Destailleur
060d7d7a60 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-28 17:46:49 +01:00
Laurent Destailleur
97f1bbc219 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-28 17:42:25 +01:00
Laurent Destailleur
c99e556ba8 FIX #36907 Close #37100 2026-02-28 16:50:41 +01:00
Laurent Destailleur
38590d0357 Fix missing import key 2026-02-28 15:35:42 +01:00
Laurent Destailleur
5aee214f75 Add missing import_id 2026-02-28 15:31:19 +01:00
Laurent Destailleur
6a458223b1 Automated merge from 22.0 by tool pullmerge.sh 2026-02-28 11:31:01 +01:00
Laurent Destailleur
ad90eb7a7c Automated merge from 21.0 by tool pullmerge.sh 2026-02-28 11:28:30 +01:00
Laurent Destailleur
c65c7678b1 Automated merge from 20.0 by tool pullmerge.sh 2026-02-28 11:28:27 +01:00
Laurent Destailleur
dc12867364 Automated merge from 19.0 by tool pullmerge.sh 2026-02-28 11:28:25 +01:00
Laurent Destailleur
a1e255a846 Automated merge from 18.0 by tool pullmerge.sh 2026-02-28 11:28:22 +01:00
Laurent Destailleur
3daff81110 Automated merge from 17.0 by tool pullmerge.sh 2026-02-28 11:27:20 +01:00
Laurent Destailleur
a424b368a0 css 2026-02-28 10:58:30 +01:00
Alexandre SPANGARO
01ac580441 FIX "Undefined array key" warnings in import_csv.modules.php on $this->cacheconvert access (#37349)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-27 17:17:26 +01:00
Anthony Berton
ce02010542 FIX - Show POS in Order and Invoice list (#37364)
* FIX - Show POS in Order and Invoice list

* Update list.php

* Change $showpos value type from int to string

* Refactor POS fields visibility logic

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-27 17:15:41 +01:00
minimexat
4ad18d1219 Fix external user 'Access Forbidden' on agenda event card (#37362)
External users (fk_soc set) were blocked from opening agenda events
because GETPOSTINT('socid') returns 0 when no socid param is in the URL
(ActionComm::getNomUrl() only generates ?id=XXXXX).

The condition 0 != $user->socid then triggers accessforbidden() for
every external user.

Fix: fall back to $user->socid when socid is not in the URL, consistent
with the pattern used in all other card pages (contracts, invoices,
orders, etc.).

The existing restrictedArea() check still validates that the event's
fk_soc matches the user's company, so security is preserved.

Fixes #37361

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-27 16:38:01 +01:00
Regis Houssin
cd4833e6de FIX #37339 (#37340)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-27 16:05:47 +01:00
Anthony Berton
e522839aa0 FIX - Twice the check in resource list column (#37342)
* FIX - Twice the check in resource list column

* Update copyright information in list.php

Added copyright notice for 2026.

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-02-27 16:02:24 +01:00
HENRY Florian
cfb6fa89d9 fix: php 8 warning Array To String (#37371)
* fix: php 8 warning Array To String

* Change logging to use json_encode for parameters

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-27 16:00:54 +01:00
atm-adrien
d0860270ac FIX : Entity on group ticket insertion (#37370) 2026-02-27 15:40:10 +01:00
Milamber
40414d35a3 Fix issue with amount in letters for French (soixante-dix+ and quatre-vingt dix+) (#37369)
Comments in EN
2026-02-27 15:23:01 +01:00
Anthony Berton
c326ab68f0 FIX - If a specific pricing system is applied, the price type is not specified (#37348)
* FIX - If a specific pricing system is applied, the price type is not specified

* Add 2026 copyright for Anthony Berton

Added copyright notice for Anthony Berton for 2026.

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-02-27 14:49:14 +01:00
Laurent Destailleur
023061e370 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-27 14:46:53 +01:00
Alexandre SPANGARO
4349cc83e4 FIX Variant - CSS (#37337) 2026-02-27 14:37:58 +01:00
Frédéric FRANCE
6282af73bf do not keep date_creation when cloning product (#37351) 2026-02-27 14:37:20 +01:00
Lucas Marcouiller
f09e8916c3 Fix bad rounding when spliting discounts (#37354)
* Fix bad rounding when spliting discounts

* fix ci

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-02-27 14:36:28 +01:00
Laurent Destailleur
7acb0e0d4d Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-27 14:36:22 +01:00
Laurent Destailleur
77ba059635 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-02-27 14:35:48 +01:00
Laurent Destailleur
1642d20d46 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-02-27 14:33:58 +01:00
Laurent Destailleur
ec97514bdb Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-02-27 14:33:43 +01:00
Laurent Destailleur
e1dedd638b Disable beautysh. Overload of work with this is 100x higher than the
gain. Disable definitely.
2026-02-27 14:32:47 +01:00
atm-jonathan
82ed704060 FIX duplicate str_replace() (#37355)
* duplcate str_replace()

* update addline and updateline logic TVA NPR
2026-02-27 14:30:06 +01:00
Laurent Destailleur
c2a3ea6f12 Fix regression 2026-02-27 14:29:35 +01:00
atm-lucas
2b0696080c Verif odt template extension (#37366) 2026-02-27 14:24:52 +01:00
Laurent Destailleur
ec2f4146c3 FIX Doc and log 2026-02-27 13:51:45 +01:00
Laurent Destailleur
15dac27fac Sync transifex 2026-02-26 16:31:57 +01:00
Laurent Destailleur
3c0c7af552 Debug v23 - Update of price in proposals 2026-02-26 15:47:15 +01:00
Laurent Destailleur
5879acbedf Fix label of button 2026-02-26 14:45:34 +01:00
ATM-Lucas
c5b4d149b5 delete more & 2026-02-26 14:11:00 +01:00
Laurent Destailleur
0b920df95a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-26 11:55:45 +01:00
Laurent Destailleur
57451d9970 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-26 11:51:50 +01:00
Laurent Destailleur
486f5ad65e FIX #37350 2026-02-26 11:51:19 +01:00
Alexandre SPANGARO
c1dcded268 FIX Warning - Remove two declaration of DOL_VERSION (#37350) 2026-02-26 11:49:37 +01:00
ATM-Lucas
ba8ab407fe delete & 2026-02-26 10:10:09 +01:00
Laurent Destailleur
8540a02561 Fix data saved with generic oauth 2026-02-25 22:50:39 +01:00
Laurent Destailleur
5fdf0f8094 Fix error management in oauth handlers 2026-02-25 21:49:13 +01:00
Laurent Destailleur
9459d72590 Fix packaging 2026-02-25 19:16:10 +01:00
Laurent Destailleur
b93a2cbf04 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-25 19:07:38 +01:00
Laurent Destailleur
82af80d411 Prepare 23.0.0 2026-02-25 19:07:24 +01:00
Alexandre SPANGARO
f85c6d6495 FIX #37323 Accountancy closure page - Problem with GETPOSTINT cannot read checkbox values properly (#37325) 2026-02-24 17:49:26 +01:00
ATM-NicolasV
11e25b25fb New/add support microsoft exchange oauth (#37329)
* backport de la liste des ressources v23

* fix oauth api conexion

* fix oauth api conexion

* fix oauth api conexion

* Fix CI

* fix: in some case on create invoice when create PDF the lang is not correcly defined because ->thirdparty is not set (#37287)

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* add microsoft exchange oauth

* add microsoft exchange oauth

* add microsoft exchange oauth

* add microsoft exchange oauth

* add microsoft exchange oauth

* Revert unintended changes to resource list

* Tidy OAuth logging and consent prompt

* Fix PHPCS blank line warnings

---------

Co-authored-by: ATM-Lucas <lucas.mantegari@atm-consulting.fr>
Co-authored-by: VIAL-GOUTEYRON Quentin <quentin.vial-gouteyron@atm-consulting.fr>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: HENRY Florian <florian.henry@open-concept.pro>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-24 17:48:29 +01:00
HENRY Florian
125caf1d4b fix: filter on shipping list on mass action (#37281)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 20:06:13 +01:00
Laurent Destailleur
7b2761790f Debug v23 2026-02-23 19:49:45 +01:00
Laurent Destailleur
0a5b75582a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-23 02:19:47 +01:00
Laurent Destailleur
65490c00c9 CI 2026-02-23 02:19:30 +01:00
HENRY Florian
d6f4bf8f03 fix: in some case on create invoice when create PDF the lang is not correcly defined because ->thirdparty is not set (#37287)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 02:10:32 +01:00
Alexandre SPANGARO
a9aea129e7 Warning in emailing module with partnership module (#37270) 2026-02-23 01:42:16 +01:00
Laurent Destailleur
16b2735ca4 Fix CI 2026-02-23 01:33:35 +01:00
ATM-Lucas
eaee0a952d Fix doc preview in comm card 2026-02-02 12:05:11 +01:00
2206 changed files with 39737 additions and 78133 deletions

View File

@@ -18,8 +18,6 @@ insert_final_newline = true
indent_style = tab
[*.css]
indent_style = tab
[*.sh]
indent_style = tab
[*.xml]
indent_style = tab
[*.md]

View File

@@ -8,13 +8,12 @@ jobs:
secrets: inherit
with:
gh_event: ${{ github.event_name }}
phan:
# if: false # Uncommenting this line disables phan
uses: ./.github/workflows/phan.yml
secrets: inherit
needs: [pre-commit]
with:
gh_event: ${{ github.event_name }}
#phan:
# uses: ./.github/workflows/phan.yml
# secrets: inherit
# needs: [pre-commit]
# with:
# gh_event: ${{ github.event_name }}
phpstan:
uses: ./.github/workflows/phpstan.yml
secrets: inherit

View File

@@ -8,12 +8,12 @@ jobs:
secrets: inherit
with:
gh_event: ${{ github.event_name }}
phan:
uses: ./.github/workflows/phan.yml
secrets: inherit
needs: [pre-commit]
with:
gh_event: ${{ github.event_name }}
#phan:
# uses: ./.github/workflows/phan.yml
# secrets: inherit
# needs: [pre-commit]
# with:
# gh_event: ${{ github.event_name }}
phpstan:
uses: ./.github/workflows/phpstan.yml
secrets: inherit

View File

@@ -49,50 +49,17 @@ jobs:
with:
php-version: 8.2
coverage: none # disable xdebug, pcov
tools: cs2pr,phan:5.5.2
tools: phan:5.5.2
- name: Run Phan analysis
# Proceed when:
# - the action is not cancelled
# AND
# - the branch is an integration branch (no merge), or,
# - the merge from branch contains 'phan_full', or,
# - there are changes in PHP files.
# Note: --output-mode=github does not provide file:line, so using checkstyle and cs2pr
if: ${{ ! cancelled() && (github.ref_name == 'develop' || github.ref_name == 'refs/heads/develop' || endsWith(github.ref_name, '.0') || contains(github.head_ref, 'phan_full') || steps.changed-php.outputs.any_changed == 'true') }}
if: "! cancelled() && steps.changed-php.outputs.any_changed == 'true'"
env:
ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }}
# shellcheck disable=2086
FILE_CHANGED_LIST: /tmp/phan-changed.lst
run: |
# shellcheck disable=2086
if [ "${{ github.ref_name }}" == "develop" ] || [[ "${{ github.ref_name }}" == *.0 ]]|| [[ "${{ github.head_ref }}" == *"phan_full"* ]] ; then
echo phan $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=checkstyle -o _phan.xml
phan $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=checkstyle -o _phan.xml
else
echo -n "" > "$FILE_CHANGED_LIST"
for f in $ALL_CHANGED_FILES; do echo "$f" >> "$FILE_CHANGED_LIST"; done
# Must exclude same files as in phan configuration
grep -v -E '^htdocs/(custom/|.*/canvas/.*/tpl/.*.tpl.php|admin/tools/ui/|includes/(nusoap/|restler/|stripe/)|conf/conf.php)$' "$FILE_CHANGED_LIST"> "$FILE_CHANGED_LIST".tmp || true
mv "$FILE_CHANGED_LIST".tmp "$FILE_CHANGED_LIST"
if [ ! -s "$FILE_CHANGED_LIST" ] ; then
echo "All changed files are excluded for phan"
else
echo phan --file-list "$FILE_CHANGED_LIST" $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=checkstyle -o _phan.xml
phan --file-list "$FILE_CHANGED_LIST" $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=checkstyle -o _phan.xml
fi
fi
- name: Add results to PR as Github notices
if: ${{ always() }}
run: |
cs2pr --prepend-filename --prepend-source --notices-as-warnings _phan.xml
- name: Provide phan log as artifact
uses: actions/upload-artifact@v6
if: ${{ always() }}
with:
name: phan-srcrt
path: ${{ github.workspace }}/_phan.xml
retention-days: 2
> /tmp/phpstan-files.txt
for f in $ALL_CHANGED_FILES; do echo "$f" >> /tmp/phan-files.txt; done
cat /tmp/phan-files.txt
echo phan --file-list /tmp/phan-files.txt $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=github
phan --file-list /tmp/phan-files.txt $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=github

View File

@@ -89,28 +89,16 @@ jobs:
# Run PHPStan
- name: Run PHPStan
id: phpstan
# Proceed when:
# - the action is not cancelled
# AND
# - the branch is an integration branch (no merge), or,
# - the merge from branch contains 'phpstan_full', or,
# - there are changes in PHP files.
if: ${{ ! cancelled() && (github.ref_name == 'develop' || github.ref_name == 'refs/heads/develop' || endsWith(github.ref_name, '.0') || contains(github.head_ref, 'phpstan_full') || steps.changed-php.outputs.any_changed == 'true') }}
if: "! cancelled() && steps.changed-php.outputs.any_changed == 'true'"
env:
ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }}
# shellcheck disable=2086
run: |
# shellcheck disable=2086
> /tmp/phpstan-files.txt
if [ "${{ github.ref_name }}" == "develop" ] || [[ "${{ github.ref_name }}" == *.0 ]]|| [[ "${{ github.head_ref }}" == *"phpstan_full"* ]] ; then
# Run on all files in integration branch
phpstan -vvv analyse --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php | tee _stan.xml | cs2pr --graceful-warnings
else
echo "$ALL_CHANGED_FILES" >> /tmp/phpstan-files.txt
cat /tmp/phpstan-files.txt
phpstan -vvv analyse --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php ${ALL_CHANGED_FILES} | tee _stan.xml | cs2pr --graceful-warnings
fi
echo "$ALL_CHANGED_FILES" >> /tmp/phpstan-files.txt
cat /tmp/phpstan-files.txt
phpstan -vvv analyse --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php ${ALL_CHANGED_FILES} | tee _stan.xml | cs2pr --graceful-warnings
# continue-on-error: true
# Save cache

View File

@@ -1,5 +1,5 @@
---
exclude: (?x)^( htdocs/includes/ckeditor/.*|htdocs/public/includes/ckeditor/.*|htdocs/public/includes/jquery/.*|(\.(?!github/workflows)[^/]*/.*))$
exclude: (?x)^( htdocs/includes/ckeditor/.*|htdocs/public/includes/ckeditor/.*|(\.(?!github/workflows)[^/]*/.*))$
repos:
# Several miscellaneous checks and fix (on yaml files, end of files fix)
- repo: https://github.com/pre-commit/pre-commit-hooks
@@ -60,26 +60,23 @@ repos:
# Gitleaks is a SAST tool for detecting and preventing hardcoded secrets like passwords, api keys, and tokens in git repos
- repo: https://github.com/gitleaks/gitleaks.git
rev: v8.30.0
rev: v8.29.0
hooks:
- id: gitleaks
# Check github actions
- repo: https://github.com/rhysd/actionlint
rev: v1.7.11
hooks:
- id: actionlint
stages: [manual] # To run: pre-commit run -a --hook-stage=manual actionlint
#- repo: https://github.com/rhysd/actionlint
# rev: v1.7.8
# hooks:
# - id: actionlint
# Beautify shell scripts
#- repo: https://github.com/lovesegfault/beautysh.git
# rev: v6.4.2
# rev: v6.2.1
# hooks:
# - id: beautysh
# exclude: |
# (?x)^(dev/setup/git/hooks/pre-commit
# |dev/initdemo/initdemo.sh # indent/outdent mismatch
# |dev/build/debian/dolibarr.postrm # indent/outdent mismatch
# )$
# args: [--tab]
@@ -196,7 +193,7 @@ repos:
# Check format of yaml files
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.38.0
rev: v1.37.1
hooks:
- id: yamllint
args:
@@ -248,16 +245,15 @@ repos:
- ned
# Check some shell scripts
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
- id: shellcheck
stages: [manual] # To run: `pre-commit run -a --hook-stage=manual shellcheck`
args: [-W, "100"]
#- repo: https://github.com/shellcheck-py/shellcheck-py
# rev: v0.11.0.1
# hooks:
# - id: shellcheck
# args: [-W, "100"]
# Check sql file syntax
- repo: https://github.com/sqlfluff/sqlfluff
rev: 4.0.4
rev: 3.3.1
hooks:
- id: sqlfluff-lint
stages: [pre-commit, manual] # manual needed for ci
@@ -296,4 +292,4 @@ repos:
# # virtualmin excluded - reason https://github.com/Dolibarr/dolibarr/pull/36370#issuecomment-3565101823
# exclude: (?x)^
# (dev/build/perl/virtualmin/dolibarr.pl
# across all file typese )$
# )$

View File

@@ -531,9 +531,6 @@ script:
php upgrade.php 22.0.0 23.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade22002300.log || cat $TRAVIS_BUILD_DIR/upgrade22002300.log
php upgrade2.php 22.0.0 23.0.0 > $TRAVIS_BUILD_DIR/upgrade22002300-2.log || cat $TRAVIS_BUILD_DIR/upgrade22002300-2.log
php step5.php 22.0.0 23.0.0 > $TRAVIS_BUILD_DIR/upgrade22002300-3.log || cat $TRAVIS_BUILD_DIR/upgrade22002300-3.log
php upgrade.php 23.0.0 24.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade23002400.log || cat $TRAVIS_BUILD_DIR/upgrade23002400.log
php upgrade2.php 23.0.0 24.0.0 > $TRAVIS_BUILD_DIR/upgrade23002400-2.log || cat $TRAVIS_BUILD_DIR/upgrade23002400-2.log
php step5.php 23.0.0 24.0.0 > $TRAVIS_BUILD_DIR/upgrade23002400-3.log || cat $TRAVIS_BUILD_DIR/upgrade23002400-3.log
set +e
echo
@@ -574,8 +571,6 @@ script:
# Execute phpunit, check its exit status and that the phpunit output shows a test summary
phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php | tee /dev/tty | grep -qE "(OK .*[0-9]+ tests.*[0-9]+ assertions|Tests: [0-9]+)" ; phpunitresult=$((PIPESTATUS[0]?PIPESTATUS[0]:PIPESTATUS[2]))
echo "Phpunit return code = $phpunitresult"
echo "Content of end of apache error.log"
sudo tail -n 200 /var/log/apache2/travis_error_log
# Comment next line if you want to go to the end to see the dolibarr.log file.
[ $phpunitresult == 0 ] || exit $phpunitresult
echo

View File

@@ -12,11 +12,16 @@ These dependencies are listed in the bottom of this file.
The Dolibarr images resources (available in the doc directory) is distributed under the Creative Commons Attribution 4.0 International license (CC BY 4.0).
Trademark usage
---------------
The name Dolibarr is a trademark initially registered by Laurent Destailleur and ceased to the Dolibarr foundation. You can use the name Dolibarr
for your own need as long as you follow the rules defined on the page https://wiki.dolibarr.org/index.php/Rules_to_use_the_brand_name_%22Dolibarr%22
The use of the name DoliStore is also restricted to the same rules defined on https://wiki.dolibarr.org/index.php/Rules_to_use_the_brand_name_%22Dolibarr%22
License of third party libraries
--------------------------------
Licence of dependencies of third-party components used by Dolibarr (all compatible with the Licence of Dolibarr):
@@ -39,7 +44,6 @@ PHP-Iban 4.1.1 LGPL-3+ Yes
PHP-Imap 2.7.2 MIT License Yes Library to use IMAP with OAuth
PHPoAuthLib 0.8.2 MIT License Yes Library to provide oauth1 and oauth2 to different service
PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests
PrestaShop-WS-Lib 94feb5f OSL-3.0 No Library providing API client for Prestashop.
PSR/Logs 1.0 MIT License Yes Library for logs (used by DebugBar)
PSR/simple-cache ? MIT License Yes Library for cache (used by PHPSpreadSheet)
Restler 3.1.1 LGPL-3+ Yes Library to develop REST Web services (+ swagger-ui js lib into dir explorer)
@@ -67,13 +71,9 @@ jQuery jPicker 1.1.6 GPL and MIT License Yes
jQuery jqueryFileTree 1.0.1 GPL and MIT License Yes JS library for filetree
jQuery jquerytreeview 1.4.1 MIT License Yes JS library for filetree
jQuery TableDnD 0.6 GPL and MIT License Yes JS library plugin TableDnD (to reorder table rows)
jQuery Timepicker 1.1.0 GPL and MIT License Yes JS library Timepicker addon for Datepicker
jsGanttImproved 2.8.10 BSD License Yes JS library (to build Gantt reports)
SwaggerUI 2.2.10 GPL-2+ Yes JS library to offer the REST API explorer
Image libraries:
Octicons 8.1 MIT Yes
Font libraries:
Fontawesome 5.13 Font Awesome Free Licence Yes

View File

@@ -2,6 +2,28 @@
English Dolibarr ChangeLog
--------------------------------------------------------------
***** ChangeLog for 23.0.1 compared to 23.0.0 *****
FIX: Removed SQL error on install process.
FIX: #37412 Better fix
FIX: Added user filtering for displaying leave in the calendar (#37385)
FIX: Bad value when entering price with multicurrency included tax.
FIX: Better compatibility for module using condition object-> in tabs
FIX: CSS
FIX: Fetch of lead status
FIX: Fix doc preview in comm card
FIX: height of confirm popup
FIX: option MAIN_USE_TITLE_FOR_USER was on update and not on create
FIX: Order API: delete order returns wrong http response in case order could not be deleted (#37472)
FIX: Pb with import of agendaevents. Date and import id not visible.
FIX: read_supplier_price filter for stock complement (#37417)
FIX: Reload page after check holiday for save param (#37410)
FIX: Several trouble with demo docker packages. More secured way to use install.force.php file
FIX: translation on multiselect with rich label - Fix CSS public ticket
FIX: update COPYRIGHT file to reflect removed libraries in v23.0.0
***** ChangeLog for 23.0.0 compared to 22.0 *****
For users:
@@ -205,7 +227,7 @@ The following changes may create regressions for some external modules, but were
* Because of the new TRIGGER_PREFIX property, the triggers SUPPLIER_PRODUCT_BUYPRICE_XXX are renamed into PRODUCT_BUYPRICE_XXX.
* Function img_pdf() has been removed. Replace it with img_picto('', 'pdf') if you were using it.
* The method run_trigger() was deprecated 10+ years ago in favor of runTrigger(). It has been removed. Change your trigger file if you still use it.
* Property ->picto of module descriptors must contains the image extension if it is not a font awesome tag. Example: $this->picto="mymoduleimg.png";
* Property ->picto of module descriptors or menu entries must contains the image extension if it is not a font awesome tag. Example: $this->picto="mymoduleimg.png";
* Stock movement API GET method output variable names has been harmonized with POST input parameter names
* Concatenation into computed property of extrafields is off by default. You can enable it from conf.php file by adding dol_concat to list of allowed function in $dolibarr_main_restrict_eval_methods,
For example: $dolibarr_main_restrict_eval_methods='getDolGlobalString,getDolGlobalInt,getDolCurrency,fetchNoCompute,hasRight,isModEnabled,isStringVarMatching,abs,min,max,round,dol_now,dol_concat,preg_match';

View File

@@ -299,12 +299,12 @@ If script fails with error Bad certificate, you can set "export PERL_LWP_SSL_VER
* Edit orig.tar.gz file to remove
- debian
- htdocs/public/includes/ckeditor
- htdocs/public/includes/jquery/css
- htdocs/public/includes/jquery/js
- htdocs/public/includes/jquery/plugins/flot
- htdocs/public/includes/jquery/plugins/multiselect
- htdocs/public/includes/jquery/plugins/datatables
- htdocs/includes/ckeditor
- htdocs/includes/jquery/css
- htdocs/includes/jquery/js
- htdocs/includes/jquery/plugins/flot
- htdocs/includes/jquery/plugins/multiselect
- htdocs/includes/jquery/plugins/datatables
- htdocs/includes/jszip
- htdocs/includes/mike42
- htdocs/includes/phpoffice

View File

@@ -61,7 +61,7 @@ License: GPL-3+
------------------------------------------------------------
Files: htdocs/public/includes/ckeditor/*
Files: htdocs/includes/ckeditor/*
Copyright: 2003-2012 CKSource - Frederico Knabben
License: GPL-2+
The ckeditor is triple licensed under the GNU General Public License (GPL),
@@ -190,7 +190,7 @@ License: CC-By-SA
------------------------------------------------------------
Files: htdocs/public/includes/jquery/*
Files: htdocs/includes/jquery/*
Copyright: JQuery team
https://www.jquery.com
License: GPL-2+ or MIT

View File

@@ -97,9 +97,10 @@ override_dh_install:
# rm -fr htdocs/includes/nusoap
# rm -fr htdocs/includes/odtphp/zip/pclzip
# clean from all JS-CSS embedded libraries (we use package dependencies instead)
# rm -fr htdocs/public/includes/ckeditor
# rm -fr htdocs/public/includes/jquery/js
# rm -fr htdocs/public/includes/jquery/css
# rm -fr htdocs/includes/ckeditor
# rm -fr htdocs/includes/jquery/js
# rm -fr htdocs/includes/jquery/css
# rm -fr htdocs/includes/jquery/plugins/flot
# clean from all embedded fonts (we use package dependencies instead)
# rm -fr htdocs/includes/fonts

View File

@@ -1,9 +1,16 @@
# Remove warning, we want to keep both standard and minified sources.
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jquery/*
dolibarr: source-contains-prebuilt-javascript-object htdocs/public/includes/jquery/*
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jsgantt/*
dolibarr: source-contains-prebuilt-javascript-object htdocs/includes/jstz/*
# Those are false positives, the files are their own sources since
# they are not minified
source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/a11yhelp/dialogs/lang/*.js
source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/specialchar/dialogs/lang/*.js
source-is-missing htdocs/includes/ckeditor/ckeditor/lang/*.js
source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/*/dialogs/*.js
source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/*/filter/*.js
source-is-missing htdocs/includes/ckeditor/ckeditor/plugins/templates/templates/default.js
source-is-missing htdocs/public/includes/ckeditor/ckeditor/plugins/a11yhelp/dialogs/lang/*.js
source-is-missing htdocs/public/includes/ckeditor/ckeditor/plugins/specialchar/dialogs/lang/*.js
source-is-missing htdocs/public/includes/ckeditor/ckeditor/lang/*.js

View File

@@ -3,19 +3,30 @@
# See README.md to know how to create a Dolibarr env with docker
set -ex
if [ "${PHP_INI_DIR}" == "" ]; then
echo
echo This script must not be run directly. It is used by the Dockerfile
echo See README.md
echo
exit
fi
if [ "${HOST_USER_ID}" == "" ]; then
echo "Define HOST_USER_ID to your user ID before starting"
echo "Define HOST_USER_ID to your user ID before starting (example: www-data)"
exit 1
fi
if [ "${HOST_GROUP_ID}" == "" ]; then
echo "Define HOST_GROUP_ID to your group ID before starting (example: www-data)"
exit 1
fi
usermod -u "${HOST_USER_ID}" www-data
groupmod -g "${HOST_USER_ID}" www-data
groupmod -g "${HOST_GROUP_ID}" www-data
echo "[docker-run] => update '${PHP_INI_DIR}/conf.d/dolibarr-php.ini'"
cat <<EOF > "${PHP_INI_DIR}/conf.d/dolibarr-php.ini"
date.timezone = ${PHP_INI_DATE_TIMEZONE:-UTC}
memory_limit = ${PHP_INI_MEMORY_LIMIT:-256M}
display_errors = Off
EOF
exec apache2-foreground

View File

@@ -1,24 +1,51 @@
# How to use or run Dolibarr with Docker ?
# How to build and run your local version of Dolibarr, quickly with Docker ?
## For a fast run of a demo of the local version, you can build the docker image from the source repository by running
## For a fast run of a demo of the local version, you can build a docker image pointing to your source repository
This process using the Dockerfile and docker-compose.yml file is a config file to use to build and run Dolibarr in the
current workspace with Docker. This docker image is intended for **development usage** (See next chapter for a production usage).
Warning: There is no persistency of database. This process is for dev purpose only.
Build the containers:
git clone https://github.com/Dolibarr/dolibarr.git dolibarr
cd dolibarr/docker
cd dolibarr/dev/build/docker
sudo docker-compose build
sudo docker-compose build [--no-cache]
or
sudo docker compose build [--no-cache]
Launch the containers:
sudo -s
export HOST_USER_ID=$(id -u)
export HOST_GROUP_ID=$(id -g)
export MYSQL_ROOT_PWD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
docker-compose up -d
or
docker compose up -d
Check that server process is on:
docker compose ps
Warning: There is no persistency of data. This process is for dev purpose only.
Check also logs of starting container:
docker logs dolibarr-web-dev
The URL to go to the installed Dolibarr is :
http://0.0.0.0:8080
To delete processes:
docker compose kill stop
## For a more robust or a production usage

View File

@@ -1,28 +1,27 @@
version: "3"
services:
mariadb-prod:
container_name: dolibarr-mariadb-prod
mariadb-dev:
container_name: dolibarr-mariadb-dev
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PWD
MYSQL_DATABASE: "dolibarr-prod"
MARIADB_ROOT_PASSWORD: $MYSQL_ROOT_PWD
MARIADB_DATABASE: "dolibarr-dev"
web:
container_name: dolibarr-web-prod
container_name: dolibarr-web-dev
build: .
volumes:
- ../../htdocs:/var/www/html/
- ../../documents:/var/www/html/documents
- ../../../htdocs:/var/www/html/
- ../../../documents:/var/www/documents
depends_on:
- mariadb-prod
- mariadb-dev
environment:
HOST_USER_ID: $HOST_USER_ID
HOST_GROUP_ID: $HOST_GROUP_ID
DOLI_ROOT_PASSWORD: $MYSQL_ROOT_PWD
DOLI_DATABASE: "dolibarr-prod"
DOLI_DB_SERVER: "mariadb-prod"
DOLI_DATABASE: "dolibarr-dev"
DOLI_DB_SERVER: "mariadb-dev"
DOLI_DB_USER: "root"
DOLI_DB_PASSWORD: $MYSQL_ROOT_PWD
ports:
- "8080:80"

View File

@@ -10,6 +10,16 @@ if [ "${PHP_INI_DIR}" == "" ]; then
exit
fi
if [ "${HOST_USER_ID}" == "" ]; then
echo "Define HOST_USER_ID to your user ID before starting (example: www-data)"
exit 1
fi
if [ "${HOST_GROUP_ID}" == "" ]; then
echo "Define HOST_GROUP_ID to your group ID before starting (example: www-data)"
exit 1
fi
usermod -u "${HOST_USER_ID}" www-data
groupmod -g "${HOST_GROUP_ID}" www-data
@@ -29,6 +39,7 @@ date.timezone = ${PHP_INI_DATE_TIMEZONE:-UTC}
memory_limit = ${PHP_INI_MEMORY_LIMIT:-256M}
EOF
cp /var/www/html/install/install.forced.docker.php /var/www/html/install/install.forced.php
echo cp /var/www/html/install/install.forced.sample.php /var/www/html/install/install.forced.php
cp /var/www/html/install/install.forced.sample.php /var/www/html/install/install.forced.php
exec apache2-foreground

View File

@@ -44,7 +44,6 @@ define('DOL_DOCUMENT_ROOT', dirname(dirname($path)).'/htdocs');
$algo = 'sha256';
require_once $path."../../htdocs/master.inc.php";
require_once DOL_DOCUMENT_ROOT."/blockedlog/versionmod.inc.php";
require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
@@ -129,10 +128,7 @@ if ($tmpver[0] == 'auto') {
$release .= '-'.$tmpver[1];
}
}
$releaseblockedlog = DOLCERT_VERSION;
// If release is auto, we take current version to read checklock file
// If release is auto, we take current version
$tmpver = explode('-', $checklock, 2);
if ($tmpver[0] == 'auto') {
$checklock = DOL_VERSION;
@@ -187,7 +183,6 @@ if ($checklock && empty($checksource)) {
if ($release) {
print "Working on files into : ".DOL_DOCUMENT_ROOT."\n";
print "Version of target release : ".$release."\n";
print "Version of blockedlog module : ".$releaseblockedlog."\n";
print "Algo : ".$algo."\n";
print "Include custom dir in signature : ".(empty($includecustom) ? 'no' : 'yes')."\n";
print "Include constants in signature : ".(empty($includeconstants) ? 'none' : '');
@@ -343,13 +338,13 @@ if ($release) {
$checksumconcat = array();
if ($release && $releaseblockedlog) {
fputs($fp, '<dolibarr_unalterable_files version="'.$releaseblockedlog.'">'."\n");
if ($release) {
fputs($fp, '<dolibarr_unalterable_files version="'.$release.'">'."\n");
}
// Array of dir/files to include in the section
$arrayofunalterablefiles = array(
//array('dir' => dirname(__FILE__).'/../../htdocs/', 'file' => 'version.inc.php'),
array('dir' => dirname(__FILE__).'/../../htdocs/', 'file' => 'version.inc.php'),
array('dir' => dirname(__FILE__).'/../../htdocs/blockedlog', 'file' => 'all', 'regextoinclude' => '(\.php|\.sql)$', 'regextoexclude' => ''),
array('dir' => dirname(__FILE__).'/../../htdocs/install/mysql/tables', 'file' => 'all', 'regextoinclude' => 'llx_blockedlog.*(\.php|\.sql)$', 'regextoexclude' => ''),
array('dir' => dirname(__FILE__).'/../../htdocs/core/triggers', 'file' => 'interface_50_modBlockedlog_ActionsBlockedLog.class.php'),
@@ -433,7 +428,6 @@ foreach ($arrayofunalterablefiles as $entry) {
}
asort($checksumconcat); // Sort list of checksum
$hashunalterable_files = hash($algo, join(',', $checksumconcat));
if ($release) {

View File

@@ -60,9 +60,19 @@ my %ALTERNATEPATH = (
);
my $RPMSUBVERSION = "auto"; # auto use value found into BUILD
my $RPMDIR = "$ENV{HOME}/rpmbuild"; # by default
if ( -d "/usr/src/redhat" ) { $RPMDIR = "/usr/src/redhat"; } # redhat
if ( -d "/usr/src/packages" ) { $RPMDIR = "/usr/src/packages"; } # opensuse
if ( -d "/usr/src/RPM" ) { $RPMDIR = "/usr/src/RPM"; } # mandrake
if ( ! -d "$RPMDIR/SOURCES" ) {
mkdir("$RPMDIR/SOURCES");
if ( ! -d "$RPMDIR/SOURCES" ) {
print "Failed to create dir $RPMDIR/SOURCES\n";
sleep 2;
exit 1;
}
}
use vars qw/ $REVISION $VERSION /;
my $VERSION = "4.0";
@@ -203,10 +213,10 @@ while (<$IN>) {
}
}
close $IN;
open( my $IN2, "<", $SOURCE . "/htdocs/filefunc.inc.php" )
open( my $IN2, "<", $SOURCE . "/htdocs/version.inc.php" )
or die "Error: Can't open version file "
. $SOURCE
. "/htdocs/filefunc.inc.php\n";
. "/htdocs/version.inc.php\n";
while (<$IN2>) {
if ( $_ =~ /define\('DOL_MINOR_VERSION',\s*'([\d\.a-z\-]+)'\)/ ) {
$MINORVERSION = $1;
@@ -625,10 +635,8 @@ if ($nboftargetok) {
. $BUILD . '"' . "\n";
$ret =
`git tag -a -f -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD"`;
print 'Run git push '
. $GITREMOTENAME
. ' -f "$MAJOR.$MINOR.$BUILD"' . "\n";
$ret = `git push $GITREMOTENAME -f -"$MAJOR.$MINOR.$BUILD"`;
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"`;
}
@@ -816,19 +824,19 @@ if ($nboftargetok) {
$ret = `rm -f $BUILDROOT/$PROJECT/htdocs/includes/geoip/sample*.*`;
$ret = `rm -f $BUILDROOT/$PROJECT/htdocs/includes/bin`;
$ret =
`rm -fr $BUILDROOT/$PROJECT/htdocs/public/includes/ckeditor/ckeditor/adapters`
`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/ckeditor/adapters`
; # Keep this removal in case we embed libraries
$ret =
`rm -fr $BUILDROOT/$PROJECT/htdocs/public/includes/ckeditor/ckeditor/samples`
`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/ckeditor/samples`
; # Keep this removal in case we embed libraries
$ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/public/includes/ckeditor/_source`
$ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/_source`
; # _source must be kept into tarball for official debian, not for the rest
$ret = `rm -f $BUILDROOT/$PROJECT/htdocs/includes/composer`;
$ret = `rm -f $BUILDROOT/$PROJECT/htdocs/includes/doctrine`;
$ret =
`rm -f $BUILDROOT/$PROJECT/htdocs/public/includes/jquery/plugins/multiselect/MIT-LICENSE.txt`;
`rm -f $BUILDROOT/$PROJECT/htdocs/includes/jquery/plugins/multiselect/MIT-LICENSE.txt`;
$ret =
`rm -f $BUILDROOT/$PROJECT/htdocs/public/includes/jquery/plugins/select2/release.sh`;
`rm -f $BUILDROOT/$PROJECT/htdocs/includes/jquery/plugins/select2/release.sh`;
$ret =
`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/doc`;
$ret =
@@ -934,7 +942,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMETGZ/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMETGZ/htdocs/public/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMETGZ/htdocs/includes/ckeditor/_source`
; # We can't remove it with exclude file, we need it for some tarball packages
print "Compress $FILENAMETGZ into $FILENAMETGZ.tgz...\n";
@@ -971,7 +979,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMEXZ/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMEXZ/htdocs/public/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMEXZ/htdocs/includes/ckeditor/_source`
; # We can't remove it with exclude file, we need it for some tarball packages
print "Compress $FILENAMEXZ into $FILENAMEXZ.xz...\n";
@@ -1010,7 +1018,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMEZIP/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMEZIP/htdocs/public/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMEZIP/htdocs/includes/ckeditor/_source`
; # We can't remove it with exclude file, we need it for some tarball packages
print "Compress $FILENAMEZIP into $FILENAMEZIP.zip...\n";
@@ -1062,7 +1070,7 @@ if ($nboftargetok) {
$ret = `$cmd`;
# Removed files we don't need (already removed before)
#$ret=`rm -fr $BUILDROOT/$FILENAMETGZ2/htdocs/public/includes/ckeditor/_source`;
#$ret=`rm -fr $BUILDROOT/$FILENAMETGZ2/htdocs/includes/ckeditor/_source`;
print "Set permissions on files/dir\n";
$ret = `chmod -R 755 $BUILDROOT/$FILENAMETGZ2`;
@@ -1261,17 +1269,17 @@ if ($nboftargetok) {
# Removed duplicate license files
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/plugins/scayt/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/plugins/scayt/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/plugins/wsc/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/plugins/wsc/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/plugins/scayt/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/plugins/scayt/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/plugins/wsc/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/plugins/wsc/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/php-iban/LICENSE`;
$ret =
@@ -1294,7 +1302,7 @@ if ($nboftargetok) {
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/mobiledetect/mobiledetectlib/LICENSE.txt`;
# Removed files we don't need (already removed)
#$ret=`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source`;
#$ret=`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source`;
$ret = `rm -fr $BUILDROOT/$PROJECT.tmp/.codeclimate.yml`;
$ret = `rm -fr $BUILDROOT/$PROJECT.tmp/.pre-commit-config.yaml`;
$ret = `rm -fr $BUILDROOT/$PROJECT.tmp/.vscode`;
@@ -1378,41 +1386,61 @@ if ($nboftargetok) {
print "Set permissions on files/dir\n";
$ret = `chmod -R 755 $BUILDROOT/$PROJECT.tmp`;
$cmd = "find $BUILDROOT/$PROJECT.tmp -type f -exec chmod 644 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp -type f -exec chmod 644 {} \\; ";
$ret = `$cmd`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.php' -type f -exec chmod 755 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.php' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.dpatch' -type f -exec chmod 755 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.dpatch' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.pl' -type f -exec chmod 755 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp/dev/build -name '*.pl' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/dev -name '*.php' -type f -exec chmod 755 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp/dev -name '*.php' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
$ret = `chmod 755 $BUILDROOT/$PROJECT.tmp/debian/rules`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/dev/translation/autotranslator.class.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/actions_mymodule.class.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/api_mymodule.class.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/myobject.class.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/core/modules/modMyModule.class.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/mymoduleindex.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_card.php`;
$ret = `chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_list.php`;
$ret = `chmod -R 755 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/scripts/mymodule.php`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/scripts -name '*.php' -type f -exec chmod 755 {} \\; ";
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/dev/translation/autotranslator.class.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/actions_mymodule.class.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/api_mymodule.class.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/myobject.class.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/core/modules/modMyModule.class.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/mymoduleindex.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_card.php`;
$ret =
`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_list.php`;
$ret =
`chmod -R 755 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/scripts/mymodule.php`;
$cmd =
"find $BUILDROOT/$PROJECT.tmp/scripts -name '*.php' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
$cmd = "find $BUILDROOT/$PROJECT.tmp/scripts -name '*.sh' -type f -exec chmod 755 {} \\; ";
$cmd =
"find $BUILDROOT/$PROJECT.tmp/scripts -name '*.sh' -type f -exec chmod 755 {} \\; ";
$ret = `$cmd`;
print "Rename directory $BUILDROOT/$PROJECT.tmp into $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build\n";
$cmd = "mv $BUILDROOT/$PROJECT.tmp $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build";
print
"Rename directory $BUILDROOT/$PROJECT.tmp into $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build\n";
$cmd =
"mv $BUILDROOT/$PROJECT.tmp $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build";
$ret = `$cmd`;
print "Go into directory $BUILDROOT\n";
chdir("$BUILDROOT");
# We need a tarball to be able to build "quilt" debian package (not required for native but we need patch so it is not a native)
print "Compress $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build into $BUILDROOT/$FILENAMEDEBNATIVE.orig.tar.gz...\n";
$cmd = "tar --exclude-vcs --exclude-from \"$BUILDROOT/$PROJECT/dev/build/tgz/tar_exclude.txt\" --directory \"$BUILDROOT\" --mode=go-w --group=500 --owner=500 -czvf \"$BUILDROOT/$FILENAMEDEBNATIVE.orig.tar.gz\" $PROJECT-$MAJOR.$MINOR.$build";
# We need a tarball to be able to build "quilt" debian package (not required for native but we need patch so it is not a native)
print
"Compress $BUILDROOT/$PROJECT-$MAJOR.$MINOR.$build into $BUILDROOT/$FILENAMEDEBNATIVE.orig.tar.gz...\n";
$cmd =
"tar --exclude-vcs --exclude-from \"$BUILDROOT/$PROJECT/dev/build/tgz/tar_exclude.txt\" --directory \"$BUILDROOT\" --mode=go-w --group=500 --owner=500 -czvf \"$BUILDROOT/$FILENAMEDEBNATIVE.orig.tar.gz\" $PROJECT-$MAJOR.$MINOR.$build";
print $cmd. "\n";
$ret = `$cmd`;
@@ -1429,8 +1457,10 @@ if ($nboftargetok) {
chdir("$olddir");
print "You can check bin package with lintian --pedantic -E -I \"$NEWDESTI/${FILENAMEDEB}_all.deb\"\n";
print "You can check src package with lintian --pedantic -E -I \"$NEWDESTI/${FILENAMEDEB}.dsc\"\n";
print
"You can check bin package with lintian --pedantic -E -I \"$NEWDESTI/${FILENAMEDEB}_all.deb\"\n";
print
"You can check src package with lintian --pedantic -E -I \"$NEWDESTI/${FILENAMEDEB}.dsc\"\n";
# Move to final dir
print "Move *_all.deb *.dsc *.orig.tar.gz *.changes to $NEWDESTI\n";
@@ -1438,7 +1468,7 @@ if ($nboftargetok) {
$ret = `mv $BUILDROOT/*.dsc "$NEWDESTI/"`;
$ret = `mv $BUILDROOT/*.orig.tar.gz "$NEWDESTI/"`;
#$ret=`mv $BUILDROOT/*.debian.tar.xz "$NEWDESTI/"`; # xz file is generated when build/debian/sources/option
#$ret=`mv $BUILDROOT/*.debian.tar.xz "$NEWDESTI/"`; # xz file is generated when build/debian/sources/option
$ret = `mv $BUILDROOT/*.debian.tar.gz "$NEWDESTI/"`;
$ret = `mv $BUILDROOT/*.changes "$NEWDESTI/"`;
next;
@@ -1460,15 +1490,17 @@ if ($nboftargetok) {
print "Check that ISCC.exe is in your PATH.\n";
}
else {
print "Check that in your Wine setup, you have created a Z: drive that point to your / directory.\n";
print
"Check that in your Wine setup, you have created a Z: drive that point to your / directory.\n";
}
$SOURCEBACK = $SOURCE;
$SOURCEBACK =~ s/\//\\/g;
print "Prepare file \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\" from \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.iss\"\n";
print
"Prepare file \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\" from \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.iss\"\n";
#$ret=`cat "$SOURCE/dev/build/exe/doliwamp/doliwamp.iss" | sed -e 's/__FILENAMEEXEDOLIWAMP__/$FILENAMEEXEDOLIWAMP/g' > "$SOURCE/build/exe/doliwamp/doliwamp.tmp.iss"`;
#$ret=`cat "$SOURCE/dev/build/exe/doliwamp/doliwamp.iss" | sed -e 's/__FILENAMEEXEDOLIWAMP__/$FILENAMEEXEDOLIWAMP/g' > "$SOURCE/build/exe/doliwamp/doliwamp.tmp.iss"`;
open( my $IN3, '<',
$SOURCE . "/dev/build/exe/doliwamp/doliwamp.iss" )
or die $!;
@@ -1482,35 +1514,40 @@ if ($nboftargetok) {
close($IN3);
close($OUT);
print "Compil exe $FILENAMEEXEDOLIWAMP.exe file from iss file \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\" on OS $OS\n";
print
"Compil exe $FILENAMEEXEDOLIWAMP.exe file from iss file \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\" on OS $OS\n";
if ( $OS eq 'windows' ) {
$cmd = "ISCC.exe \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\"";
$cmd =
"ISCC.exe \"$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\"";
}
else {
#$cmd= "wine ISCC.exe \"Z:$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\"";
#$cmd= "wine ISCC.exe \"Z:$SOURCEBACK\\dev\\build\\exe\\doliwamp\\doliwamp.tmp.iss\"";
}
print "$cmd\n";
$ret = `$cmd`;
print "ret=$ret\n";
# Move to final dir
print "Move \"$SOURCE\\dev\\build\\$FILENAMEEXEDOLIWAMP.exe\" to $NEWDESTI/$FILENAMEEXEDOLIWAMP.exe\n";
print
"Move \"$SOURCE\\dev\\build\\$FILENAMEEXEDOLIWAMP.exe\" to $NEWDESTI/$FILENAMEEXEDOLIWAMP.exe\n";
rename(
"$SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe",
"$NEWDESTI/$FILENAMEEXEDOLIWAMP.exe"
);
print "Move $SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe to $NEWDESTI/$FILENAMEEXEDOLIWAMP.exe\n";
print
"Move $SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe to $NEWDESTI/$FILENAMEEXEDOLIWAMP.exe\n";
use File::Copy;
#$ret=`mv "$SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe" "$NEWDESTI/$FILENAMEEXEDOLIWAMP.exe"`;
#$ret=`mv "$SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe" "$NEWDESTI/$FILENAMEEXEDOLIWAMP.exe"`;
$ret = move(
"$SOURCE/dev/build/$FILENAMEEXEDOLIWAMP.exe",
"$NEWDESTI/$FILENAMEEXEDOLIWAMP.exe"
);
print "Remove tmp file $SOURCE/dev/build/exe/doliwamp/doliwamp.tmp.iss\n";
print
"Remove tmp file $SOURCE/dev/build/exe/doliwamp/doliwamp.tmp.iss\n";
#$ret=`rm "$SOURCE/dev/build/exe/doliwamp/doliwamp.tmp.iss"`;
$ret = unlink("$SOURCE/dev/build/exe/doliwamp/doliwamp.tmp.iss");
@@ -1529,7 +1566,7 @@ if ($nboftargetok) {
"$DESTI/signatures/filelist-$MAJOR.$MINOR.$BUILD.xml" =>
'none', # none means it won't be published on SF
"$DESTI/package_rpm_generic/$FILENAMERPM" =>
'Dolibarr installer for Fedora-Redhat-Mandriva-Opensuse (DoliRpm)',
'Dolibarr installer for Fedora-Redhat-Mandriva-Opensuse (DoliRpm)',
"$DESTI/package_rpm_generic/$FILENAMERPMSRC" =>
'none', # none means it won't be published on SF
"$DESTI/package_debian-ubuntu/${FILENAMEDEB}_all.deb" =>
@@ -1560,7 +1597,8 @@ if ($nboftargetok) {
'package_debian-ubuntu',
"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.dsc" =>
'package_debian-ubuntu',
#"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.xz"=>'package_debian-ubuntu',
#"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.xz"=>'package_debian-ubuntu',
"$DESTI/package_debian-ubuntu/${FILENAMEDEB}.debian.tar.gz" =>
'package_debian-ubuntu',
"$DESTI/package_debian-ubuntu/${FILENAMEDEBSHORT}.orig.tar.gz" =>
@@ -1622,7 +1660,8 @@ if ($nboftargetok) {
$NUM_SCRIPT = <STDIN>;
chomp($NUM_SCRIPT);
print "Create empty dir /tmp/emptydir. We need it to create target dir using rsync.\n";
print
"Create empty dir /tmp/emptydir. We need it to create target dir using rsync.\n";
$ret = `mkdir -p "/tmp/emptydir/"`;
%filestoscan = %filestoscansf;
@@ -1666,13 +1705,13 @@ if ($nboftargetok) {
#use String::ShellQuote qw( shell_quote );
#$ssh->cmd('mkdir '.shell_quote($destFolder).' && exit');
#use Net::SFTP::Foreign;
#my $sftp = Net::SFTP::Foreign->new($ip, user => $user, password => $pass, autodie => 1);
#$sftp->mkdir($destFolder)
#use Net::SFTP::Foreign;
#my $sftp = Net::SFTP::Foreign->new($ip, user => $user, password => $pass, autodie => 1);
#$sftp->mkdir($destFolder)
#$command="ssh eldy,dolibarr\@frs.sourceforge.net mkdir -p \"$destFolder\"";
#print "$command\n";
#my $ret=`$command 2>&1`;
#$command="ssh eldy,dolibarr\@frs.sourceforge.net mkdir -p \"$destFolder\"";
#print "$command\n";
#my $ret=`$command 2>&1`;
$command = "rsync -s -e 'ssh' --recursive /tmp/emptydir/ \""
. $destFolder . "\"";

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
diff -up htdocs/filefunc.inc.php.patch htdocs/filefunc.inc.php
--- htdocs/filefunc.inc.php.patch 2011-09-03 02:32:48.666952000 +0200
+++ htdocs/filefunc.inc.php 2011-09-03 02:33:00.510952001 +0200
@@ -63,8 +63,8 @@
@@ -128,8 +128,8 @@
$conffile = "conf/conf.php";
$conffiletoshow = "htdocs/conf/conf.php";
// For debian/redhat like systems

View File

@@ -103,7 +103,7 @@ cui hai bisogno ed essere facile da usare.
%{__cp} -pr dev/build/tgz/* $RPM_BUILD_ROOT%{_datadir}/%{name}/dev/build/tgz
%{__cp} -pr htdocs $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__cp} -pr scripts $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/nusoap
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
@@ -189,7 +189,6 @@ done >>%{name}.lang
%_datadir/dolibarr/htdocs/expedition
%_datadir/dolibarr/htdocs/expensereport
%_datadir/dolibarr/htdocs/exports
%_datadir/dolibarr/htdocs/externalsite
%_datadir/dolibarr/htdocs/fichinter
%_datadir/dolibarr/htdocs/fourn
%_datadir/dolibarr/htdocs/ftp

View File

@@ -167,7 +167,7 @@ cui hai bisogno ed essere facile da usare.
%{__cp} -pr dev/build/tgz/* $RPM_BUILD_ROOT%{_datadir}/%{name}/dev/build/tgz
%{__cp} -pr htdocs $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__cp} -pr scripts $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/ckeditor/_source
%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos_version}
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/nusoap
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
@@ -270,7 +270,6 @@ done >>%{name}.lang
%_datadir/dolibarr/htdocs/expedition
%_datadir/dolibarr/htdocs/expensereport
%_datadir/dolibarr/htdocs/exports
%_datadir/dolibarr/htdocs/externalsite
%_datadir/dolibarr/htdocs/fichinter
%_datadir/dolibarr/htdocs/fourn
%_datadir/dolibarr/htdocs/ftp

View File

@@ -102,7 +102,7 @@ cui hai bisogno ed essere facile da usare.
%{__cp} -pr dev/build/tgz/* $RPM_BUILD_ROOT%{_datadir}/%{name}/dev/build/tgz
%{__cp} -pr htdocs $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__cp} -pr scripts $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
# Lang
@@ -187,7 +187,6 @@ done >>%{name}.lang
%_datadir/dolibarr/htdocs/expedition
%_datadir/dolibarr/htdocs/expensereport
%_datadir/dolibarr/htdocs/exports
%_datadir/dolibarr/htdocs/externalsite
%_datadir/dolibarr/htdocs/fichinter
%_datadir/dolibarr/htdocs/fourn
%_datadir/dolibarr/htdocs/ftp

View File

@@ -102,7 +102,7 @@ cui hai bisogno ed essere facile da usare.
%{__cp} -pr dev/build/tgz/* $RPM_BUILD_ROOT%{_datadir}/%{name}/dev/build/tgz
%{__cp} -pr htdocs $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__cp} -pr scripts $RPM_BUILD_ROOT%{_datadir}/%{name}
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
# Lang
@@ -197,7 +197,6 @@ done >>%{name}.lang
%_datadir/dolibarr/htdocs/expedition
%_datadir/dolibarr/htdocs/expensereport
%_datadir/dolibarr/htdocs/exports
%_datadir/dolibarr/htdocs/externalsite
%_datadir/dolibarr/htdocs/fichinter
%_datadir/dolibarr/htdocs/fourn
%_datadir/dolibarr/htdocs/ftp

View File

@@ -263,7 +263,7 @@ with
PHP JQUERYFILETREE:
-------------------
* Remove directory htdocs/public/includes/jquery/plugins/jqueryFileTree/connectors
* Remove directory htdocs/includes/jquery/plugins/jqueryFileTree/connectors

View File

@@ -15,7 +15,7 @@
"npm": ">=5.6.0"
},
"dependencies": {
"zapier-platform-core": "18.1.1"
"zapier-platform-core": "17.5.0"
},
"devDependencies": {
"mocha": "^5.2.0",

View File

@@ -1,2 +1 @@
/initdemopostsql.sql
/mysqldump_dolibarr_24.0.0.sql2

View File

@@ -1,23 +0,0 @@
BEGIN - regnumber=7dd3b63bd8… - date=2025-02-05T11:54:50Z - period=2025-01 - entity=1 - formatexport=VE1 - user=Alice Adminson;Id;Date création;Action;Origine;Montant HT;Montant TTC;Réf.;Date;Utilisateur;Lier à;Type de lien;Données complètes;Version;Version de la signature;Signature dans la base de données;État;NOTE - previoushash=b63e359ffca54d5c2bab869916eaf23d4a736703028ccbf77ce1167c5f830e7b
;"411";"1736932388";"MODULE_SET";"";"0";"0";"systemevent";"1736932388";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""id"":0,""ref"":""systemevent"",""entity"":1,""date"":1736932388}";"24.0.0-alpha";"V2";"2031b54f7017f18227cbee83d2e0c3beec2cf2169e472719dd6b920f143ed94e";"Valid";
;"413";"1736932630";"BLOCKEDLOG_EXPORT";"";"0";"0";"systemevent";"1736932630";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""id"":0,""ref"":""systemevent"",""entity"":1,""date"":1736932630,""fullname"":""Alice Adminson"",""label"":""Export unalterable logs"",""period"":""year=2024 month=1""}";"24.0.0-alpha";"V2";"b850352ef955c0b8133386b79f88dd347e2c625ed133e30e49314f502ace54fc";"Valid";
;"414";"1736932963";"BILL_VALIDATE";"";"9";"9";"FA2501-0037";"1736895600";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""FA2501-0037"",""module_source"":"""",""pos_source"":"""",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""PINKDRESS"",""product_type"":""0"",""product_label"":""Pink dress"",""qty"":""1"",""subprice"":""9.00000000"",""tva_tx"":""0.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""9.00000000"",""total_tva"":""0.00000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""9.00000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""9.00000000"",""multicurrency_total_tva"":""0.00000000"",""multicurrency_total_ttc"":""9.00000000""}},""type"":""0"",""date"":1736895600,""total_ht"":9,""total_tva"":0,""total_ttc"":9,""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"1e43eda5e73678c9275d0137cbf5684d12a79b3d0d32eafa79583b8e21ae4869";"Valid";
;"415";"1737018433";"BILL_VALIDATE";"";"11";"11";"FA2501-0038";"1737018433";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""FA2501-0038"",""module_source"":"""",""pos_source"":"""",""pos_print_counter"":0,""email_sent_counter"":0,""invoiceline"":{""1"":{""product_type"":""1"",""product_label"":""Adh\u00e9sion \/ cotisation 2025"",""qty"":""1"",""subprice"":""11.00000000"",""tva_tx"":""0.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""11.00000000"",""total_tva"":""0.00000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""11.00000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""11.00000000"",""multicurrency_total_tva"":""0.00000000"",""multicurrency_total_ttc"":""11.00000000""}},""type"":0,""date"":1737018433,""total_ht"":11,""total_tva"":0,""total_ttc"":11}";"24.0.0-alpha";"V2";"20ea65b804e7250ef18a4c4bb40c0dc66362c0b1bf3a2055a596920f808a15ae";"Valid";
;"416";"1737018433";"PAYMENT_CUSTOMER_CREATE";"";"";"11";"PAY2501-0001";"1736982000";"Alice Adminson";"FA2501-0038";"payment";"{""thirdparty"":{""name"":""test test"",""email"":""test@test.com"",""idprof1"":"""",""idprof2"":"""",""tva_assuj"":""1"",""tva_intra"":"""",""code_client"":""CU2501-00037"",""country_code"":""FR""},""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""PAY2501-0001"",""date"":1736982000,""type_code"":""CHQ"",""payment_part"":{""1"":{""amount"":""11"",""invoice"":{""ref"":""FA2501-0038"",""module_source"":"""",""pos_source"":"""",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""type"":""0"",""date"":1736982000,""total_ht"":""11.00000000"",""total_tva"":""0.00000000"",""total_ttc"":""11.00000000"",""revenuestamp"":""0.00000000""}}},""amount"":11}";"24.0.0-alpha";"V2";"af79bb9344a27868825a1c22b2c9ab6d2f7db2aef315541f049490ea620daae5";"Valid";
;"417";"1737018535";"BILL_VALIDATE";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":1.25,""total_tva"":0.25,""total_ttc"":1.5,""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"b9c58af18960660e2d98b7ca5539677ee0b611f2f49c2ce3ddcd2a7fff06e2b8";"Valid";
;"418";"1737018536";"PAYMENT_CUSTOMER_CREATE";"takepos";"";"1.5";"PAY2501-0002";"1737018535";"Alice Adminson";"TC1-2501-0009";"payment";"{""thirdparty"":{""name"":""Generic customer"",""email"":""ttt@ttt.com"",""idprof1"":"""",""idprof2"":"""",""tva_assuj"":""1"",""tva_intra"":"""",""capital"":""0.00000000"",""typent_code"":""TE_PRIVATE"",""code_client"":""CU1302-0011"",""country_code"":""GB""},""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""PAY2501-0002"",""date"":1737018535,""type_code"":""LIQ"",""payment_part"":{""1"":{""amount"":""1.5"",""invoice"":{""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}}},""amount"":1.5}";"24.0.0-alpha";"V2";"bb3ffec5b8e04ceb0f1a469b882487aadd6f5e1e04244f5e7ddf1cc2f2f2e3c4";"Valid";
;"419";"1737019049";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":1,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"17a3c6170409b72a5fedf853abb00581877b18320a207e479c42d77b3d07c4d6";"Valid";
;"420";"1737019181";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":2,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"d8770dd062220b8332d304039a53565de2d2d5f917f0aa5620dbcb634e75462e";"Valid";
;"421";"1737019353";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":3,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"dbb2d0f11a6ed01566b69717ddb1c08cee10f6964c47cd6b5f0da213027fd1be";"Valid";
;"422";"1737019636";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":4,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"e6e65a101521cb8b3921ae31d9565be3432ac94703f2e055e8f1229cb2abee6b";"Valid";
;"423";"1737020016";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":5,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"24e0d354f83b5e216414930cfa0b07923725a98a0457969df3f962111932baa2";"Valid";
;"424";"1737024079";"DOC_PREVIEW";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":6,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"f1daed6d4977aed9427b2f6530c340b2613e0d9dbfc748d68cf5320af1def9ea";"Valid";
;"431";"1737028500";"BILL_SENTBYMAIL";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":""8"",""email_sent_counter"":5,""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000"",""action_email_sent"":{""email_from"":""myemail@mybigcompany.com"",""email_to"":""ttt@ttt.com"",""email_msgid"":""6788f3948bc635.10121388.phpmail@cc385f40e47e5be82815b1fa583939f749c7f86e""}}";"24.0.0-alpha";"V2";"749dbdedc18a10087649f00ee3e6b27ce8d092c513450174dc54503959d8a2f8";"Valid";
;"432";"1737028654";"BILL_SENTBYMAIL";"takepos";"1.25";"1.5";"TC1-2501-0009";"1736982000";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC1-2501-0009"",""module_source"":""takepos"",""pos_source"":""1"",""pos_print_counter"":""6"",""email_sent_counter"":2,""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""}},""type"":""0"",""date"":1736982000,""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_ttc"":""1.50000000"",""revenuestamp"":""0.00000000"",""action_email_sent"":{""email_from"":""aaaa <aaaa@aa.com>"",""email_to"":""test@test.com"",""email_msgid"":""6788f42ecbbfd9.77578037.phpmail-dolibarr-inv460@cc385f40e47e5be82815b1fa583939f749c7f86e""}}";"24.0.0-alpha";"V2";"2456751468d90ed6cdd06da34cf8a392585eb152db6a9d457c8f6f97539a77ae";"Valid";
;"433";"1737102950";"DOC_PREVIEW";"takepos";"2.33";"2.8";"(PROV-POS2-0)";"1737068400";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""(PROV-POS2-0)"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""},""2"":{""ref"":""POS-KIWI"",""product_type"":""0"",""product_label"":""Kiwi"",""qty"":""1"",""subprice"":""1.08333000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.08000000"",""total_tva"":""0.22000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.30000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.08000000"",""multicurrency_total_tva"":""0.22000000"",""multicurrency_total_ttc"":""1.30000000""}},""type"":""0"",""date"":1737068400,""total_ht"":""2.33000000"",""total_tva"":""0.47000000"",""total_ttc"":""2.80000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"451b90f983512fa095ef9475876d130084489f3e2cb89464ad522391dc1b06a2";"Valid";
;"434";"1737102963";"BILL_VALIDATE";"takepos";"2.33";"2.8";"TC2-2501-0001";"1737068400";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC2-2501-0001"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""},""2"":{""ref"":""POS-KIWI"",""product_type"":""0"",""product_label"":""Kiwi"",""qty"":""1"",""subprice"":""1.08333000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.08000000"",""total_tva"":""0.22000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.30000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.08000000"",""multicurrency_total_tva"":""0.22000000"",""multicurrency_total_ttc"":""1.30000000""}},""type"":""0"",""date"":1737068400,""total_ht"":2.33,""total_tva"":0.47,""total_ttc"":2.8,""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"a4f51205e87339187636bd26df2b330dba86c404204144a69711ec4e0e0cc58f";"Valid";
;"435";"1737102963";"PAYMENT_CUSTOMER_CREATE";"takepos";"";"2.8";"PAY2501-0003";"1737102963";"Alice Adminson";"TC2-2501-0001";"payment";"{""thirdparty"":{""name"":""Generic customer"",""email"":""ttt@ttt.com"",""idprof1"":"""",""idprof2"":"""",""tva_assuj"":""1"",""tva_intra"":"""",""capital"":""0.00000000"",""typent_code"":""TE_PRIVATE"",""code_client"":""CU1302-0011"",""country_code"":""GB""},""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""PAY2501-0003"",""date"":1737102963,""type_code"":""LIQ"",""payment_part"":{""1"":{""amount"":""2.8"",""invoice"":{""ref"":""TC2-2501-0001"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":""0"",""email_sent_counter"":""0"",""type"":""0"",""date"":1737068400,""total_ht"":""2.33000000"",""total_tva"":""0.47000000"",""total_ttc"":""2.80000000"",""revenuestamp"":""0.00000000""}}},""amount"":2.8}";"24.0.0-alpha";"V2";"e095af5c7eec1f1d0272d1ab633c9f9b78d5f9ee44f425f3fed5ed844ea700b2";"Valid";
;"436";"1737102971";"DOC_PREVIEW";"takepos";"2.33";"2.8";"TC2-2501-0001";"1737068400";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC2-2501-0001"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":1,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""},""2"":{""ref"":""POS-KIWI"",""product_type"":""0"",""product_label"":""Kiwi"",""qty"":""1"",""subprice"":""1.08333000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.08000000"",""total_tva"":""0.22000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.30000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.08000000"",""multicurrency_total_tva"":""0.22000000"",""multicurrency_total_ttc"":""1.30000000""}},""type"":""0"",""date"":1737068400,""total_ht"":""2.33000000"",""total_tva"":""0.47000000"",""total_ttc"":""2.80000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"fc5c19832334b5c00d7cc3a4414a5ca37867fa9ee5c367c921324aaebd0f81de";"Valid";
;"437";"1737102993";"DOC_PREVIEW";"takepos";"2.33";"2.8";"TC2-2501-0001";"1737068400";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC2-2501-0001"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":2,""email_sent_counter"":""0"",""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""},""2"":{""ref"":""POS-KIWI"",""product_type"":""0"",""product_label"":""Kiwi"",""qty"":""1"",""subprice"":""1.08333000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.08000000"",""total_tva"":""0.22000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.30000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.08000000"",""multicurrency_total_tva"":""0.22000000"",""multicurrency_total_ttc"":""1.30000000""}},""type"":""0"",""date"":1737068400,""total_ht"":""2.33000000"",""total_tva"":""0.47000000"",""total_ttc"":""2.80000000"",""revenuestamp"":""0.00000000""}";"24.0.0-alpha";"V2";"91cf7545174270befeb93fcefb67acb2f07525c7d73a190eee76936cfa7dfd7d";"Valid";
;"438";"1737104486";"BILL_SENTBYMAIL";"takepos";"2.33";"2.8";"TC2-2501-0001";"1737068400";"Alice Adminson";"";"";"{""mycompany"":{""name"":""MyBigCompany"",""phone"":""09123123"",""fax"":""09123124"",""email"":""myemail@mybigcompany.com"",""idprof1"":""123456"",""idprof2"":""ABC-DEF"",""idprof3"":""15E-45-8D"",""tva_assuj"":1,""tva_intra"":""FR12345678"",""localtax1_assuj"":0,""localtax2_assuj"":0,""managers"":""Zack Zeceo"",""capital"":10000,""forme_juridique_code"":0,""country_code"":""FR"",""address"":""21 Jump street."",""zip"":""75500"",""town"":""MyTown""},""ref"":""TC2-2501-0001"",""module_source"":""takepos"",""pos_source"":""2"",""pos_print_counter"":""2"",""email_sent_counter"":1,""invoiceline"":{""1"":{""ref"":""POS-APPLE"",""product_type"":""0"",""product_label"":""Apple"",""qty"":""1"",""subprice"":""1.25000000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.25000000"",""total_tva"":""0.25000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.50000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.25000000"",""multicurrency_total_tva"":""0.25000000"",""multicurrency_total_ttc"":""1.50000000""},""2"":{""ref"":""POS-KIWI"",""product_type"":""0"",""product_label"":""Kiwi"",""qty"":""1"",""subprice"":""1.08333000"",""tva_tx"":""20.000"",""localtax1_tx"":""0.000"",""localtax2_tx"":""0.000"",""total_ht"":""1.08000000"",""total_tva"":""0.22000000"",""total_localtax1"":""0.00000000"",""total_localtax2"":""0.00000000"",""total_ttc"":""1.30000000"",""info_bits"":""0"",""special_code"":""0"",""multicurrency_code"":""EUR"",""multicurrency_total_ht"":""1.08000000"",""multicurrency_total_tva"":""0.22000000"",""multicurrency_total_ttc"":""1.30000000""}},""type"":""0"",""date"":1737068400,""total_ht"":""2.33000000"",""total_tva"":""0.47000000"",""total_ttc"":""2.80000000"",""revenuestamp"":""0.00000000"",""action_email_sent"":{""email_from"":""Alice Adminson <laurent@destailleur.fr>"",""email_to"":""Generic customer <ttt@ttt.com>"",""email_msgid"":""678a1c6608cdb4.28637446.phpmail-dolibarr-inv461@cc385f40e47e5be82815b1fa583939f749c7f86e""}}";"24.0.0-alpha";"V2";"7ebd906d6133f5526411664bc637ad88fc5d30bd147d4e6dcfc460520144411f";"Valid";
END - sha256=14290f951be42f11da5b36274cdbb9d018ea1787855c19c92f317152bf7bb9e6 - hmac_sha256=851ac6dc40c60faf69efeb4ef6712abacfffe5a986c674ca478f8c1525a126eb
Can't render this file because it has a wrong number of fields in line 23.

View File

@@ -1,6 +1,5 @@
#!/bin/bash
# Copyright (C) 2010-2026 Laurent Destailleur <eldy@users.sourceforge.net>
# Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
# Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
#------------------------------------------------------
# Script to purge and initialize a database with demo values.
@@ -12,8 +11,8 @@
# Regis Houssin - regis.houssin@inodbox.com
# Laurent Destailleur - eldy@users.sourceforge.net
#------------------------------------------------------
# Usage: initdemo.sh confirm|confirmresetblockedlog
# usage: initdemo.sh confirm|confirmresetblockedlog mysqldump_dolibarr_x.x.x.sql database port login pass
# Usage: initdemo.sh confirm
# usage: initdemo.sh confirm mysqldump_dolibarr_x.x.x.sql database port login pass
#------------------------------------------------------
@@ -44,12 +43,12 @@ admin=$5
passwd=$6
# ----------------------------- check params
if [ "$confirm" != "confirm" ] && [ "$confirm" != "confirmresetblockedlog" ]
if [ "$confirm" != "confirm" ]
then
echo "----- $0 -----"
echo "Usage: initdemo.sh confirm|confirmresetblockedlog "
echo "Usage: initdemo.sh confirm "
echo " or"
echo "Usage: initdemo.sh confirm|confirmresetblockedlog [mysqldump_dolibarr_x.x.x.sql database port login pass]"
echo "Usage: initdemo.sh confirm [mysqldump_dolibarr_x.x.x.sql database port login pass]"
exit
fi
@@ -92,7 +91,7 @@ then
fichtemp=$(mktemp 2>/dev/null) || fichtemp=/tmp/test$$
# shellcheck disable=2064,2172
trap "rm -f '$fichtemp'" 0 1 2 5 15
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql database name :" 16 55 "$base" 2> "$fichtemp"
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql database name :" 16 55 $base 2> "$fichtemp"
valret=$?
case $valret in
0)
@@ -108,7 +107,7 @@ then
fichtemp=$(mktemp 2>/dev/null) || fichtemp=/tmp/test$$
# shellcheck disable=2064,2172
trap "rm -f '$fichtemp'" 0 1 2 5 15
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql port (ex: 3306):" 16 55 "$port" 2> "$fichtemp"
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql port (ex: 3306):" 16 55 $port 2> "$fichtemp"
valret=$?
case $valret in
@@ -162,7 +161,7 @@ then
# ---------------------------- confirmation
$DIALOG --title "Erase Dolibarr with demo values" --clear --yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Document dir : '$documentdir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : --hidden--" 15 55
$DIALOG --title "Init Dolibarr with demo values" --clear --yesno "Do you confirm ? \n Dump file : '$dumpfile' \n Dump dir : '$mydir' \n Document dir : '$documentdir' \n Mysql database : '$base' \n Mysql port : '$port' \n Mysql login: '$admin' \n Mysql password : --hidden--" 15 55
case $? in
0) echo "Ok, start process..." ;;
@@ -173,7 +172,7 @@ then
fi
# ---------------------------- Run sql file
# ---------------------------- run sql file
if [ "$passwd" != "" ]
then
export passwd="-p$passwd"
@@ -182,11 +181,8 @@ fi
#echo "mysql -P$port -u$admin $passwd $base < $mydir/$dumpfile"
#mysql -P$port -u$admin $passwd $base < $mydir/$dumpfile
#echo "drop old table"
echo "drop table if exists llx_accounting_account;"
echo "drop table"
echo "drop table if exists llx_accounting_account;" | mysql "-P$port" "-u$admin" "$passwd" "$base"
echo "drop table if exists llx_accounting_system;"
echo "drop table if exists llx_accounting_system;" | mysql "-P$port" "-u$admin" "$passwd" "$base"
echo "mysql -P$port -u$admin $passwdshown $base < '$mydir/$dumpfile'"
mysql "-P$port" "-u$admin" "$passwd" "$base" < "$mydir/$dumpfile"
export res=$?
@@ -196,24 +192,10 @@ if [ $res -ne 0 ]; then
exit
fi
# ---------------------------- Run update of demo data
echo
echo Run script updatedemo.php confirm
"$mydir/updatedemo.php" confirm
export res=$?
# ---------------------------- Run update of demo data
if [ "$confirm" == "confirmresetblockedlog" ]; then
echo
echo Run script updatedemo.php confirmresetblockedlog
"$mydir/updatedemo.php" confirmresetblockedlog
export res=$?
fi
# ---------------------------- Copy demo files
# ---------------------------- copy demo files
export documentdir
# shellcheck disable=2016
documentdir=$(< "$mydir/../../htdocs/conf/conf.php" grep '^\$dolibarr_main_data_root' | sed -e 's/$dolibarr_main_data_root=//' | sed -e 's/;//' | sed -e "s/'//g" | sed -e 's/"//g')
@@ -264,8 +246,8 @@ fi
if [ "$res" = "0" ]
then
echo "Success, file successfully loaded: Note that crypted data need to have dolibarr_main_instance_unique_id=11f3c81e86fc9e3b3fd11d81c9a31bd0 with this data set to be readable."
echo "Success, file successfully loaded."
else
echo "Error, 1 step of script has failed."
echo "Error, load failed."
fi
echo

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,4 @@
#!/bin/bash
# Copyright (C) 2010-2026 Laurent Destailleur <eldy@users.sourceforge.net>
#!/bin/sh
#------------------------------------------------------
# Script to extract a database with demo values.
# Note: "dialog" tool need to be available if no parameter provided.
@@ -13,28 +11,26 @@
#------------------------------------------------------
# shellcheck disable=2012,2006,2034,2046,2064,2086,2155,2166,2186,2172,2268
export mydir
mydir=${0//savedemo.sh/}
if [ "$mydir" = "" ] || [ "$mydir" = "./" ]
export mydir=`echo "$0" | sed -e 's/savedemo.sh//'`;
if [ "x$mydir" = "x" ]
then
export mydir="."
fi
export id
id=$(id -u)
export id=`id -u`;
# ----------------------------- check if root
if [ "$id" != "0" ] && [ "$id" != "1001" ]
if [ "x$id" != "x0" -a "x$id" != "x1001" ]
then
echo "Script must be executed as root"
echo "Script must be ran as root"
exit
fi
# ----------------------------- command line params
dumpfile=$1;
base="${2:-dolibarrdemo}"
port="${3:-3306}"
base=$2;
port=$3;
admin=$4;
passwd=$5;
@@ -58,7 +54,7 @@ then
fichtemp=`tempfile 2>/dev/null` || fichtemp=/tmp/test$$
trap "rm -f $fichtemp" 0 1 2 5 15
$DIALOG --title "Save Dolibarr with demo values" --clear \
--inputbox "Output dump file :" 16 55 "$dumpfile" 2> $fichtemp
--inputbox "Output dump file :" 16 55 $dumpfile 2> $fichtemp
valret=$?
case $valret in
0)
@@ -75,7 +71,7 @@ then
fichtemp=`tempfile 2>/dev/null` || fichtemp=/tmp/test$$
trap "rm -f $fichtemp" 0 1 2 5 15
$DIALOG --title "Save Dolibarr with demo values" --clear \
--inputbox "Mysql database name :" 16 55 "$base" 2> $fichtemp
--inputbox "Mysql database name :" 16 55 dolibarrdemo 2> $fichtemp
valret=$?
case $valret in
0)
@@ -91,7 +87,7 @@ then
fichtemp=`tempfile 2>/dev/null` || fichtemp=/tmp/test$$
trap "rm -f $fichtemp" 0 1 2 5 15
$DIALOG --title "Save Dolibarr with demo values" --clear \
--inputbox "Mysql port (ex: 3306):" 16 55 "$port" 2> $fichtemp
--inputbox "Mysql port (ex: 3306):" 16 55 3306 2> $fichtemp
valret=$?
@@ -176,7 +172,6 @@ fi
if [ "x$passwd" != "x" ]
then
export passwd="-p$passwd"
export passwdshown="-p*****"
fi
export list="
--ignore-table=$base.llx_abonne
@@ -352,24 +347,20 @@ export list="
--ignore-table=$base.llx_ultimatepdf
--ignore-table=$base.llx_update_modules
--ignore-table=$base.llx_ventilation_achat
--ignore-table=$base.llx_verifactudolibarr_add_tpls
--ignore-table=$base.llx_verifactudolibarr_facture_log
--ignore-table=$base.llx_verifactudolibarr_messages
--ignore-table=$base.llx_verifactudolibarr_tax_type
--ignore-table=$base.tmp_llx_accouting_account
--ignore-table=$base.tmp_llx_product_batch
--ignore-table=$base.tmp_llx_product_batch2
--ignore-table=$base.tmp_tmp
--ignore-table=$base.tmp_user
"
echo "mysqldump -P$port -u$admin $passwdshown $list $base > $mydir/$dumpfile"
echo "mysqldump -P$port -u$admin -p***** $list $base > $mydir/$dumpfile"
mysqldump -P$port -u$admin $passwd $list $base > $mydir/$dumpfile
export res=$?
if [ "x$res" = "x0" ]
then
echo "Success, file successfully dumped."
echo "Success, file successfully loaded."
else
echo "Error, dump failed."
echo "Error, load failed."
fi
echo

View File

@@ -65,7 +65,6 @@ if (!$res) {
* @var DoliDB $db
*/
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
include_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
/*
@@ -102,115 +101,6 @@ $tables = array(
);
if ($confirm == 'regenerate') {
$entity = 1;
$fromrowid = 0;
//$fromrowid = 442;
$block_static = new BlockedLog($db);
$block_static->loadTrackedEvents();
print "TZ=".date_default_timezone_get()."\n";
$db->begin();
// Now restart request with all data, so without the limit(1) in sql request
$sql = "SELECT rowid, entity, date_creation, tms, user_fullname, action, module_source, amounts_taxexcl, amounts, element, fk_object, date_object, ref_object,";
$sql .= " linktoref, linktype, signature, fk_user, object_data, object_version, object_format, debuginfo";
$sql .= " FROM ".MAIN_DB_PREFIX."blockedlog";
$sql .= " WHERE entity = ".((int) $entity);
$sql .= " AND rowid >= ".((int) $fromrowid);
$sql .= " ORDER BY date_creation ASC, rowid ASC"; // Required so later we can use the parameter $previoushash of checkSignature()
$i = 0;
$resql = $db->query($sql);
if ($resql) {
// Make the first fetch to get first line and then get the previous hash.
while ($obj = $db->fetch_object($resql)) {
// We set here all data used into signature calculation (see checkSignature method) and more
// IMPORTANT: We must have here, the same rule for transformation of data than into
// the blockedlog->fetch() method (db->jdate for date, ...)
$block_static->id = $obj->rowid;
$block_static->entity = $obj->entity;
if ($i == 0) {
$tmparray = $block_static->getPreviousHash(0, $block_static->id);
$previoushash = $tmparray['previoushash'];
}
$tz = 'gmt';
if (empty($obj->object_format) || $obj->object_format == 'V1') {
$tz = 'tzserver';
}
$block_static->date_creation = $db->jdate($obj->date_creation, $tz); // jdate(date_creation) is UTC
$block_static->date_modification = $db->jdate($obj->tms, $tz); // jdate(tms) is UTC
$block_static->action = $obj->action;
$block_static->module_source = $obj->module_source;
$block_static->amounts_taxexcl = is_null($obj->amounts_taxexcl) ? null : (float) $obj->amounts_taxexcl; // Database store value with 8 digits, we cut ending 0 them with (flow)
$block_static->amounts = (float) $obj->amounts; // Database store value with 8 digits, we cut ending 0 them with (flow)
$block_static->fk_object = $obj->fk_object; // Not in signature
$block_static->date_object = $db->jdate($obj->date_object, $tz); // jdate(date_object) is UTC
$block_static->ref_object = $obj->ref_object;
$block_static->linktoref = $obj->linktoref;
$block_static->linktype = $obj->linktype;
$block_static->fk_user = $obj->fk_user; // Not in signature
$block_static->user_fullname = $obj->user_fullname;
$block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data);
// Old hash + Previous fields concatenated = signature
$block_static->signature = $obj->signature;
$block_static->element = $obj->element; // Not in signature
$block_static->object_format = $obj->object_format; // Not in signature.
$block_static->object_version = $obj->object_version; // Not in signature
//$block_static->certified = ($obj->certified == 1); // Not in signature
//var_dump($obj->date_creation, $tz, $block_static->date_creation);
// Build/Check the string for the signature
$signature = $block_static->checkSignature($previoushash, 2);
print "For ROWID ".$obj->rowid." - Previous hash = ".$previoushash."\n";
print "Signature in db: ".$obj->signature." - New calculated: ".$signature['calculatedsignature']."\n";
if ($obj->signature != $signature['calculatedsignature']) {
$tmpsql = "UPDATE ".MAIN_DB_PREFIX."blockedlog SET signature = '".$db->escape($signature['calculatedsignature'])."'";
$tmpsql .= " WHERE rowid = ".((int) $obj->rowid);
print "Update for ROWID ".$obj->rowid." with ".$tmpsql."\n";
$tmpresult = $db->query($tmpsql);
}
$previoushash = $signature['calculatedsignature'];
// Set new previous hash for next fetch
$i++;
// Uncomment to proceed one only
//break;
}
} else {
$error++;
setEventMessages($db->lasterror, null, 'errors');
}
$db->commit();
}
if ($confirm == 'confirm') {
print "Update dates to current year for database name = ".$db->database_name."\n";
@@ -346,7 +236,7 @@ if ($confirm == 'confirmresetblockedlog') {
$db->query($sql);
$sql = "UPDATE ".MAIN_DB_PREFIX."facture SET datef = datec";
$sql = "UPDATE ".MAIN_DB_PREFIX."facture SET datef = datec WHERE datef >= NOW()";
print $sql;
print "\n";
$db->query($sql);
@@ -362,12 +252,6 @@ if ($confirm == 'confirmresetblockedlog') {
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = 'MAIN_FIRST_REGISTRATION_OK_DATE'";
print $sql;
print "\n";
$db->query($sql);
/*
// Delete corrupted record no more used that still exists in demo image but can't exist in a production env
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog WHERE action LIKE 'PAYMENT_VARIOUS_%'";

View File

@@ -1,103 +0,0 @@
<?php
/* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace codesniffer\Sniffs\Dolibarr;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* CheckIsModEnabledArgumentSniff
*/
class CheckIsModEnabledArgumentSniff implements Sniff
{
// Nom de la fonction cible
protected $targetFunction = 'ismodenabled';
protected $deprecatedModulesNames = [
'actioncomm' => 'agenda',
'adherent' => 'member',
'adherent_type' => 'member_type',
'banque' => 'bank',
'categorie' => 'category',
'commande' => 'order',
'contrat' => 'contract',
'entrepot' => 'stock',
'expedition' => 'shipping',
'facture' => 'invoice',
'ficheinter' => 'intervention',
'product_fournisseur_price' => 'productsupplierprice',
'product_price' => 'productprice',
'projet' => 'project',
'propale' => 'propal',
'socpeople' => 'contact',
];
/**
* register
*
* @return void
*/
public function register()
{
// We are listening function calls (T_STRING)
return [T_STRING];
}
/**
* process
*
* @param File $phpcsFile file to process
* @param mixed $stackPtr pointer
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if (strtolower($tokens[$stackPtr]['content']) !== strtolower($this->targetFunction)) {
return;
}
// Check that it is a function call (followed by '(')
$openParen = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
if ($tokens[$openParen]['code'] !== T_OPEN_PARENTHESIS) {
return;
}
// We are looking for the first 'useful' token after the parenthesis
$firstArgTokenPtr = $phpcsFile->findNext(T_WHITESPACE, $openParen + 1, null, true);
// If the function is called without arguments (isModEnabled()), we stop
if ($tokens[$firstArgTokenPtr]['code'] === T_CLOSE_PARENTHESIS) {
return;
}
// check value of argument
$argContent = str_replace(["'", '"'], '', $tokens[$firstArgTokenPtr]['content']);
$argCode = $tokens[$firstArgTokenPtr]['code'];
if (array_key_exists($argContent, $this->deprecatedModulesNames)) {
$phpcsFile->addError(
'The function "%s" has deprecated argument ("%s") to replace with "%s".',
$firstArgTokenPtr,
'DeprecatedArgument',
[$tokens[$stackPtr]['content'], $argContent, $this->deprecatedModulesNames[$argContent]]
);
}
}
}

View File

@@ -1,112 +0,0 @@
<?php
/* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace codesniffer\Sniffs\Dolibarr;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* LanguageOfCommentsSniff
*/
class LanguageOfCommentsSniff implements Sniff
{
// List of words that betray a comment in French
public $frenchWords = [
' additionner ',
' arrondir ',
' avec ',
' calculer ',
' chaine ',
' chaîne ',
' chercher ',
' chiffre ',
' chiffres ',
// ' commande ',
' commandes ',
' compteur ',
' compteurs ',
' contrats ',
' depuis ',
' diviser ',
' donnée ',
' entier ',
// ' facture ', // avoid french name of dolibarr object
' factures ',
' ligne ',
' lignes ',
' modèle ',
' niveau ',
' niveaux ',
' nombre ',
' parametrage ',
' paramétrage ',
' pourcentage ',
' produit ',
' produits ',
' quand ',
' rechercher ',
' sinon ',
' stocker ',
' soustraire ',
' sujet ',
' sujets ',
' suppression ',
' utilisateur ',
' utilisateurs ',
' valeur ',
' valeurs ',
];
/**
* Which tokens to listen ?
* T_COMMENT = comments // or #
* T_DOC_COMMENT_STRING = text in block comments
* @return int[]
*/
public function register()
{
return [
T_COMMENT,
T_DOC_COMMENT_STRING,
];
}
/**
* process
*
* @param File $phpcsFile file to process
* @param mixed $stackPtr pointer
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$content = $tokens[$stackPtr]['content'];
// Basic cleanup (lowercase for comparison)
$contentLower = strtolower($content);
foreach ($this->frenchWords as $word) {
if (strpos($contentLower, $word) !== false) {
$error = "The comment appears to be in French (word detected: '%s'). Please write in English.";
$data = [trim($word)];
$phpcsFile->addWarning($error, $stackPtr, 'FrenchDetected', $data);
return; // We stop at the first occurrence.
}
}
}
}

View File

@@ -21,11 +21,6 @@
<exclude-pattern>/\.git/</exclude-pattern>
<exclude-pattern>/\.cache/</exclude-pattern>
<!-- Custom rules -->
<config name="installed_paths" value="/dev/setup/codesniffer" />
<rule ref="codesniffer.Dolibarr.LanguageOfComments"/>
<rule ref="codesniffer.Dolibarr.CheckIsModEnabledArgument"/>
<!-- List of all tests -->
@@ -36,12 +31,12 @@
<!-- Rules from Generic Standard -->
<!--
<rule ref="PSR12.Files.OpenTag">
<properties>
<property name="ignoreIndent" value="true"/>
</properties>
</rule>
<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">
@@ -81,16 +76,16 @@
<severity>0</severity>
</rule>
<!-- Lower severity on warnings we do not want to show in the pre-commit reports -->
<rule ref="Generic.Files.LineLength.TooLong">
<!-- Lower severity on warnings we do not want to show in the pre-commit reports -->
<rule ref="Generic.Files.LineLength.TooLong">
<severity>4</severity>
</rule>
<rule ref="Generic.Metrics.CyclomaticComplexity.TooHigh">
</rule>
<rule ref="Generic.Metrics.CyclomaticComplexity.TooHigh">
<severity>4</severity>
</rule>
<rule ref="Generic.Metrics.NestingLevel.TooHigh">
</rule>
<rule ref="Generic.Metrics.NestingLevel.TooHigh">
<severity>4</severity>
</rule>
</rule>
<!-- Warnings on TODO -->

View File

@@ -1,18 +1,18 @@
# Fail2Ban configuration file
#
# Regexp to detect try to check a couple login/password so we can add mitigation on IPs making too much tries.
# Regexp to detect try to check a couple login/password so we can add mitigation
# on IP making too much tries.
[Definition]
# To test, you can inject this example into log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 functions_dolibarr::check_user_password_abcd Authentication KO" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 1234567 33 functions_dolibarr::check_user_password_abcd Authentication KO" >> /mypath/documents/dolibarr.log
#
# then
# fail2ban-client status web-dolibarr-bruteforce
# fail2ban-client status web-dol-bruteforce
#
# To test rule file on a existing log file
# fail2ban-regex /mypath/documents/dolibarr.log /etc/fail2ban/filter.d/web-dolibarr-rulesbruteforce.conf --print-all-matched
failregex = ^ [A-Z\s]+ <HOST>\s.*functions_.*::check_user_.* Authentication KO
failregex = ^ [A-Z\s]+ <HOST>\s+functions_.*::check_user_.* Authentication KO
ignoreregex =

View File

@@ -7,7 +7,6 @@
# To test, you can inject this example into log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 Hack attempt detected - xxx" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 1234567 33 Hack attempt detected - xxx" >> /mypath/documents/dolibarr.log
#
# then
# fail2ban-client status web-dolibarr-hackattempt
@@ -15,5 +14,5 @@
# To test rule file on a existing log file
# fail2ban-regex /mypath/documents/dolibarr.log /etc/fail2ban/filter.d/web-dolibarr-hackattempt.conf --print-all-matched
failregex = ^ [A-Z\s]+ <HOST>\s.*Hack attempt detected
failregex = ^ [A-Z\s]+ <HOST>\s+Hack attempt detected
ignoreregex =

View File

@@ -6,8 +6,7 @@
[Definition]
# To test, you can inject this example into log
# echo `date +'%Y-%m-%d %H:%M:%S'`" NOTICE 1.2.3.4 --- Access to GET /public/clicktodial/cidlookup.php" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" NOTICE 1.2.3.4 1234567 33 --- Access to GET /public/clicktodial/cidlookup.php" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 --- Access to GET /public/clicktodial/cidlookup.php" >> /mypath/documents/dolibarr.log
#
# then
# fail2ban-client status web-dolibarr-limitpublic
@@ -15,5 +14,5 @@
# To test rule file on a existing log file
# fail2ban-regex /mypath/documents/dolibarr.log /etc/fail2ban/filter.d/web-dolibarr-limitpublic.conf --print-all-matched
failregex = ^ [A-Z\s]+ <HOST>\s.*--- Access to .*/public/
failregex = ^ [A-Z\s]+ <HOST>\s+--- Access to .*/public/
ignoreregex =

View File

@@ -6,8 +6,7 @@
[Definition]
# To test, you can inject this example into log
# echo `date +'%Y-%m-%d %H:%M:%S'`" NOTICE 1.2.3.4 --- Access to GET /passwordforgotten.php - action=buildnewpassword, massaction=" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" NOTICE 1.2.3.4 1234567 33 --- Access to GET /passwordforgotten.php - action=buildnewpassword, massaction=" >> /mypath/documents/dolibarr.log
# echo `date +'%Y-%m-%d %H:%M:%S'`" INFO 1.2.3.4 --- Access to GET /passwordforgotten.php - action=buildnewpassword, massaction=" >> /mypath/documents/dolibarr.log
#
# then
# fail2ban-client status web-dolibarr-passf
@@ -15,5 +14,5 @@
# To test rule file on a existing log file
# fail2ban-regex /mypath/documents/dolibarr.log /etc/fail2ban/filter.d/web-dolibarr-passf.conf --print-all-matched
failregex = ^ [A-Z\s]+ <HOST>\s.*--- Access to .*/passwordforgotten.php - action=buildnewpassword
failregex = ^ [A-Z\s]+ <HOST>\s+--- Access to .*/passwordforgotten.php - action=buildnewpassword
ignoreregex =

View File

@@ -47,7 +47,7 @@ function save_db_cache() (
# Get the target version from the version.inc.php file
target_version=$(sed -n "s/.*define('DOL_\\(MAJOR_\\)\\?VERSION',[[:space:]]*'\\([0-9.]*\\).*/\\2/p" ../version.inc.php) ; echo $target_version
# Default in case that failed
target_version=${target_version:=22.0.0}
target_version=${target_version:=23.0.0}
# Sequence of versions for upgrade process (to be completed)
VERSIONS=("3.5.0" "3.6.0" "3.7.0" "3.8.0" "3.9.0")

View File

@@ -883,7 +883,7 @@ foreach ($arrayofalerts as $key => $alert) {
// VDP ID
$html .= '<td style="white-space: nowrap">';
if (!empty($alert['issueidvdp'])) {
$html .= '#'.$alert['issueidvdp'];
$html .= '#vdp'.$alert['issueidvdp'];
$arrayofalerts[$key]['description'] .= "\n<br>".'VDP ID #'.$alert['issueidvdp'];
} else {
//$html .= '<span class="opacitymedium">public issue</span>';
@@ -1158,11 +1158,11 @@ function cleanVal2($val)
if (preg_match('/CVE([0-9\-\s]+)/', $tmpval['title'], $reg)) {
$tmpval['issueidcve'] = preg_replace('/^\-/', '', preg_replace('/\s+/', '-', trim($reg[1])));
}
if (preg_match('/#(yogosha\d+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidvdp'] = strtolower($reg[1]);
if (preg_match('/#yogosha(\d+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidvdp'] = $reg[1];
}
if (preg_match('/#(ghsa[a-z\-\d]+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidvdp'] = strtolower($reg[1]);
if (preg_match('/#ghsa([a-z\-\d]+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidvdp'] = $reg[1];
}
return $tmpval;

View File

@@ -97,7 +97,7 @@
$sql .= " AND cs.periode >= '".$db->idate($search_date_limit_start)."'";
$sql .= " OR (cs.periode IS NULL AND cs.date_ech between '".$db->idate(dol_get_first_day($year))."' AND '".$db->idate(dol_get_last_day($year))."')";
$sql .= " SET reponses = '".$db->escape($nouveauchoix)."'";
$sql .= " cs.rowid, cs.libelle, cs.fk_type as type, cs.periode as period, cs.date_ech, cs.amount as total,";
$sql .= " cs.rowid, cs.libelle as label, cs.fk_type as type, cs.periode as period, cs.date_ech, cs.amount as total,";
$sql.= " ".MAIN_DB_PREFIX."notify_def as nd,";
$sql.= " AND nd.fk_action = ad.rowid";
$sql.= " WHERE u.rowid = nd.fk_user";

View File

@@ -9,18 +9,19 @@
*/
return [
// # Issue statistics:
// PhanUndeclaredProperty : 400+ occurrences
// PhanTypeMismatchArgument : 60+ occurrences
// PhanUndeclaredGlobalVariable : 50+ occurrences
// PhanUndeclaredProperty : 410+ occurrences
// PhanTypeMismatchArgument : 65+ occurrences
// PhanUndeclaredGlobalVariable : 60+ occurrences
// PhanTypeMismatchArgumentNullable : 20+ occurrences
// PhanTypeMismatchProperty : 20+ occurrences
// PhanTypeInvalidDimOffset : 10+ occurrences
// PhanTypeInvalidDimOffset : 15+ occurrences
// PhanTypeMismatchDimFetch : 10+ occurrences
// PhanTypeMismatchArgumentNullable : 7 occurrences
// PhanTypeArraySuspiciousNull : 5 occurrences
// PhanTypeExpectedObjectPropAccess : 5 occurrences
// PhanUndeclaredMethod : 5 occurrences
// PhanPluginDuplicateArrayKey : 4 occurrences
// PhanPluginUndeclaredVariableIsset : 2 occurrences
// PhanPossiblyUndeclaredGlobalVariable : 2 occurrences
// PhanTypeMismatchArgumentProbablyReal : 2 occurrences
// PhanParamTooMany : 1 occurrence
// PhanPossiblyUndeclaredVariable : 1 occurrence
@@ -29,6 +30,7 @@ return [
// Currently, file_suppressions and directory_suppressions are the only supported suppressions
'file_suppressions' => [
'htdocs/categories/viewcat.php' => ['PhanUndeclaredProperty'],
'htdocs/comm/action/index.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchProperty'],
'htdocs/comm/action/pertype.php' => ['PhanTypeExpectedObjectPropAccess'],
'htdocs/comm/action/peruser.php' => ['PhanTypeMismatchArgument'],
@@ -39,12 +41,16 @@ return [
'htdocs/commande/class/commande.class.php' => ['PhanUndeclaredProperty'],
'htdocs/commande/list.php' => ['PhanUndeclaredProperty'],
'htdocs/commande/list_det.php' => ['PhanTypeInvalidDimOffset'],
'htdocs/compta/bank/account_statement_document.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/bank/class/account.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/bank/class/paymentvarious.class.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/bank/line.php' => ['PhanUndeclaredGlobalVariable'],
'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/clients.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/facture/card.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/facture/class/facture.class.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/localtax/card.php' => ['PhanUndeclaredGlobalVariable'],
@@ -53,6 +59,7 @@ return [
'htdocs/compta/paiement/card.php' => ['PhanUndeclaredProperty'],
'htdocs/compta/paiement/cheque/list.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable'],
'htdocs/compta/paiement/rapport.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/prelevement/card.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/resultat/clientfourn.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/resultat/index.php' => ['PhanTypeMismatchArgument'],
'htdocs/compta/resultat/projects.php' => ['PhanTypeMismatchArgument'],
@@ -69,7 +76,7 @@ return [
'htdocs/core/class/CMailFile.class.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/class/canvas.class.php' => ['PhanUndeclaredMethod'],
'htdocs/core/class/cgenericdic.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/commonobject.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonobject.class.php' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonpeople.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/conf.class.php' => ['PhanTypeMismatchProperty'],
'htdocs/core/class/ctyperesource.class.php' => ['PhanUndeclaredProperty'],
@@ -94,32 +101,38 @@ return [
'htdocs/core/modules/asset/mod_asset_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/bom/mod_bom_advanced.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/modules/cheque/modules_chequereceipts.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/commande/doc/pdf_einstein.modules.php' => ['PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/commande/doc/pdf_einstein.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/contract/doc/pdf_strato.modules.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/contract/doc/pdf_strato.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/delivery/doc/pdf_storm.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/delivery/doc/pdf_typhon.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/delivery/mod_delivery_saphir.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/expedition/doc/pdf_espadon.modules.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/expedition/doc/pdf_espadon.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expedition/doc/pdf_merou.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expedition/doc/pdf_rouget.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expensereport/doc/pdf_standard_expensereport.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/facture/doc/pdf_octopus.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/modules/facture/doc/pdf_octopus.modules.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/holiday/mod_holiday_immaculate.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/hrm/mod_evaluation_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/import/import_csv.modules.php' => ['PhanPossiblyUndeclaredVariable'],
'htdocs/core/modules/member/modules_cards.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/mrp/doc/pdf_vinci.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/mrp/mod_mo_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/oauth/github_oauthcallback.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/propale/doc/pdf_azur.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/propale/doc/pdf_cyan.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/reception/doc/pdf_squille.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/propale/doc/pdf_azur.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/modules/propale/doc/pdf_cyan.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/modules/reception/doc/pdf_squille.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/stocktransfer/mod_stocktransfer_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php' => ['PhanTypeMismatchProperty'],
'htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php' => ['PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php' => ['PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php' => ['PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_proposal/doc/pdf_zenith.modules.php' => ['PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'],
'htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/supplier_proposal/doc/pdf_zenith.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/syslog/mod_syslog_file.php' => ['PhanPluginDuplicateArrayKey'],
'htdocs/core/modules/workstation/mod_workstation_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/multicompany_page.php' => ['PhanTypeMismatchArgument'],
@@ -133,6 +146,7 @@ return [
'htdocs/delivery/class/delivery.class.php' => ['PhanUndeclaredProperty'],
'htdocs/emailcollector/class/emailcollector.class.php' => ['PhanUndeclaredProperty'],
'htdocs/eventorganization/class/conferenceorboothattendee.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'],
'htdocs/eventorganization/core/actions_massactions_mail.inc.php' => ['PhanUndeclaredProperty'],
'htdocs/expedition/card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/expedition/class/expedition.class.php' => ['PhanUndeclaredProperty'],
'htdocs/expensereport/card.php' => ['PhanUndeclaredProperty'],
@@ -221,15 +235,16 @@ return [
'htdocs/salaries/virement_request.php' => ['PhanUndeclaredProperty'],
'htdocs/societe/ajax/company.php' => ['PhanUndeclaredProperty'],
'htdocs/societe/class/societe.class.php' => ['PhanTypeMismatchProperty'],
'htdocs/societe/paymentmodes.php' => ['PhanTypeMismatchArgument'],
'htdocs/societe/paymentmodes.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgument'],
'htdocs/supplier_proposal/card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'],
'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanUndeclaredProperty'],
'htdocs/supplier_proposal/class/supplier_proposal.class.php' => ['PhanUndeclaredProperty'],
'htdocs/takepos/invoice.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/takepos/invoice.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'],
'htdocs/takepos/split.php' => ['PhanPluginUndeclaredVariableIsset'],
'htdocs/ticket/card.php' => ['PhanUndeclaredProperty'],
'htdocs/ticket/class/actions_ticket.class.php' => ['PhanUndeclaredProperty'],
'htdocs/ticket/class/cticketcategory.class.php' => ['PhanUndeclaredProperty'],
'htdocs/ticket/class/ticket.class.php' => ['PhanUndeclaredProperty'],
'htdocs/user/class/user.class.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'htdocs/user/class/usergroup.class.php' => ['PhanUndeclaredProperty'],
'htdocs/variants/tpl/productattributevalueline_edit.tpl.php' => ['PhanUndeclaredProperty'],
@@ -238,6 +253,7 @@ return [
'htdocs/webhook/target_card.php' => ['PhanUndeclaredGlobalVariable'],
'htdocs/webportal/admin/setup.php' => ['PhanTypeMismatchArgument'],
'htdocs/webportal/class/html.formlistwebportal.class.php' => ['PhanUndeclaredProperty'],
'htdocs/webportal/class/webportalpropal.class.php' => ['PhanUndeclaredProperty'],
'htdocs/webservices/server_project.php' => ['PhanUndeclaredProperty'],
],
// 'directory_suppressions' => ['src/directory_name' => ['PhanIssueName1', 'PhanIssueName2']] can be manually added if needed.

View File

@@ -227,24 +227,6 @@ return [
'backward_compatibility_checks' => false,
'simplify_ast' => true,
'analyzed_file_extensions' => ['php','inc'],
/*'included_extension_subset' => [
'curl',
'dom',
'filter',
'gd',
'imap',
'intl',
'json',
'libxml',
'mbstring',
'mysqli',
'opcache',
'openssl',
'session',
'sqlite3',
'xml',
'zip'
],*/
'globals_type_map' => [
'_Avery_Labels' => '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}>',
'action' => 'string',
@@ -457,7 +439,6 @@ return [
'PhanTypeObjectUnsetDeclaredProperty',
'PhanTypePossiblyInvalidDimOffset', // a lot of false positive, in most cases, we want to keep the code as it is
// 'PhanPluginUnknownArrayFunctionReturnType', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanTypeMismatchArgumentSuperType', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanPluginWhitespaceTab', // Dolibarr uses tabs
'PhanPluginCanUsePHP71Void', // Dolibarr is maintaining 7.0 compatibility

View File

@@ -74,7 +74,6 @@ $config['suppress_issue_types'] = [
'PhanTypeObjectUnsetDeclaredProperty',
'PhanTypePossiblyInvalidDimOffset', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanPluginUnknownArrayFunctionReturnType', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanTypeMismatchArgumentSuperType', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanPluginWhitespaceTab', // Dolibarr used tabs
'PhanPluginCanUsePHP71Void', // Dolibarr is maintaining 7.0 compatibility

View File

@@ -76,8 +76,6 @@ parameters:
- '#Empty array passed to foreach#'
- '#Unable to resolve the template type T#'
- '#in empty\(\) always exists and is always falsy#'
- '#in empty\(\) always exists and is not falsy#'
- '#in isset\(\) is not nullable#'
- '#is always#'
internalErrorsCountLimit: 50
cache:

View File

@@ -23,7 +23,7 @@
# - Some side effects from translations on variables.
# - Some other minors side effects to be examined (#, %).
#
# Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
# Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
LANG_DIR=htdocs/langs/en_US/
MYDIR=$(dirname "$(realpath "$0")")
@@ -141,10 +141,10 @@ sed -n 's@< \(.*\)@^\1\\s*=@p' \
#
REPL_STR=""
for t in trans transnoentities transnoentitiesnoconv newItem buttonsSaveCancel; do
REPL_STR="${REPL_STR}\n->${t}(\"\\1\","
REPL_STR="${REPL_STR}\n->${t}('\\1',"
REPL_STR="${REPL_STR}\n->${t}(\"\\1\")"
REPL_STR="${REPL_STR}\n->${t}('\\1')"
REPL_STR="${REPL_STR}\n->${t}(\"\\1\","
REPL_STR="${REPL_STR}\n->${t}('\\1',"
REPL_STR="${REPL_STR}\n->${t}(\"\\1\")"
REPL_STR="${REPL_STR}\n->${t}('\\1')"
done
rm -f "${MISSING_FILE}.grep" >/dev/null 2>&1

View File

@@ -100,7 +100,7 @@ if (!$sortorder) {
$object = new AccountingAccount($db);
$arrayfields = array(
'aa.account_number' => array('label' => "AccountNumber", 'checked' => '1'),
'aa.account_number' => array('label' => "AccountNumber", 'checked' => '1', 'csslist' => 'maxwidth50'),
'aa.label' => array('label' => "Label", 'checked' => '1'),
'aa.labelshort' => array('label' => "ShortLabel", 'checked' => '1'),
'aa.account_parent' => array('label' => "Accountparent", 'checked' => '1'),
@@ -259,9 +259,6 @@ if ($action == 'delete') {
$pcgver = getDolGlobalInt('CHARTOFACCOUNTS');
$sql = "SELECT aa.rowid, aa.fk_pcg_version, aa.pcg_type, aa.account_number, aa.account_parent, aa.label, aa.labelshort, aa.fk_accounting_category,";
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
$sql .= " (SELECT COUNT(*) FROM ".MAIN_DB_PREFIX."accounting_category_account aca WHERE aca.fk_accounting_account = aa.rowid) as nb_categories,";
}
$sql .= " aa.reconcilable, aa.centralized, aa.active, aa.import_key,";
$sql .= " a2.rowid as rowid2, a2.label as label2, a2.account_number as account_number2";
@@ -530,10 +527,10 @@ if ($resql) {
print '</td>';
}
if (!empty($arrayfields['aa.account_number']['checked'])) {
print '<td class="liste_titre"><input type="text" class="flat width100" name="search_account" value="'.$search_account.'"></td>';
print '<td class="liste_titre"><input type="text" class="flat width75" name="search_account" value="'.$search_account.'"></td>';
}
if (!empty($arrayfields['aa.label']['checked'])) {
print '<td class="liste_titre"><input type="text" class="flat width150" name="search_label" value="'.$search_label.'"></td>';
print '<td class="liste_titre"><input type="text" class="flat width100" name="search_label" value="'.$search_label.'"></td>';
}
if (!empty($arrayfields['aa.labelshort']['checked'])) {
print '<td class="liste_titre"><input type="text" class="flat width100" name="search_labelshort" value="'.$search_labelshort.'"></td>';
@@ -764,31 +761,9 @@ if ($resql) {
}
// Custom accounts
if (!empty($arrayfields['categories']['checked'])) {
print '<td>';
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
// Multi report system
if (!empty($obj->nb_categories)) {
$accountingcategory_temp = new AccountancyCategory($db);
$categories = $accountingcategory_temp->getCategoriesForAccount($obj->rowid);
$categoriesLabels = array();
foreach ($categories as $cat) {
$categoriesLabels[] = '<span class="badge badge-status4" title="'.dol_escape_htmltag($cat['label']).'">'.dol_escape_htmltag($cat['code']).'</span>';
}
print implode(' ', $categoriesLabels);
} else {
print '<span class="opacitymedium">-</span>';
}
} else {
// OLD SYSTEM: One-to-many
if (!empty($obj->fk_accounting_category)) {
print dol_escape_htmltag($obj->fk_accounting_category);
} else {
print '<span class="opacitymedium">-</span>';
}
}
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";
if (!$i) {
$totalarray['nbfield']++;

View File

@@ -11,8 +11,8 @@
* Copyright (C) 2011-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 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
@@ -196,7 +196,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("Country")), null, 'errors');
}
// In case of 'actionadd' and with valid parameters, add the line
// Si verif ok et action add, on ajoute la ligne
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -241,11 +241,11 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// In case of 'actionmodify' and with valid parameters, modify the line
// Si verif ok et action modify, on modifie la ligne
if ($ok && GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Change field's value
// Modifie valeur des champs
$i = 0;
foreach ($listfieldmodify as $field) {
@@ -268,6 +268,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
$sql .= " WHERE rowid = ".((int) $rowid);
dol_syslog("actionmodify", LOG_DEBUG);
//print $sql;
$resql = $db->query($sql);
if (!$resql) {
setEventMessages($db->error(), null, 'errors');
@@ -326,13 +327,13 @@ $linkback = '';
print load_fiche_titre($titre, $linkback, 'title_accountancy');
// Confirmation of line deletion
// Confirmation de la suppression de la ligne
if ($action == 'delete') {
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);
}
// Complete the values search query with the sort order
// Complete requete recherche valeurs avec critere de tri
$sql = $tabsql[$id];
if ($search_country_id > 0) {
@@ -350,6 +351,7 @@ if ($sortfield == 'country') {
}
$sql .= $db->order($sortfield, $sortorder);
$sql .= $db->plimit($listlimit + 1, $offset);
//print $sql;
$fieldlist = explode(',', $tabfield[$id]);
@@ -366,8 +368,8 @@ $fieldlist = explode(',', $tabfield[$id]);
// Line for title
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries
// 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";
@@ -391,6 +393,7 @@ foreach ($fieldlist as $field => $value) {
if ($fieldlist[$field] == 'pcg_version' || $fieldlist[$field] == 'fk_pcg_version') {
$valuetoshow = $langs->trans("Pcg_version");
}
//var_dump($value);
if ($valuetoshow != '') {
print '<td class="'.$class.'">';

View File

@@ -1,9 +1,9 @@
<?php
/* Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2014-2015 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2016 Jamal Elbaz <jamelbaz@gmail.pro>
* Copyright (C) 2017-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2022 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
*
* 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
@@ -27,6 +27,9 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
/**
* @var Conf $conf
@@ -36,399 +39,187 @@ require '../../main.inc.php';
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
$error = 0;
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "admin", "bills", "compta"));
$langs->loadLangs(array("bills", "accountancy", "compta"));
$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
$id = GETPOSTINT('id');
$catid = GETPOSTINT('catid'); // Alternative parameter name for consistency
if (empty($id) && !empty($catid)) {
$id = $catid;
$cancel = GETPOST('cancel', 'alpha');
$action = GETPOST('action', 'aZ09');
$cat_id = GETPOSTINT('account_category');
$selectcpt = GETPOST('cpt_bk', 'array');
$cpt_id = GETPOSTINT('cptid');
if ($cat_id == 0) {
$cat_id = null;
}
// Load variable for pagination
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$sortfield = GETPOST('sortfield', 'aZ09comma');
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
// If $page is not defined, or '' or -1 or if we click on clear filters
$page = 0;
}
$offset = $limit * $page;
$pageprev = $page - 1;
$pagenext = $page + 1;
if (empty($sortfield)) {
$sortfield = 'account_number';
}
if (empty($sortorder)) {
$sortorder = 'ASC';
}
$account_id = GETPOSTINT('account_id');
$cpt_id = GETPOSTINT('cpt'); // For compatibility with old system
// Security check
if (!$user->hasRight('accounting', 'chartofaccount')) {
accessforbidden();
}
// Initialize objects
$accountingcategory = new AccountancyCategory($db);
$form = new Form($db);
$formaccounting = new FormAccounting($db);
// Load category
if ($id > 0) {
$result = $accountingcategory->fetch($id);
if ($result < 0) {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
}
}
// Parameters for list (new system only)
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$sortfield = GETPOST('sortfield', 'aZ09comma');
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
$page = 0;
}
$offset = $limit * $page;
// Search filters (new system only)
$search_account = GETPOST('search_account', 'alpha');
$search_label = GETPOST('search_label', 'alpha');
if (empty($sortfield)) {
$sortfield = "aa.account_number";
}
if (empty($sortorder)) {
$sortorder = "ASC";
}
// Use new multi report system
$useNewSystem = (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT'));
/*
* Actions
*/
if ($useNewSystem) {
// Remove filter
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
$search_account = '';
$search_label = '';
}
// Add account to category
if ($action == 'add_account' && !empty($account_id)) {
$result = $accountingcategory->addAccountToCategory($account_id);
if ($result > 0) {
setEventMessages($langs->trans("AccountAddedToCategory"), null, 'mesgs');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit;
} elseif ($result == 0) {
setEventMessages($langs->trans("AccountAlreadyInCategory"), null, 'warnings');
} else {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
// If we add account
if (!empty($selectcpt)) {
$cpts = array();
foreach ($selectcpt as $selectedoption) {
if (!array_key_exists($selectedoption, $cpts)) {
$cpts[$selectedoption] = "'".$selectedoption."'";
}
}
// Remove account from category
if ($action == 'confirm_delete' && $confirm == 'yes' && !empty($account_id)) {
$result = $accountingcategory->deleteAccountFromCategory($account_id);
$return = $accountingcategory->updateAccAcc((int) $cat_id, $cpts);
if ($result > 0) {
setEventMessages($langs->trans("AccountRemovedFromCategory"), null, 'mesgs');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit;
} else {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
}
if ($return < 0) {
setEventMessages($langs->trans('errors'), $accountingcategory->errors, 'errors');
} else {
setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
}
}
// Add multiple accounts
if ($action == 'add_multiple' && GETPOST('accounts_to_add', 'array')) {
$accounts_to_add = GETPOST('accounts_to_add', 'array');
$result = $accountingcategory->addMultipleAccountsToCategory($accounts_to_add);
if ($result > 0) {
setEventMessages($langs->trans("XAccountsAdded", $result), null, 'mesgs');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit;
} elseif ($result < 0) {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
if ($action == 'delete') {
if ($cpt_id) {
if ($accountingcategory->deleteCptCat($cpt_id)) {
setEventMessages($langs->trans('AccountRemovedFromGroup'), null, 'mesgs');
} else {
setEventMessages($langs->trans("NoAccountAdded"), null, 'warnings');
}
}
// Remove all accounts
if ($action == 'confirm_remove_all' && $confirm == 'yes') {
$result = $accountingcategory->removeAllAccountsFromCategory();
if ($result >= 0) {
setEventMessages($langs->trans("XAccountsRemoved", $result), null, 'mesgs');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit;
} else {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
}
}
} else {
// OLD SYSTEM: One-to-many via fk_accounting_category field
if ($action == 'clean') {
$result = $accountingcategory->deleteCptCat($cpt_id);
if ($result >= 0) {
header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
exit;
} else {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
setEventMessages($langs->trans('errors'), null, 'errors');
}
}
}
/*
* View
*/
$help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilité_en_Partie_Double#Configuration';
llxHeader('', $langs->trans("AccountingCategory"), $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin-categories');
$form = new Form($db);
$formaccounting = new FormAccounting($db);
if ($useNewSystem) {
// ============================================================================
// NEW SYSTEM VIEW
// ============================================================================
$title = $langs->trans('AccountingCategory');
$help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilit&eacute;_en_Partie_Double#Configuration';
// Confirmation dialogs
if ($action == 'delete') {
print $form->formconfirm(
$_SERVER["PHP_SELF"].'?id='.$id.'&account_id='.$account_id,
$langs->trans('RemoveAccountFromCategory'),
$langs->trans('ConfirmRemoveAccountFromCategory'),
'confirm_delete',
'',
0,
1
);
}
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin_categories');
if ($action == 'remove_all') {
print $form->formconfirm(
$_SERVER["PHP_SELF"].'?id='.$id,
$langs->trans('RemoveAllAccountsFromCategory'),
$langs->trans('ConfirmRemoveAllAccountsFromCategory'),
'confirm_remove_all',
'',
0,
1
);
}
$linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories_list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$titlepicto = 'setup';
// Page title
$title = $langs->trans("AccountingCategory").': '.$accountingcategory->label;
print load_fiche_titre($title, '', 'title_accountancy');
print load_fiche_titre($langs->trans('AccountingCategory'), $linkback, $titlepicto);
// Category information card
print dol_get_fiche_head();
print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="display">';
print '<table class="border centpercent">';
print '<tr><td class="titlefield">'.$langs->trans("Code").'</td><td>'.$accountingcategory->code.'</td></tr>';
print '<tr><td>'.$langs->trans("Label").'</td><td>'.$accountingcategory->label.'</td></tr>';
if (!empty($accountingcategory->range_account)) {
print '<tr><td>'.$langs->trans("Comment").'</td><td>'.$accountingcategory->range_account.'</td></tr>';
}
print '<tr><td>'.$langs->trans("AccountsLinked").'</td><td><strong>'.$accountingcategory->countAccountsInCategory().'</strong></td></tr>';
print '</table>';
print dol_get_fiche_head();
print dol_get_fiche_end();
print '<table class="border centpercent">';
// Build SQL for linked accounts
$sql = "SELECT aa.rowid, aa.account_number, aa.label";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = aca.fk_accounting_account";
$sql .= " WHERE aca.fk_accounting_category = ".((int) $id);
$sql .= " AND aa.entity = ".$conf->entity;
// Search filters
if (!empty($search_account)) {
$sql .= natural_search("aa.account_number", $search_account);
}
if (!empty($search_label)) {
$sql .= natural_search("aa.label", $search_label);
}
// Count total
$nbtotalofrecords = '';
if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
$resql = $db->query($sql);
$nbtotalofrecords = $db->num_rows($resql);
if (($page * $limit) > $nbtotalofrecords) {
$page = 0;
$offset = 0;
}
}
// Add sort and limit
$sql .= $db->order($sortfield, $sortorder);
$sql .= $db->plimit($limit + 1, $offset);
$resql = $db->query($sql);
if (!$resql) {
dol_print_error($db);
exit;
}
$num = $db->num_rows($resql);
// Parameters
$param = '&id='.$id;
if (!empty($search_account)) {
$param .= '&search_account='.urlencode($search_account);
}
if (!empty($search_label)) {
$param .= '&search_label='.urlencode($search_label);
}
// Form to add accounts
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="add_multiple">';
print '<input type="hidden" name="id" value="'.$id.'">';
// Get available accounts
$availableAccounts = $accountingcategory->getAvailableAccountsForCategory();
if (count($availableAccounts) > 0) {
print '<table class="border centpercent">';
print '<tr><td class="fieldrequired titlefieldcreate">'.$langs->trans("AddAccountsToCategory").": ".'</td><td>';
// Prepare array for multiselectarray
$arrayofaccounts = array();
foreach ($availableAccounts as $account) {
$arrayofaccounts[$account['id']] = $account['account_number'].' - '.$account['label'];
}
// Use Dolibarr native multiselect with search
print $form->multiselectarray('accounts_to_add', $arrayofaccounts, array(), 0, 0, '', 0, '100%', '', '', $langs->trans("SelectAccountsToAdd"));
print '</td></tr>';
print '</table>';
print '<div class="center">';
print '<input type="submit" class="button button-save" value="'.$langs->trans("Add").'">';
print ' &nbsp; ';
print '<input type="button" class="button button-cancel" value="'.$langs->trans("Cancel").'" onClick="javascript:history.go(-1)">';
print '</div>';
} else {
print '<div class="info">'.$langs->trans("AllAccountsAlreadyLinked").'</div>';
}
print '</form>';
// List of linked accounts
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
$massactionbutton = '';
$title = $langs->trans("AccountsLinked");
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'accountancy', 0, '', '', $limit);
print '<div class="div-table-responsive">';
print '<table class="tagtable nobottomiftotal liste">';
// Search filters row
print '<tr class="liste_titre">';
print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_account" value="'.dol_escape_htmltag($search_account).'"></td>';
print '<td class="liste_titre"><input type="text" class="flat maxwidth200" name="search_label" value="'.dol_escape_htmltag($search_label).'"></td>';
print '<td class="liste_titre center">';
$searchpicto = $form->showFilterAndCheckAddButtons(0);
print $searchpicto;
print '</td>';
print '</tr>';
// Header row
print '<tr class="liste_titre">';
print_liste_field_titre("AccountNumber", $_SERVER["PHP_SELF"], "aa.account_number", "", $param, "", $sortfield, $sortorder);
print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "aa.label", "", $param, "", $sortfield, $sortorder);
print_liste_field_titre("", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
print '</tr>';
// Data rows
$i = 0;
while ($i < min($num, $limit)) {
$obj = $db->fetch_object($resql);
print '<tr class="oddeven">';
// Account number
print '<td>';
print '<a href="'.DOL_URL_ROOT.'/accountancy/admin/card.php?id='.$obj->rowid.'">';
print $obj->account_number;
print '</a>';
print '</td>';
// Label
print '<td>';
print dol_escape_htmltag($obj->label);
print '</td>';
// Actions
print '<td class="center">';
print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$id.'&account_id='.$obj->rowid.'" class="reposition">';
print img_delete();
print '</a>';
print '</td>';
print '</tr>';
$i++;
}
if ($num == 0) {
print '<tr><td colspan="3"><span class="opacitymedium">'.$langs->trans("NoAccountLinked").'</span></td></tr>';
}
print '</table>';
print '</div>';
print '</form>';
// Button to remove all
if ($num > 0) {
print '<div class="tabsAction">';
print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?action=remove_all&token='.newToken().'&id='.$id.'">'.$langs->trans("RemoveAllAccountsFromCategory").'</a>';
print '</div>';
}
// Select the category
print '<tr><td class="titlefield">'.$langs->trans("AccountingCategory").'</td>';
print '<td>';
$s = $formaccounting->select_accounting_category((int) $cat_id, 'account_category', 1, 0, 0, 0);
if ($formaccounting->nbaccounts_category <= 0) {
print '<span class="opacitymedium">'.$s.'</span>';
} else {
// ============================================================================
// OLD SYSTEM VIEW (compatibility)
// ============================================================================
print $s;
print '<input type="submit" class="button small" value="'.$langs->trans("Select").'">';
}
print '</td></tr>';
$listcpt = $accountingcategory->display($id);
$listcptNotIn = $accountingcategory->getAccountsWithNoCategory($id);
print '</table>';
print load_fiche_titre($langs->trans('AccountingCategory')." : ".$accountingcategory->label);
print dol_get_fiche_end();
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'?id='.$id.'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="clean">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("AccountNumber").'</td>';
print '<td>'.$langs->trans("Label").'</td>';
print '<td></td>';
print "</tr>\n";
// Select the accounts
if (!empty($cat_id)) {
$return = $accountingcategory->getAccountsWithNoCategory($cat_id);
if ($return < 0) {
setEventMessages(null, $accountingcategory->errors, 'errors');
}
print '<br>';
if (is_array($listcpt) && count($listcpt) > 0) {
foreach ($listcpt as $cpt) {
print '<tr class="oddeven">';
print '<td>'.length_accountg($cpt->account_number).'</td>';
print '<td>'.$cpt->label.'</td>';
print '<td>';
print '<input type="submit" class="button smallpaddingimp" name="cpt" value="'.$cpt->rowid.'" title="'.$langs->trans("DeleteFromCat").'">';
print img_picto($langs->trans("DeleteFromCat"), 'unlink', 'class="paddingleft"');
print "</td>";
print "</tr>\n";
}
} else {
print '<tr><td colspan="3"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
$arraykeyvalue = array();
foreach ($accountingcategory->lines_cptbk as $key => $val) {
$doc_ref = !empty($val->doc_ref) ? $val->doc_ref : '';
$arraykeyvalue[length_accountg($val->numero_compte)] = length_accountg($val->numero_compte) . ' - ' . $val->label_compte . ($doc_ref ? ' '.$doc_ref : '');
}
print '</table>';
print '</form>';
if (is_array($accountingcategory->lines_cptbk) && count($accountingcategory->lines_cptbk) > 0) {
print img_picto($langs->trans("AccountingAccount"), 'accounting_account', 'class="pictofixedwidth"');
print $form->multiselectarray('cpt_bk', $arraykeyvalue, GETPOST('cpt_bk', 'array'), 0, 0, '', 0, "80%", '', '', $langs->transnoentitiesnoconv("AddAccountFromBookKeepingWithNoCategories"));
print '<input type="submit" class="button button-add small" id="" class="action-delete" value="'.$langs->trans("Add").'"> ';
}
}
print '</form>';
if ((empty($action) || $action == 'display' || $action == 'delete') && $cat_id > 0) {
$param = 'account_category='.((int) $cat_id);
print '<br>';
print '<table class="noborder centpercent">'."\n";
print '<tr class="liste_titre">';
print getTitleFieldOfList('AccountAccounting', 0, $_SERVER['PHP_SELF'], 'account_number', '', $param, '', $sortfield, $sortorder, '')."\n";
print getTitleFieldOfList('Label', 0, $_SERVER['PHP_SELF'], 'label', '', $param, '', $sortfield, $sortorder, '')."\n";
print getTitleFieldOfList('', 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, '')."\n";
print '</tr>'."\n";
if (!empty($cat_id)) {
$return = $accountingcategory->display($cat_id); // This load ->lines_display
if ($return < 0) {
setEventMessages(null, $accountingcategory->errors, 'errors');
}
if (is_array($accountingcategory->lines_display) && count($accountingcategory->lines_display) > 0) {
$accountingcategory->lines_display = dol_sort_array($accountingcategory->lines_display, $sortfield, $sortorder, -1, 0, 1);
foreach ($accountingcategory->lines_display as $cpt) {
print '<tr class="oddeven">';
print '<td>'.length_accountg($cpt->account_number).'</td>';
print '<td>'.$cpt->label.'</td>';
print '<td class="right">';
print '<a href="'.$_SERVER['PHP_SELF'].'?action=delete&token='.newToken().'&account_category='.$cat_id.'&cptid='.$cpt->rowid.'">';
print $langs->trans("DeleteFromCat");
print img_picto($langs->trans("DeleteFromCat"), 'unlink', 'class="paddingleft"');
print "</a>";
print "</td>";
print "</tr>\n";
}
} else {
print '<tr><td colspan="3"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
}
print "</table>";
}
// End of page

View File

@@ -1,8 +1,8 @@
<?php
/* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2011-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* 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
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,14 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php';
/**
* @var Conf $conf
@@ -35,16 +43,6 @@ require '../../main.inc.php';
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyreport.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php';
// Load translation files required by the page
$langs->loadLangs(array("errors", "admin", "companies", "resource", "holiday", "accountancy", "hrm"));
@@ -72,7 +70,7 @@ $listlimit = GETPOSTINT('listlimit') > 0 ? GETPOSTINT('listlimit') : 1000;
$sortfield = (string) GETPOST("sortfield", 'aZ09comma');
$sortorder = GETPOST("sortorder", 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
if (empty($page) || $page < 0 || GETPOST('button_refresh', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
// If $page is not defined, or '' or -1 or if we click on clear filters
$page = 0;
}
@@ -82,22 +80,6 @@ $pagenext = $page + 1;
$search_country_id = GETPOST('search_country_id', 'int');
// Report filter (Multi report)
$search_report = GETPOSTINT('search_report');
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
if (empty($search_report)) {
// Try to get from session
if (!empty($_SESSION['accounting_category_report_filter'])) {
$search_report = $_SESSION['accounting_category_report_filter'];
} else {
$search_report = 1; // Default report
}
} else {
// Save in session
$_SESSION['accounting_category_report_filter'] = $search_report;
}
}
// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
$hookmanager->initHooks(array('admin'));
@@ -117,7 +99,7 @@ $tablib[32] = "DictionaryAccountancyCategory";
// Requests to extract data
$tabsql = array();
$tabsql[32] = "SELECT a.rowid as rowid, a.code as code, a.label, a.range_account, a.category_type, a.formula, a.position as position, a.fk_report, a.fk_country as country_id, c.code as country_code, c.label as country, a.active FROM ".MAIN_DB_PREFIX."c_accounting_category as a, ".MAIN_DB_PREFIX."c_country as c WHERE a.fk_country=c.rowid AND c.active=1 AND a.entity IN (".getEntity('c_accounting_category').")";
$tabsql[32] = "SELECT a.rowid as rowid, a.code as code, a.label, a.range_account, a.category_type, a.formula, a.position as position, a.fk_country as country_id, c.code as country_code, c.label as country, a.active FROM ".MAIN_DB_PREFIX."c_accounting_category as a, ".MAIN_DB_PREFIX."c_country as c WHERE a.fk_country=c.rowid AND c.active=1 AND a.entity IN (".getEntity('c_accounting_category').")";
// Criteria to sort dictionaries
$tabsqlsort = array();
@@ -165,12 +147,6 @@ $accountingcategory = new AccountancyCategory($db);
if (GETPOST('button_removefilter', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter_x', 'alpha')) {
$search_country_id = '';
// Reset report filter
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
$search_report = 1;
$_SESSION['accounting_category_report_filter'] = 1;
}
}
// Actions add or modify an entry into a dictionary
@@ -233,7 +209,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors');
}
// In case of 'actionadd' and with valid parameters, add the line
// Si verif ok et action add, on ajoute la ligne
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -304,7 +280,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modify field values
// Modifie valeur des champs
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
@@ -450,71 +426,6 @@ print load_fiche_titre($titre, $linkback, $titlepicto);
print '<span class="opacitymedium">'.$langs->trans("AccountingAccountGroupsDesc", $langs->transnoentitiesnoconv("ByPersonalizedAccountGroups")).'</span><br><br>';
// Report selector (New System)
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
print '<div class="fichecenter">';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" id="form_report_selector">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Report").'</td>';
print '</tr>';
print '<tr class="oddeven">';
print '<td>';
// Get list of reports
$reports_list = array();
$sql_reports = "SELECT r.rowid, r.code, r.label";
$sql_reports .= " FROM ".MAIN_DB_PREFIX."c_accounting_report as r";
$sql_reports .= " WHERE r.active = 1";
$sql_reports .= " ORDER BY r.code ASC";
$resql_reports = $db->query($sql_reports);
if ($resql_reports) {
$num_reports = $db->num_rows($resql_reports);
$i_report = 0;
while ($i_report < $num_reports) {
$obj_report = $db->fetch_object($resql_reports);
$reports_list[$obj_report->rowid] = $obj_report->label.' ('.$obj_report->code.')';
$i_report++;
}
$db->free($resql_reports);
}
if (empty($reports_list)) {
$reports_list[1] = $langs->trans("ReportPersonalized");
}
// Display select with auto-submit
print '<select name="search_report" id="search_report" class="flat minwidth200">';
foreach ($reports_list as $report_id => $report_label) {
$selected = ($report_id == $search_report) ? ' selected' : '';
print '<option value="'.$report_id.'"'.$selected.'>'.dol_escape_htmltag($report_label).'</option>';
}
print '</select>';
print ' ';
print '<input type="submit" class="button button-add" name="button_refresh" value="'.$langs->trans("Refresh").'">';
print '</td>';
print '</tr>';
print '</table>';
print '</div>';
print '</form>';
print '</div>';
print '<div class="clearboth"></div>';
}
// Confirmation of the deletion of the line
if ($action == 'delete') {
print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id.($search_country_id > 0 ? '&search_country_id='.$search_country_id : ''), $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
@@ -532,15 +443,6 @@ if ($search_country_id > 0) {
$sql .= " (a.fk_country = ".((int) $search_country_id)." OR a.fk_country = 0)";
}
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT') && $search_report > 0) {
if (preg_match('/ WHERE /', $sql)) {
$sql .= " AND ";
} else {
$sql .= " WHERE ";
}
$sql .= " a.fk_report = ".((int) $search_report);
}
// If sort order is "country", we use country_code instead
if ($sortfield == 'country') {
$sortfield = 'country_code';
@@ -559,9 +461,6 @@ $param = '&id='.$id;
if ($search_country_id > 0) {
$param .= '&search_country_id='.urlencode((string) ($search_country_id));
}
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT') && $search_report > 0) {
$param .= '&search_report='.urlencode((string) ($search_report));
}
$paramwithsearch = $param;
if ($sortorder) {
$paramwithsearch .= '&sortorder='.urlencode($sortorder);
@@ -594,8 +493,8 @@ if ($tabname[$id]) {
print '<td></td>';
}
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries.
// 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";
@@ -990,18 +889,11 @@ if ($resql) {
print '<td>';
if (empty($obj->formula)) {
// Count number of accounts into group
if (getDolGlobalInt('ACCOUNTING_ENABLE_MULTI_REPORT')) {
// NEW SYSTEM: Multi report
$accountingcategory_temp = new AccountancyCategory($db);
$accountingcategory_temp->id = $obj->rowid;
$nbofaccountintogroup = $accountingcategory_temp->countAccountsInCategory();
} else {
// OLD SYSTEM: Only one report
$listofaccountintogroup = $accountingcategory->getCptsCat($obj->rowid);
$nbofaccountintogroup = count($listofaccountintogroup);
}
$nbofaccountintogroup = 0;
$listofaccountintogroup = $accountingcategory->getCptsCat($obj->rowid);
$nbofaccountintogroup = count($listofaccountintogroup);
print '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories.php?id='.$obj->rowid.'">';
print '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories.php?action=display&save_lastsearch_values=1&account_category='.$obj->rowid.'">';
print $langs->trans("NAccounts", $nbofaccountintogroup);
print '</a>';
} else {
@@ -1010,7 +902,7 @@ if ($resql) {
print '</td>';
// Active
print '<td class="center nowrap">';
print '<td class="center" class="nowrap">';
if ($canbedisabled) {
print '<a class="reposition" href="'.$url.'action='.urlencode($acts[$obj->active]).'&token='.newToken().'">'.$actl[$obj->active].'</a>';
} else {

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2017-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 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
@@ -194,7 +194,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
$ok = 0;
}
// In case of 'actionadd' and with valid parameters, add the line
// Si verif ok et action add, on ajoute la ligne
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0; // Initialise before if for static analysis
if ($tabrowid[$id]) {
@@ -251,7 +251,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// If check ok and action modify, we modify the line
// Si verif ok et action modify, on modifie la ligne
if ($ok && GETPOST('actionmodify', 'alpha')) {
if ($tabrowid[$id]) {
$rowidcol = $tabrowid[$id];
@@ -261,7 +261,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modify the field values
// Modifie valeur des champs
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
@@ -373,7 +373,7 @@ $titlepicto = 'title_accountancy';
print load_fiche_titre($titre, $linkback, $titlepicto);
// Generate a form to confirm the deletion of the row
// Confirmation de la suppression de la ligne
if ($action == 'delete') {
print $form->formconfirm($_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.$rowid.'&code='.$code.'&id='.$id, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_delete', '', 0, 1);
}
@@ -382,7 +382,7 @@ if ($action == 'delete') {
* Show a dictionary
*/
// Complete the search query with sort criteria
// Complete requete recherche valeurs avec critere de tri
$sql = $tabsql[$id];
$sql .= " WHERE a.entity = ".((int) $conf->entity);
@@ -409,8 +409,8 @@ if ($tabname[$id]) {
// Line for title
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries.
// 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";
@@ -522,8 +522,8 @@ if ($resql) {
// Title of lines
print '<tr class="liste_titre liste_titre_add">';
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries.
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$class = "left";
$sortable = 1;
$valuetoshow = '';

View File

@@ -552,12 +552,10 @@ if ($resql) {
if ($massaction == 'set_default_account') {
$formquestion = array();
$formquestion[] = array(
'type' => 'other',
$formquestion[] = array('type' => 'other',
'name' => 'set_default_account',
'label' => $langs->trans("AccountancyCode"),
'value' => $form->select_account('', 'default_account', 1, array(), 0, 0, 'maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone')
);
'value' => $form->select_account('', 'default_account', 1, array(), 0, 0, 'maxwidth200 maxwidthonsmartphone', 'cachewithshowemptyone'));
print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmPreselectAccount"), $langs->trans("ConfirmPreselectAccountQuestion", $nbselected), "confirm_set_default_account", $formquestion, 1, 0, 200, 500, 1);
}
@@ -664,7 +662,7 @@ if ($resql) {
while ($i < min($num, $limit)) {
$obj = $db->fetch_object($resql);
// Product ref as link
// Ref produit as link
$product_static->ref = $obj->ref;
$product_static->id = $obj->rowid;
$product_static->type = $obj->product_type;
@@ -909,48 +907,49 @@ if ($resql) {
}
print '</table>';
print '</div>';
?>
<script type="text/javascript">
jQuery(document).ready(function() {
function init_savebutton() {
console.log("We check if at least one line is checked")
atleastoneselected = 0;
jQuery(".checkforselect").each(function(index) {
/* console.log( index + ": " + $( this ).text() ); */
if ($(this).is(':checked')) atleastoneselected++;
});
print '<script type="text/javascript">
jQuery(document).ready(function() {
function init_savebutton()
{
console.log("We check if at least one line is checked")
if (atleastoneselected) jQuery("#changeaccount").removeAttr('disabled');
else jQuery("#changeaccount").attr('disabled', 'disabled');
if (atleastoneselected) jQuery("#changeaccount").attr('class', 'button');
else jQuery("#changeaccount").attr('class', 'button');
}
atleastoneselected=0;
jQuery(".checkforselect").each(function( index ) {
/* console.log( index + ": " + $( this ).text() ); */
if ($(this).is(\':checked\')) atleastoneselected++;
});
jQuery(".checkforselect").change(function() {
init_savebutton();
});
jQuery(".productforselect").change(function() {
console.log($(this).attr("id") + " " + $(this).val());
if (atleastoneselected) jQuery("#changeaccount").removeAttr(\'disabled\');
else jQuery("#changeaccount").attr(\'disabled\',\'disabled\');
if (atleastoneselected) jQuery("#changeaccount").attr(\'class\',\'button\');
else jQuery("#changeaccount").attr(\'class\',\'button\');
}
jQuery(".checkforselect").change(function() {
init_savebutton();
});
jQuery(".productforselect").change(function() {
console.log($(this).attr("id")+" "+$(this).val());
if ($(this).val() && $(this).val() != -1) {
$(".productforselect"+$(this).attr("id")).prop('checked', true);
$(".productforselect"+$(this).attr("id")).prop(\'checked\', true);
} else {
$(".productforselect"+$(this).attr("id")).prop('checked', false);
$(".productforselect"+$(this).attr("id")).prop(\'checked\', false);
}
init_savebutton();
});
init_savebutton();
});
init_savebutton();
init_savebutton();
jQuery("#search_current_account").keyup(function() {
if (jQuery("#search_current_account").val() != '') {
console.log("We set a value of account to search " + jQuery("#search_current_account").val() + ", so we disable the other search criteria on account");
jQuery("#search_current_account_valid").val(-1);
}
});
});
</script>
<?php
jQuery("#search_current_account").keyup(function() {
if (jQuery("#search_current_account").val() != \'\')
{
console.log("We set a value of account to search "+jQuery("#search_current_account").val()+", so we disable the other search criteria on account");
jQuery("#search_current_account_valid").val(-1);
}
});
});
</script>';
print '</form>';

View File

@@ -1,7 +1,6 @@
<?php
/* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
* 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
@@ -184,7 +183,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// In case of 'actionadd' and with valid parameters, add the line
// Si verif ok et action add, on ajoute la ligne
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -255,7 +254,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modify field values
// Modifie valeur des champs
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
@@ -428,8 +427,8 @@ if ($tabname[$id]) {
print '<td></td>';
}
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries.
// 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";

View File

@@ -1,651 +0,0 @@
<?php
/* Copyright (C) 2024 AWeerWolf
* Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* \file accountancy/admin/template/card.php
* \ingroup accountancy
* \brief Page to create/edit/view bookkeeping template
*/
// Load Dolibarr environment
require '../../../main.inc.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php';
require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeepingtemplate.class.php';
require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeepingtemplateline.class.php';
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "other"));
// Set needed objects
$accountingaccount = new AccountingAccount($db);
$formaccounting = new FormAccounting($db);
// Get parameters
$id = GETPOST('id', 'int');
$code = GETPOST('code', 'alpha');
$lineid = GETPOSTINT('lineid');
$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
$cancel = GETPOST('cancel', 'aZ09');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepingtemplatecard';
$backtopage = GETPOST('backtopage', 'alpha');
$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
// Initialize technical objects
$object = new BookkeepingTemplate($db);
$extrafields = new ExtraFields($db);
$diroutputmassaction = $conf->accounting->dir_output . '/temp/massgeneration/' . $user->id;
$hookmanager->initHooks(array($object->element . 'card', 'globalcard'));
// Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
// Initialize array of search criteria
$search_all = trim(GETPOST("search_all", 'alpha'));
$search = array();
foreach ($object->fields as $key => $val) {
if (GETPOST('search_' . $key, 'alpha')) {
$search[$key] = GETPOST('search_' . $key, 'alpha');
}
}
if (empty($action) && empty($id) && empty($code)) {
$action = 'view';
}
// Load object
include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php';
if ($id > 0 && empty($object->id)) {
dol_print_error($db, 'Failed to load object');
}
// Security check
$permissiontoread = $user->hasRight('accounting', 'chartofaccount');
$permissiontoadd = $user->hasRight('accounting', 'chartofaccount');
$permissiontodelete = $user->hasRight('accounting', 'chartofaccount');
$permissionnote = $user->hasRight('accounting', 'chartofaccount');
$permissiondellink = $user->hasRight('accounting', 'chartofaccount');
$upload_dir = $conf->accounting->multidir_output[isset($object->entity) ? $object->entity : 1];
if (!$permissiontoread) {
accessforbidden();
}
$form = new Form($db);
$formfile = new FormFile($db);
/*
* Actions
*/
$parameters = array();
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
if (empty($reshook)) {
$error = 0;
$backurlforlist = DOL_URL_ROOT . '/accountancy/admin/template/list.php';
if (empty($backtopage) || ($cancel && empty($id))) {
if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
$backtopage = $backurlforlist;
} else {
$backtopage = DOL_URL_ROOT . '/accountancy/admin/template/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__');
}
}
}
$triggermodname = 'ACCOUNTING_BOOKKEEPINGTEMPLATE_MODIFY';
// Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen
include DOL_DOCUMENT_ROOT . '/core/actions_addupdatedelete.inc.php';
// Actions when linking object each other
include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php';
// Actions when printing a doc from card
include DOL_DOCUMENT_ROOT . '/core/actions_printing.inc.php';
// Action to build doc
include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
// Actions to send emails
$triggersendname = 'ACCOUNTING_BOOKKEEPINGTEMPLATE_SENTBYMAIL';
$autocopy = 'MAIN_MAIL_AUTOCOPY_BOOKKEEPINGTEMPLATE_TO';
$trackid = 'bookkeepingtemplate' . $object->id;
include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
}
// Action to add a new line
if ($action == 'addline' && $permissiontoadd) {
$error = 0;
// Get line data from POST
$general_account = GETPOST('general_account', 'alphanohtml');
$subledger_account = GETPOST('subledger_account', 'alphanohtml');
if ($subledger_account == '-1') {
$subledger_account = null;
}
$subledger_label = GETPOST('subledger_label', 'alphanohtml');
$operation_label = GETPOST('operation_label', 'alphanohtml');
$debit = price2num(GETPOST('debit', 'alpha'));
$credit = price2num(GETPOST('credit', 'alpha'));
// Validation
if (((float) $debit != 0.0) && ((float) $credit != 0.0)) {
$error++;
setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors');
$action = 'edit';
}
if (empty($general_account) || $general_account == '-1') {
$error++;
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("AccountNumber")), null, 'errors');
$action = 'edit';
}
if (!$error) {
// Fetch account label
$accountingaccount->fetch(0, $general_account, 1);
$general_label = $accountingaccount->label;
// Create line object
$line = new BookkeepingTemplateLine($db);
$line->fk_transaction_template = $object->id;
$line->general_account = $general_account;
$line->general_label = $general_label;
$line->subledger_account = $subledger_account;
$line->subledger_label = $subledger_label;
$line->operation_label = $operation_label;
$line->debit = $debit;
$line->credit = $credit;
$result = $line->create($user, 0);
if ($result < 0) {
$error++;
setEventMessages($line->error, $line->errors, 'errors');
$action = 'edit';
} else {
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $object->id);
exit;
}
}
}
// Action to update a line
if ($action == 'updateline' && $permissiontoadd) {
$error = 0;
// Get line data from POST
$general_account = GETPOST('general_account', 'alphanohtml');
$subledger_account = GETPOST('subledger_account', 'alphanohtml');
if ($subledger_account == '-1') {
$subledger_account = null;
}
$subledger_label = GETPOST('subledger_label', 'alphanohtml');
$operation_label = GETPOST('operation_label', 'alphanohtml');
$debit = price2num(GETPOST('debit', 'alpha'));
$credit = price2num(GETPOST('credit', 'alpha'));
// Validation
if (((float) $debit != 0.0) && ((float) $credit != 0.0)) {
$error++;
setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors');
$action = 'editline';
}
if (empty($general_account) || $general_account == '-1') {
$error++;
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("AccountNumber")), null, 'errors');
$action = 'editline';
}
if (!$error) {
// Fetch account label
$accountingaccount->fetch(0, $general_account, 1);
$general_label = $accountingaccount->label;
// Load and update line
$line = new BookkeepingTemplateLine($db);
$result = $line->fetch($lineid);
if ($result > 0) {
$line->general_account = $general_account;
$line->general_label = $general_label;
$line->subledger_account = $subledger_account;
$line->subledger_label = $subledger_label;
$line->operation_label = $operation_label;
$line->debit = $debit;
$line->credit = $credit;
$result = $line->update($user, 0);
if ($result < 0) {
$error++;
setEventMessages($line->error, $line->errors, 'errors');
$action = 'editline';
} else {
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $object->id);
exit;
}
} else {
$error++;
setEventMessages($line->error, $line->errors, 'errors');
}
}
}
// Action to delete a line
if ($action == 'confirm_deleteline' && $confirm == 'yes' && $permissiontodelete) {
$result = $object->deleteLine($user, $lineid);
if ($result > 0) {
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $object->id);
exit;
} else {
setEventMessages($object->error, $object->errors, 'errors');
}
}
/*
* View
*/
$title = $langs->trans('BookkeepingTemplate') . " - " . $langs->trans('Card');
if ($action == 'create') {
$title = $langs->trans("NewBookkeepingTemplate");
}
$help_url = '';
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin-template-card');
// Update fields properties in realtime
if (!empty($conf->use_javascript_ajax)) {
print "\n" . '<script type="text/javascript">';
print '$(document).ready(function () {
function toggleSubledger() {
var isCentral = $("#accountingaccount_number option:selected").data("centralized");
console.log("the selected general ledger account is centralised?", isCentral);
if (isCentral) {
$("#subledger_account, #subledger_label").prop("disabled", false);
} else {
$("#subledger_account, #subledger_label").prop("disabled", true);
}
}
toggleSubledger();
$("#accountingaccount_number").on("change", toggleSubledger);
$("#accountingaccount_number").on("select2:select", toggleSubledger);
';
print ' });' . "\n";
print ' </script>' . "\n";
}
// Part to create
if ($action == 'create') {
if (empty($permissiontoadd)) {
accessforbidden('NotEnoughPermissions', 0, 1);
}
print load_fiche_titre($title, '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';
print '<input type="hidden" name="token" value="' . newToken() . '">';
print '<input type="hidden" name="action" value="add">';
if ($backtopage) {
print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
}
if ($backtopageforcancel) {
print '<input type="hidden" name="backtopageforcancel" value="' . $backtopageforcancel . '">';
}
print dol_get_fiche_head(array(), '');
print '<table class="border centpercent tableforfieldcreate">' . "\n";
// Common attributes
include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_add.tpl.php';
// Other attributes
include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_add.tpl.php';
print '</table>' . "\n";
print dol_get_fiche_end();
print $form->buttonsSaveCancel("Create");
print '</form>';
dol_set_focus('input[name="code"]');
}
// Part to edit record
if (($id || $code) && $action == 'edit') {
print load_fiche_titre($langs->trans("BookkeepingTemplate"), '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';
print '<input type="hidden" name="token" value="' . newToken() . '">';
print '<input type="hidden" name="action" value="update">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
if ($backtopage) {
print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
}
if ($backtopageforcancel) {
print '<input type="hidden" name="backtopageforcancel" value="' . $backtopageforcancel . '">';
}
print dol_get_fiche_head();
print '<table class="border centpercent tableforfieldedit">' . "\n";
// Common attributes
include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_edit.tpl.php';
// Other attributes
include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_edit.tpl.php';
print '</table>';
print dol_get_fiche_end();
print $form->buttonsSaveCancel();
print '</form>';
}
// Part to show record
if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
$head = accountingTransactionTemplatePrepareHead($object);
print dol_get_fiche_head($head, 'card', $langs->trans("BookkeepingTemplate"), -1, $object->picto, 0, '', '', 0, '', 1);
$formconfirm = '';
// Confirmation to delete template
if ($action == 'delete') {
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteBookkeepingTemplate'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1);
}
// Confirmation to delete line
if ($action == 'deleteline') {
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
}
// Clone confirmation
if ($action == 'clone') {
// Create an array for form
$formquestion = array();
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->code), 'confirm_clone', $formquestion, 'yes', 1);
}
// Call Hook formConfirm
$parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
if (empty($reshook)) {
$formconfirm .= $hookmanager->resPrint;
} elseif ($reshook > 0) {
$formconfirm = $hookmanager->resPrint;
}
// Print form confirm
print $formconfirm;
// Object card
$linkback = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/template/list.php?restore_lastsearch_values=1">' . $langs->trans("BackToList") . '</a>';
$morehtmlref = '<div class="refidno">';
$morehtmlref .= '</div>';
dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'code', $morehtmlref);
print '<div class="fichecenter">';
print '<div class="fichehalfleft">';
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">' . "\n";
// Common attributes
$keyforbreak = '';
include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php';
// Other attributes
include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
print '</table>';
print '</div>';
print '</div>';
print '<div class="clearboth"></div>';
print dol_get_fiche_end();
// Buttons for actions
if ($action != 'presend' && $action != 'editline' && $action != 'addline') {
print '<div class="tabsAction">' . "\n";
$parameters = array();
$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
if (empty($reshook)) {
// Modify
if ($permissiontoadd) {
print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoadd);
}
// Clone
if ($permissiontoadd) {
print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=clone&token=' . newToken(), '', $permissiontoadd);
}
// Delete
print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=delete&token=' . newToken(), '', $permissiontodelete);
}
print '</div>' . "\n";
}
// Lines section
print '<div class="div-table-responsive-no-min">';
if (!empty($object->table_element_line)) {
// Show object lines
$result = $object->getLinesArray();
print '<form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '' : '#line_' . GETPOST('lineid', 'int')) . '" method="POST">';
print '<input type="hidden" name="token" value="' . newToken() . '">';
print '<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">';
print '<input type="hidden" name="mode" value="">';
print '<input type="hidden" name="page_y" value="">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
if (!empty($conf->use_javascript_ajax) && $object->status == 0) {
// Define required variables for ajaxrow.tpl.php
$fk_element = 'fk_transaction_template';
$table_element_line = $object->table_element_line;
include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
}
print '<div class="div-table-responsive-no-min">';
print '<table id="tablelines" class="noborder noshadow centpercent">';
// Show header
print '<tr class="liste_titre">';
print_liste_field_titre("AccountAccountingShort");
print_liste_field_titre("SubledgerAccount");
print_liste_field_titre("LabelOperation");
print_liste_field_titre("AccountingDebit", "", "", "", "", 'class="right"');
print_liste_field_titre("AccountingCredit", "", "", "", "", 'class="right"');
print_liste_field_titre("Action", "", "", "", "", 'width="60"', "", "", 'center ');
print "</tr>\n";
$i = 0;
// Show existing lines
foreach ($object->lines as $line) {
// Line in view mode
if ($action != 'editline' || GETPOST('lineid', 'int') != $line->id) {
print '<tr class="oddeven" id="row-' . $line->id . '">';
print '<!-- td columns in display mode -->';
$resultfetch = $accountingaccount->fetch(0, $line->general_account, true);
print '<td>';
if ($resultfetch > 0) {
print $accountingaccount->getNomUrl(0, 1, 1, '', 0);
} else {
print dol_escape_htmltag($line->general_account).' <span class="warning">('.$langs->trans("AccountRemovedFromCurrentChartOfAccount").')</span>';
}
print '</td>';
print '<td>'.length_accounta($line->subledger_account ?? '');
if (!empty($line->subledger_label)) {
print ' - <span class="opacitymedium">'.dol_escape_htmltag($line->subledger_label).'</span>';
}
print '</td>';
print '<td>' . ($line->operation_label ? dol_escape_htmltag($line->operation_label) : '') . '</td>';
print '<td class="right">' . ($line->debit ? price($line->debit) : '') . '</td>';
print '<td class="right">' . ($line->credit ? price($line->credit) : '') . '</td>';
// Edit link
print '<td class="center">';
if ($permissiontoadd) {
print '<a class="editfielda reposition" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=editline&token=' . newToken() . '&lineid=' . $line->id . '#line_' . $line->id . '">';
print img_edit('', 0, 'class="marginrightonly"');
print '</a> &nbsp;';
}
// Delete link
if ($permissiontodelete) {
print '<a class="reposition" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=deleteline&token=' . newToken() . '&lineid=' . $line->id . '">';
print img_delete();
print '</a>';
}
print '</td>';
print '</tr>';
}
// Line in edit mode
if ($action == 'editline' && GETPOST('lineid', 'int') == $line->id) {
print '<tr class="oddeven" data-lineid="'.((int) $line->id).'">';
print '<input type="hidden" name="lineid" value="' . GETPOST('lineid', 'int') . '">';
// Account number
print '<td>';
print $formaccounting->select_account((GETPOSTISSET("accountingaccount_number") ? GETPOST("accountingaccount_number", "alpha") : $line->general_account), 'general_account', 1, array(), 1, 1, 'minwidth200 maxwidth500');
print '</td>';
// Subledger account
print '<td>';
// TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because:
// It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases.
// Also, it is not possible to use a value that is not in the list.
// Also, the label is not automatically filled when a value is selected.
if (getDolGlobalString('ACCOUNTANCY_COMBO_FOR_AUX')) {
print $formaccounting->select_auxaccount((GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account), 'subledger_account', 1, 'maxwidth250', '', 'subledger_label');
} else {
print '<input type="text" class="maxwidth150" name="subledger_account" value="'.(GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'">';
}
// Add also input for subledger label
print '<br><input type="text" class="maxwidth150" name="subledger_label" value="'.(GETPOSTISSET("subledger_label") ? GETPOST("subledger_label", "alpha") : $line->subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">';
print '</td>';
// Operation label
print '<td>';
print '<input type="text" class="minwidth200" name="operation_label" value="'.(GETPOSTISSET("operation_label") ? GETPOST("operation_label", "alpha") : $line->operation_label).'">';
print '</td>';
// Debit
print '<td class="right">';
print '<input type="text" name="debit" class="flat right maxwidth75" value="' . ($line->debit ? price($line->debit) : '') . '">';
print '</td>';
// Credit
print '<td class="right">';
print '<input type="text" name="credit" class="flat right maxwidth75" value="' . ($line->credit ? price($line->credit) : '') . '">';
print '</td>';
// Save button
print '<td class="center" colspan="2">';
print '<input type="submit" class="button buttongen marginbottomonly button-save" name="save" value="' . $langs->trans("Save") . '">';
print '<br>';
print '<input type="submit" class="button buttongen marginbottomonly button-cancel" name="cancel" value="' . $langs->trans("Cancel") . '">';
print '</td>';
print '</tr>';
}
$i++;
}
// Form to add new line
if ($action != 'editline' && $permissiontoadd) {
print '<tr class="liste_titre nodrag nodrop">';
print '<td>';
print $formaccounting->select_account('', 'general_account', 1, [], 1, 1, 'maxwidth300');
print '</td>';
print '<td>';
// TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because:
// It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases.
// Also, it is not possible to use a value that is not in the list.
// Also, the label is not automatically filled when a value is selected.
if (getDolGlobalString('ACCOUNTANCY_COMBO_FOR_AUX')) {
print $formaccounting->select_auxaccount('', 'subledger_account', 1, 'maxwidth250', '', 'subledger_label');
} else {
print '<input type="text" class="maxwidth150" name="new_subledger_account" value="" placeholder="' . dol_escape_htmltag($langs->trans("SubledgerAccount")) . '">';
}
print '<br><input type="text" class="maxwidth150" name="new_subledger_label" value="" placeholder="' . dol_escape_htmltag($langs->trans("SubledgerAccountLabel")) . '">';
print '</td>';
print '<td><input type="text" name="operation_label" class="flat minwidth150"></td>';
print '<td class="right"><input type="text" name="debit" class="flat right maxwidth75"></td>';
print '<td class="right"><input type="text" name="credit" class="flat right maxwidth75"></td>';
print '<td class="center" colspan="2"><input type="submit" class="button buttongen marginbottomonly" name="addline" value="' . $langs->trans("Add") . '"></td>';
print '</tr>';
}
print '</table>';
print '</div>';
print '</form>';
}
print '</div>';
}
// End of page
llxFooter();
$db->close();

View File

@@ -1,701 +0,0 @@
<?php
/* Copyright (C) 2024 AWeerWolf
* Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* \file accountancy/admin/template/list.php
* \ingroup accountancy
* \brief List page for bookkeeping templates
*/
// Load Dolibarr environment
require '../../../main.inc.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplate.class.php';
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "other"));
// Get parameters
$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view';
$massaction = GETPOST('massaction', 'alpha');
$show_files = GETPOST('show_files', 'int');
$confirm = GETPOST('confirm', 'alpha');
$cancel = GETPOST('cancel', 'alpha');
$toselect = GETPOST('toselect', 'array');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepingtemplatelist';
$backtopage = GETPOST('backtopage', 'alpha');
$optioncss = GETPOST('optioncss', 'aZ');
$mode = GETPOST('mode', 'aZ');
// Load variable for pagination
$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
$sortfield = GETPOST('sortfield', 'aZ09comma');
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
if (empty($page) || $page == -1) {
$page = 0;
} // If $page is not defined, or '' or -1
$offset = $limit * $page;
$pageprev = $page - 1;
$pagenext = $page + 1;
// Initialize technical objects
$object = new BookkeepingTemplate($db);
$extrafields = new ExtraFields($db);
$diroutputmassaction = $conf->accounting->dir_output.'/temp/massgeneration/'.$user->id;
$hookmanager->initHooks(array($contextpage));
// Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element);
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
// Default sort order (if not yet defined by previous GETPOST)
if (!$sortfield) {
reset($object->fields);
$sortfield = "t.".key($object->fields);
}
if (!$sortorder) {
$sortorder = "ASC";
}
// Initialize array of search criteria
$search_all = trim(GETPOST('search_all', 'alphanohtml'));
$search = array();
foreach ($object->fields as $key => $val) {
if (GETPOST('search_'.$key, 'alpha') !== '') {
$search[$key] = GETPOST('search_'.$key, 'alpha');
}
if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
$search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOSTINT('search_'.$key.'_dtstartmonth'), GETPOSTINT('search_'.$key.'_dtstartday'), GETPOSTINT('search_'.$key.'_dtstartyear'));
$search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOSTINT('search_'.$key.'_dtendmonth'), GETPOSTINT('search_'.$key.'_dtendday'), GETPOSTINT('search_'.$key.'_dtendyear'));
}
}
// List of fields to search into when doing a "search in all"
$fieldstosearchall = array();
foreach ($object->fields as $key => $val) {
if (!empty($val['searchall'])) {
$fieldstosearchall['t.'.$key] = $val['label'];
}
}
// Definition of array of fields for columns
$arrayfields = array();
foreach ($object->fields as $key => $val) {
// If $val['visible']==0, then we never show the field
if (!empty($val['visible'])) {
$visible = (int) dol_eval($val['visible'], 1);
$arrayfields['t.'.$key] = array(
'label'=>$val['label'],
'checked'=>(($visible < 0) ? 0 : 1),
'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)),
'position'=>$val['position'],
'help'=> isset($val['help']) ? $val['help'] : ''
);
}
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
$object->fields = dol_sort_array($object->fields, 'position');
$arrayfields = dol_sort_array($arrayfields, 'position');
// Security check
$permissiontoread = $user->hasRight('accounting', 'chartofaccount');
$permissiontoadd = $user->hasRight('accounting', 'chartofaccount');
$permissiontodelete = $user->hasRight('accounting', 'chartofaccount');
if (!$permissiontoread) {
accessforbidden();
}
/*
* Actions
*/
if (GETPOST('cancel', 'alpha')) {
$action = 'list';
$massaction = '';
}
if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
$massaction = '';
}
$parameters = array();
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
if (empty($reshook)) {
// Selection of new fields
include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
// Purge search criteria
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
foreach ($object->fields as $key => $val) {
$search[$key] = '';
if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
$search[$key.'_dtstart'] = '';
$search[$key.'_dtend'] = '';
}
}
$toselect = array();
$search_array_options = array();
}
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
|| GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
$massaction = '';
}
// Mass actions
$objectclass = 'BookkeepingTemplate';
$objectlabel = 'BookkeepingTemplate';
$uploaddir = $conf->accounting->dir_output;
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
/*
* View
*/
$form = new Form($db);
$now = dol_now();
$title = $langs->trans("BookkeepingTemplates");
$help_url = '';
$morejs = array();
$morecss = array();
// Build and execute select
$sql = 'SELECT ';
$sql .= $object->getFieldList('t');
// Add fields from extrafields
if (!empty($extrafields->attributes[$object->table_element]['label'])) {
foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
}
}
// Add fields from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action);
$sql .= $hookmanager->resPrint;
$sql = preg_replace('/,\s*$/', '', $sql);
$sqlfields = $sql;
$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
}
// Add table from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action);
$sql .= $hookmanager->resPrint;
if ($object->ismultientitymanaged == 1) {
$sql .= " WHERE t.entity IN (".getEntity('accounting').")";
} else {
$sql .= " WHERE 1 = 1";
}
foreach ($search as $key => $val) {
if (array_key_exists($key, $object->fields)) {
if ($key == 'status' && $search[$key] == -1) {
continue;
}
$mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
if ($search[$key] == '-1') {
$search[$key] = '';
$modesearch = 2;
} elseif ($search[$key] === '0' && (!isset($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval']))) {
$search[$key] = '';
$modesearch = 2;
}
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}
}
}
if ($search_all) {
$sql .= natural_search(array_keys($fieldstosearchall), $search_all);
}
// Add where from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
// Add where from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action);
$sql .= $hookmanager->resPrint;
// Count total nb of records
$nbtotalofrecords = '';
if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
$sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
$sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
$resql = $db->query($sqlforcount);
if ($resql) {
$objforcount = $db->fetch_object($resql);
$nbtotalofrecords = $objforcount->nbtotalofrecords;
} else {
dol_print_error($db);
}
if (($page * $limit) > $nbtotalofrecords) {
$page = 0;
$offset = 0;
}
$db->free($resql);
}
// Complete request and execute it with limit
$sql .= $db->order($sortfield, $sortorder);
if ($limit) {
$sql .= $db->plimit($limit + 1, $offset);
}
$resql = $db->query($sql);
if (!$resql) {
dol_print_error($db);
exit;
}
$num = $db->num_rows($resql);
// Direct jump if only one record found
if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
$obj = $db->fetch_object($resql);
$id = $obj->rowid;
header("Location: ".DOL_URL_ROOT.'/accountancy/admin/template/card.php?id='.((int) $id));
exit;
}
// Output page
llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist');
$arrayofselected = is_array($toselect) ? $toselect : array();
$param = '';
if (!empty($mode)) {
$param .= '&mode='.urlencode($mode);
}
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
$param .= '&contextpage='.urlencode($contextpage);
}
if ($limit > 0 && $limit != $conf->liste_limit) {
$param .= '&limit='.((int) $limit);
}
if ($optioncss != '') {
$param .= '&optioncss='.urlencode($optioncss);
}
foreach ($search as $key => $val) {
if (is_array($search[$key])) {
foreach ($search[$key] as $skey) {
if ($skey != '') {
$param .= '&search_'.$key.'[]='.urlencode($skey);
}
}
} elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
$param .= '&search_'.$key.'month='.((int) GETPOST('search_'.$key.'month', 'int'));
$param .= '&search_'.$key.'day='.((int) GETPOST('search_'.$key.'day', 'int'));
$param .= '&search_'.$key.'year='.((int) GETPOST('search_'.$key.'year', 'int'));
} elseif ($search[$key] != '') {
$param .= '&search_'.$key.'='.urlencode($search[$key]);
}
}
// Add $param from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
// Add $param from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action);
$param .= $hookmanager->resPrint;
// List of mass actions available
$arrayofmassactions = array();
if (!empty($permissiontodelete)) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
}
if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
$arrayofmassactions = array();
}
$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
if ($optioncss != '') {
print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
}
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
print '<input type="hidden" name="action" value="list">';
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
print '<input type="hidden" name="mode" value="'.$mode.'">';
$newcardbutton = '';
$newcardbutton .= dolGetButtonTitle($langs->trans('NewBookkeepingTemplate'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/accountancy/admin/template/card.php?action=create', '', $permissiontoadd);
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
// Add code for pre mass action (confirmation or email presend form)
$topicmail = "SendBookkeepingTemplateRef";
$modelmail = "bookkeepingtemplate";
$objecttmp = new BookkeepingTemplate($db);
$trackid = 'bookkeepingtemplate'.$object->id;
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
if ($search_all) {
$setupstring = '';
foreach ($fieldstosearchall as $key => $val) {
$fieldstosearchall[$key] = $langs->trans($val);
$setupstring .= $key."=".$val.";";
}
print '<!-- Search done like if BOOKKEEPINGTEMPLATE_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>'."\n";
}
$moreforfilter = '';
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action);
if (empty($reshook)) {
$moreforfilter .= $hookmanager->resPrint;
} else {
$moreforfilter = $hookmanager->resPrint;
}
if (!empty($moreforfilter)) {
print '<div class="liste_titre liste_titre_bydiv centpercent">';
print $moreforfilter;
print '</div>';
}
$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : '');
$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
print '<div class="div-table-responsive">';
print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
// Fields title search
print '<tr class="liste_titre_filter">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre maxwidthsearch">';
$searchpicto = $form->showFilterButtons('left');
print $searchpicto;
print '</td>';
}
foreach ($object->fields as $key => $val) {
$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
if ($key == 'status') {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
} elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
} elseif (in_array($val['type'], array('timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
$cssforfield .= ($cssforfield ? ' ' : '').'right';
}
if (!empty($arrayfields['t.'.$key]['checked'])) {
print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
} elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
} elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
print '<div class="nowrap">';
print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
print '</div>';
print '<div class="nowrap">';
print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
print '</div>';
} elseif ($key == 'lang') {
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
$formadmin = new FormAdmin($db);
print $formadmin->select_language($search[$key], 'search_lang', 0, [], 1, 0, 0, 'minwidth150 maxwidth200', 2);
} else {
print '<input type="text" class="flat maxwidth'.($val['type'] == 'integer' ? '50' : '75').'" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
}
print '</td>';
}
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
// Fields from hook
$parameters = array('arrayfields'=>$arrayfields);
$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action);
print $hookmanager->resPrint;
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre maxwidthsearch">';
$searchpicto = $form->showFilterButtons();
print $searchpicto;
print '</td>';
}
print '</tr>'."\n";
$totalarray = array();
$totalarray['nbfield'] = 0;
// Fields title label
print '<tr class="liste_titre">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
$totalarray['nbfield']++;
}
foreach ($object->fields as $key => $val) {
$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
if ($key == 'status') {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
} elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
} elseif (in_array($val['type'], array('timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
} elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
$cssforfield .= ($cssforfield ? ' ' : '').'right';
}
$cssforfield = preg_replace('/small\s*/', '', $cssforfield);
if (!empty($arrayfields['t.'.$key]['checked'])) {
print_liste_field_titre($arrayfields['t.'.$key]['label'], $_SERVER["PHP_SELF"], 't.'.$key, '', $param, '', $sortfield, $sortorder, $cssforfield.' ');
$totalarray['nbfield']++;
}
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
// Hook fields
$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action);
print $hookmanager->resPrint;
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
$totalarray['nbfield']++;
}
print '</tr>'."\n";
// Loop on record
$i = 0;
$savnbfield = $totalarray['nbfield'];
$totalarray = array();
$totalarray['nbfield'] = 0;
$imaxinloop = ($limit ? min($num, $limit) : $num);
while ($i < $imaxinloop) {
$obj = $db->fetch_object($resql);
if (empty($obj)) {
break;
}
$object->setVarsFromFetchObj($obj);
// Show here line of result
$j = 0;
print '<tr data-rowid="'.$object->id.'" class="oddeven">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="nowrap center">';
if ($massactionbutton || $massaction) {
$selected = 0;
if (in_array($object->id, $arrayofselected)) {
$selected = 1;
}
print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
foreach ($object->fields as $key => $val) {
$cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
} elseif ($key == 'status') {
$cssforfield .= ($cssforfield ? ' ' : '').'center';
}
if (in_array($val['type'], array('timestamp'))) {
$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
} elseif ($key == 'ref') {
$cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
}
if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) {
$cssforfield .= ($cssforfield ? ' ' : '').'right';
}
if (!empty($arrayfields['t.'.$key]['checked'])) {
print '<td'.($cssforfield ? ' class="'.$cssforfield.'"' : '').'>';
if ($key == 'status') {
print $object->getLibStatut(5);
} elseif ($key == 'rowid') {
print $object->showOutputField($val, $key, (string) $object->id, '');
} elseif ($key == 'code') {
// Display code with link to card using getNomUrl
print $object->getNomUrl(1);
} else {
print $object->showOutputField($val, $key, $object->$key, '');
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
if (!$i) {
$totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
}
if (!isset($totalarray['val'])) {
$totalarray['val'] = array();
}
if (!isset($totalarray['val']['t.'.$key])) {
$totalarray['val']['t.'.$key] = 0;
}
$totalarray['val']['t.'.$key] += $object->$key;
}
}
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
// Fields from hook
$parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action);
print $hookmanager->resPrint;
// Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="nowrap center">';
if ($massactionbutton || $massaction) {
$selected = 0;
if (in_array($object->id, $arrayofselected)) {
$selected = 1;
}
print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
print '</tr>'."\n";
$i++;
}
// Show total line
include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
// If no record found
if ($num == 0) {
$colspan = 1;
foreach ($arrayfields as $key => $val) {
if (!empty($val['checked'])) {
$colspan++;
}
}
print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
$db->free($resql);
$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action);
print $hookmanager->resPrint;
print '</table>'."\n";
print '</div>'."\n";
print '</form>'."\n";
if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
$hidegeneratedfilelistifempty = 1;
if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
$hidegeneratedfilelistifempty = 0;
}
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
$formfile = new FormFile($db);
// Show list of available documents
$urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
$urlsource .= str_replace('&amp;', '&', $param);
$filedir = $diroutputmassaction;
$genallowed = $permissiontoread;
$delallowed = $permissiontoadd;
print $formfile->showdocuments('massfilesarea_accounting', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
}
// End of page
llxFooter();
$db->close();

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2013-2017 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2017 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
@@ -34,12 +34,9 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplate.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplateline.class.php';
/**
* @var Conf $conf
@@ -315,79 +312,14 @@ if (empty($reshook)) {
$action = 'create';
} else {
// Transaction created successfully
$piece_num = $object->piece_num;
$reshook = $hookmanager->executeHooks('afterCreateBookkeeping', $parameters, $object, $action);
// Check if a template was selected
$template_id = GETPOSTINT('template_id');
if ($template_id > 0) {
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplate.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplateline.class.php';
$template = new BookkeepingTemplate($db);
$result_template = $template->fetch($template_id);
if ($result_template > 0 && !empty($template->lines)) {
$db->begin();
$error_template = 0;
foreach ($template->lines as $templateline) {
$bookkeeping = new BookKeeping($db);
// Set common fields from the form
$bookkeeping->doc_date = $date_start;
$bookkeeping->doc_type = GETPOST('doctype', 'alpha');
$bookkeeping->piece_num = $piece_num;
$bookkeeping->doc_ref = GETPOST('docref', 'alpha');
$bookkeeping->code_journal = $journal_code;
$bookkeeping->journal_label = $journal_label;
$bookkeeping->fk_doc = 0;
$bookkeeping->fk_docdet = 0;
$bookkeeping->ref = GETPOST('ref', 'alpha') ? GETPOST('ref', 'alpha') : $object->ref;
// Set fields from template line
$bookkeeping->numero_compte = $templateline->general_account;
$bookkeeping->label_compte = $templateline->general_label;
$bookkeeping->subledger_account = $templateline->subledger_account;
$bookkeeping->subledger_label = $templateline->subledger_label;
$bookkeeping->label_operation = $templateline->operation_label;
$bookkeeping->debit = (float) $templateline->debit;
$bookkeeping->credit = (float) $templateline->credit;
// Backward compatibility
if ((float) $bookkeeping->debit != 0.0) {
$bookkeeping->montant = $bookkeeping->debit;
$bookkeeping->amount = $bookkeeping->debit;
$bookkeeping->sens = 'D';
}
if ((float) $bookkeeping->credit != 0.0) {
$bookkeeping->montant = $bookkeeping->credit;
$bookkeeping->amount = $bookkeeping->credit;
$bookkeeping->sens = 'C';
}
$result_line = $bookkeeping->createStd($user, 0, '_tmp');
if ($result_line < 0) {
$error_template++;
setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
break;
}
}
if (!$error_template) {
$db->commit();
setEventMessages($langs->trans('TemplateLinesLoaded', count($template->lines)), null, 'mesgs');
} else {
$db->rollback();
}
}
if ($mode != '_tmp') {
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
}
// Redirect to the transaction
header("Location: ".$_SERVER["PHP_SELF"]."?piece_num=".$piece_num."&mode=_tmp");
exit;
$action = '';
$id = $object->id;
$piece_num = (int) $object->piece_num;
}
}
}
@@ -637,47 +569,15 @@ if ($action == 'create') {
} else {
print '<span class="opacitymedium">'.$langs->trans("Automatic").'</span>';
}
print '</td>';
// Template
print '<tr>';
print '<td>'.$langs->trans("BookkeepingTemplate").'</td>';
print '<td>';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeepingtemplate.class.php';
$sql = "SELECT rowid, code, label";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_transaction_template";
$sql .= " WHERE entity IN (".getEntity('accounting').")";
$sql .= " ORDER BY code ASC";
$resql = $db->query($sql);
$templates = array();
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
$templates[$obj->rowid] = $obj->code.' - '.$obj->label;
$i++;
}
$db->free($resql);
}
if (count($templates) > 0) {
print '<select class="flat minwidth300" name="template_id" id="template_id">';
print '<option value=""></option>';
foreach ($templates as $key => $label) {
print '<option value="'.$key.'">'.dol_escape_htmltag($label).'</option>';
}
print '</select>';
} else {
print '<span class="opacitymedium">'.$langs->trans("NoTemplateAvailable").'</span>';
}
print '</td>';
print '</tr>';
/*
print '<tr>';
print '<td>' . $langs->trans("Doctype") . '</td>';
print '<td><input type="text" class="minwidth200 name="doc_type" value=""/></td>';
print '</tr>';
*/
$reshookAddLine = $hookmanager->executeHooks('bookkeepingAddLine', $parameters, $object, $action);
print '</table>';
@@ -838,38 +738,7 @@ if ($action == 'create') {
print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
print '</form>';
} else {
// Get information of an element
if ($object->doc_type === 'customer_invoice' && !empty($object->fk_doc)) {
$invoicestatic = new Facture($db);
$result = $invoicestatic->fetch($object->fk_doc);
if ($result > 0) {
$label_element = $invoicestatic->getNomUrl(1);
} else {
$label_element = $object->doc_ref;
}
} elseif ($object->doc_type === 'supplier_invoice' && !empty($object->fk_doc)) {
$supplierinvoicestatic = new FactureFournisseur($db);
$result = $supplierinvoicestatic->fetch($object->fk_doc);
if ($result > 0) {
$label_element = $supplierinvoicestatic->getNomUrl(1);
} else {
$label_element = $object->doc_ref;
}
} elseif ($object->doc_type === 'expense_report' && !empty($object->fk_doc)) {
$expensereportstatic = new ExpenseReport($db);
$result = $expensereportstatic->fetch($object->fk_doc);
if ($result > 0) {
$label_element = $expensereportstatic->getNomUrl(1);
} else {
$label_element = $object->doc_ref;
}
} else {
$label_element = $object->doc_ref;
}
print $label_element;
print $object->doc_ref;
}
print '</td>';
print '</tr>';
@@ -935,13 +804,7 @@ if ($action == 'create') {
print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
print '</form>';
} else {
// Get information of a journal
$accountingjournalstatic = new AccountingJournal($db);
$accountingjournalstatic->fetch(0, $object->code_journal);
$journal = $accountingjournalstatic->code;
$journal_label = $accountingjournalstatic->label;
print $accountingjournalstatic->getNomUrl(1, 1, 1);
print $object->code_journal;
}
print '</td>';
print '</tr>';

View File

@@ -846,30 +846,50 @@ if ($action == 'export_file') {
}
// add documents in an archive for some accountancy export format
if (getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS
|| getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_FEC
|| getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_FEC2
) {
$except = array();
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_INVOICE_SOURCE_FILE')) {
$except[] = $langs->trans('Invoice');
}
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_EXPENSEREPORT_SOURCE_FILE')) {
$except[] = $langs->trans('ExpenseReport');
}
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_SUPPLIERINVOICE_SOURCE_FILE')) {
$except[] = $langs->trans('SupplierInvoice');
}
$exportTypesWithDocs = array(
AccountancyExport::$EXPORT_TYPE_QUADRATUS,
AccountancyExport::$EXPORT_TYPE_FEC,
AccountancyExport::$EXPORT_TYPE_FEC2
);
$form_question['notifiedexportfull'] = array(
'name' => 'notifiedexportfull',
'type' => 'checkbox',
'label' => $langs->trans('NotifiedExportFull').(empty($except) ? '' : ' <spanc class="opacitymedium">('.$langs->trans("except").' '.implode(', ', $except).')</span>'),
'value' => 'false',
);
$except = array();
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_INVOICE_SOURCE_FILE')) {
$except[] = $langs->trans('Invoice');
}
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_EXPENSEREPORT_SOURCE_FILE')) {
$except[] = $langs->trans('ExpenseReport');
}
if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_SUPPLIERINVOICE_SOURCE_FILE')) {
$except[] = $langs->trans('SupplierInvoice');
}
$form_question['notifiedexportfull'] = array(
'name' => 'notifiedexportfull',
'type' => 'checkbox',
'label' => $langs->trans('NotifiedExportFull').(empty($except) ? '' : ' <spanc class="opacitymedium">('.$langs->trans("except").' '.implode(', ', $except).')</span>'),
'value' => 'false',
);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").'...', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 500, 700);
$formconfirm .= '<script>
jQuery(document).ready(function() {
const exportTypesWithDocs = ['.implode(',', $exportTypesWithDocs).'];
const $formatExport = jQuery("#formatexport");
function toggleExportFull() {
const $checkbox = jQuery("#notifiedexportfull");
const show = exportTypesWithDocs.indexOf(parseInt($formatExport.val())) !== -1;
$checkbox.closest(".tagtr").toggle(show);
if (!show) {
$checkbox.prop("checked", false); // remove checked if hidden
}
}
$formatExport.on("change", toggleExportFull);
toggleExportFull();
});
</script>';
}
// Print form confirm

View File

@@ -750,7 +750,8 @@ if (!empty($socid)) {
print '</div>';
print dol_get_fiche_end();
print info_admin($langs->trans("WarningThisPageContainsOnlyEntriesTransferredInAccounting")).'';
print info_admin($langs->trans("WarningThisPageContainsOnlyEntriesTransferredInAccounting"));
print '<br>';
// Choice of mode (customer / supplier)
if (!empty($conf->dol_use_jmobile)) {

View File

@@ -1,8 +1,8 @@
<?php
/* Copyright (C) 2016 Jamal Elbaz <jamelbaz@gmail.pro>
* Copyright (C) 2016-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2016 Jamal Elbaz <jamelbaz@gmail.pro>
* Copyright (C) 2016-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* 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
* it under the terms of the GNU General Public License as published by
@@ -906,326 +906,4 @@ class AccountancyCategory // extends CommonObject
return -1;
}
}
// ====================================================================
// MULTI REPORT METHODS (New system with llx_accounting_category_account)
// Requires constant ACCOUNTING_ENABLE_MULTI_REPORT
// ====================================================================
/**
* Link an accounting account to this category (multi-report system)
*
* @param int $fkAccountingAccount ID of the accounting account to link
* @return int<-1,1> <0 if KO, 0 if already exists, >0 if OK
*/
public function addAccountToCategory($fkAccountingAccount)
{
// Check if relation already exists
if ($this->isAccountInCategory($fkAccountingAccount)) {
return 0;
}
$sql = "INSERT INTO ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " (fk_accounting_category, fk_accounting_account)";
$sql .= " VALUES (".((int) $this->id).", ".((int) $fkAccountingAccount).")";
dol_syslog(get_class($this)."::addAccountToCategory", LOG_DEBUG);
$this->db->begin();
$resql = $this->db->query($sql);
if ($resql) {
$this->db->commit();
return 1;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
$this->db->rollback();
return -1;
}
}
/**
* Unlink an accounting account from this category (multi-report system)
*
* @param int $fkAccountingAccount ID of the accounting account to unlink
* @return int<-1,1> <0 if KO, >0 if OK
*/
public function deleteAccountFromCategory($fkAccountingAccount)
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
$sql .= " AND fk_accounting_account = ".((int) $fkAccountingAccount);
dol_syslog(get_class($this)."::deleteAccountFromCategory", LOG_DEBUG);
$this->db->begin();
$resql = $this->db->query($sql);
if ($resql) {
$this->db->commit();
return 1;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
$this->db->rollback();
return -1;
}
}
/**
* Get all accounting accounts linked to this category (multi-report system)
*
* @return array<int,array{id:int,account_number:string,label:string}> Array of accounting accounts indexed by account ID, or empty array if error
*/
public function getAccountsForCategory()
{
global $conf;
$accounts = array();
$sql = "SELECT aca.fk_accounting_account, aa.account_number, aa.label";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = aca.fk_accounting_account";
$sql .= " WHERE aca.fk_accounting_category = ".((int) $this->id);
$sql .= " AND aa.entity = ".$conf->entity;
$sql .= " ORDER BY aa.account_number ASC";
dol_syslog(get_class($this)."::getAccountsForCategory", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
$accounts[$obj->fk_accounting_account] = array(
'id' => $obj->fk_accounting_account,
'account_number' => $obj->account_number,
'label' => $obj->label
);
$i++;
}
$this->db->free($resql);
return $accounts;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
dol_syslog(get_class($this)."::getAccountsForCategory ".$this->error, LOG_ERR);
return array();
}
}
/**
* Get categories for a specific accounting account (multi-report system)
*
* @param int $fkAccountingAccount ID of the accounting account
* @return array<int,array{id:int,code:string,label:string,fk_report:int}> Array of categories indexed by category ID, or empty array if error
*/
public function getCategoriesForAccount($fkAccountingAccount)
{
global $conf;
$categories = array();
$sql = "SELECT aca.fk_accounting_category, ac.code, ac.label, ac.fk_report";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account as aca";
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."c_accounting_category as ac ON ac.rowid = aca.fk_accounting_category";
$sql .= " WHERE aca.fk_accounting_account = ".((int) $fkAccountingAccount);
$sql .= " AND ac.entity = ".$conf->entity;
$sql .= " ORDER BY ac.position ASC";
dol_syslog(get_class($this)."::getCategoriesForAccount", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
$categories[$obj->fk_accounting_category] = array(
'id' => $obj->fk_accounting_category,
'code' => $obj->code,
'label' => $obj->label,
'fk_report' => $obj->fk_report
);
$i++;
}
$this->db->free($resql);
return $categories;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
dol_syslog(get_class($this)."::getCategoriesForAccount ".$this->error, LOG_ERR);
return array();
}
}
/**
* Check if an account belongs to this category (multi-report system)
*
* @param int $fkAccountingAccount ID of the accounting account
* @return bool True if account is in category, false otherwise
*/
public function isAccountInCategory($fkAccountingAccount)
{
$sql = "SELECT COUNT(*) as nb";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
$sql .= " AND fk_accounting_account = ".((int) $fkAccountingAccount);
dol_syslog(get_class($this)."::isAccountInCategory", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$obj = $this->db->fetch_object($resql);
return ($obj->nb > 0);
}
return false;
}
/**
* Get all accounting accounts NOT linked to this category (for selection)
*
* @return array<array{id:int,account_number:string,label:string}> Array of available accounts, or empty array if error
*/
public function getAvailableAccountsForCategory()
{
global $conf;
$accounts = array();
$pcgverid = getDolGlobalInt('CHARTOFACCOUNTS');
$pcgvercode = dol_getIdFromCode($this->db, (string) $pcgverid, 'accounting_system', 'rowid', 'pcg_version');
if (empty($pcgvercode)) {
$pcgvercode = $pcgverid;
}
$sql = "SELECT aa.rowid, aa.account_number, aa.label";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa";
$sql .= " WHERE aa.rowid NOT IN (";
$sql .= " SELECT fk_accounting_account";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
$sql .= " )";
$sql .= " AND aa.entity = ".$conf->entity;
$sql .= " AND aa.active = 1";
$sql .= " AND aa.fk_pcg_version = '".$this->db->escape($pcgvercode)."'";
$sql .= " ORDER BY aa.account_number ASC";
dol_syslog(get_class($this)."::getAvailableAccountsForCategory", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $this->db->fetch_object($resql);
$accounts[$obj->rowid] = array(
'id' => $obj->rowid,
'account_number' => $obj->account_number,
'label' => $obj->label
);
$i++;
}
$this->db->free($resql);
return $accounts;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
dol_syslog(get_class($this)."::getAvailableAccountsForCategory ".$this->error, LOG_ERR);
return array();
}
}
/**
* Add multiple accounts to this category at once
*
* @param array<int> $accountIds Array of accounting account IDs
* @return int<-1,max> Number of accounts added, -1 if error
*/
public function addMultipleAccountsToCategory(array $accountIds)
{
$added = 0;
$error = 0;
$this->db->begin();
foreach ($accountIds as $accountId) {
if (!$this->isAccountInCategory($accountId)) {
$sql = "INSERT INTO ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " (fk_accounting_category, fk_accounting_account)";
$sql .= " VALUES (".((int) $this->id).", ".((int) $accountId).")";
$resql = $this->db->query($sql);
if ($resql) {
$added++;
} else {
$error++;
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
}
}
}
if ($error) {
$this->db->rollback();
return -1;
} else {
$this->db->commit();
return $added;
}
}
/**
* Remove all accounts from this category
*
* @return int<-1,max> Number of deleted relations if OK, -1 if error
*/
public function removeAllAccountsFromCategory()
{
$sql = "DELETE FROM ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
dol_syslog(get_class($this)."::removeAllAccountsFromCategory", LOG_DEBUG);
$this->db->begin();
$resql = $this->db->query($sql);
if ($resql) {
$affected = $this->db->affected_rows($resql);
$this->db->commit();
return $affected;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
$this->db->rollback();
return -1;
}
}
/**
* Count number of accounts linked to this category
*
* @return int Number of accounts, <0 if error
*/
public function countAccountsInCategory()
{
$sql = "SELECT COUNT(*) as nb";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_category_account";
$sql .= " WHERE fk_accounting_category = ".((int) $this->id);
dol_syslog(get_class($this)."::countAccountsInCategory", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$obj = $this->db->fetch_object($resql);
return (int) $obj->nb;
} else {
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
return -1;
}
}
}

View File

@@ -14,7 +14,7 @@
* Copyright (C) 2020 Guillaume Alexandre <guillaume@tag-info.fr>
* Copyright (C) 2022 Joachim Kueter <jkueter@gmx.de>
* Copyright (C) 2022 Progiseize <a.bisotti@progiseize.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-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
@@ -1391,7 +1391,7 @@ class AccountancyExport
$separator = ';';
$end_line = "\n";
// Extract the Third party account numbers from the table to provide the correct line for ISTEA
// parcours du tableau pour recuperation des numero de compte des tiers pour pouvoir les fournir dans la bonne ligne pour istea
$tiers = [];
foreach ($objectLines as $line) {
if ($line->subledger_account && substr($line->subledger_account, 0, 1) == '4') {
@@ -2752,7 +2752,7 @@ class AccountancyExport
$tab[] = substr($date, 3, 2);
$tab[] = substr($date, 0, 2);
$tab[] = $line->doc_ref;
// Convert the UTF-8 string in latin9
//Conversion de chaine UTF8 en Latin9
$tab[] = mb_convert_encoding(str_replace(' - Compte auxiliaire', '', $line->label_operation), "Windows-1252", 'UTF-8');
//Calcul de la longueur des numéros de comptes

View File

@@ -1,5 +1,5 @@
<?php
/* Copyright (C) 2024-2026 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

View File

@@ -72,11 +72,6 @@ class AccountingAccount extends CommonObject
*/
public $rowid;
/**
* @var string Ref
*/
public $ref;
/**
* Date creation record (datec)
*

View File

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2017-2022 OpenDSI <support@open-dsi.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Janniaux <alexandre.janniaux@gmail.com>
* Copyright (C) 2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
@@ -1323,7 +1323,7 @@ class AccountingJournal extends CommonObject
$element['blocks'][] = $lines_book;
}
} else {
// When VAT = 0, push the 2 lines view/bookkeeping already prepared
// si TVA = 0, pousser les 2 lignes view/bookkeeping déjà constituées
if ($type == 'view') {
$element['blocks'][] = $lines_view;
} elseif ($type == 'bookkeeping') {

View File

@@ -1963,7 +1963,7 @@ class BookKeeping extends CommonObject
{
global $conf;
$sql = "SELECT piece_num, ref, doc_date, code_journal, journal_label, doc_ref, doc_type, fk_doc,";
$sql = "SELECT piece_num, ref, doc_date, code_journal, journal_label, doc_ref, doc_type,";
$sql .= " date_creation, tms as date_modification, date_validated as date_validation, date_lim_reglement, import_key";
// In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
if ($mode != "_tmp") {
@@ -1985,7 +1985,6 @@ class BookKeeping extends CommonObject
$this->doc_date = $this->db->jdate($obj->doc_date);
$this->doc_ref = $obj->doc_ref;
$this->doc_type = $obj->doc_type;
$this->fk_doc = $obj->fk_doc;
$this->date_creation = $this->db->jdate($obj->date_creation);
$this->date_modification = $this->db->jdate($obj->date_modification);
if ($mode != "_tmp") {
@@ -2523,7 +2522,7 @@ class BookKeeping extends CommonObject
$alias = !empty($alias) && strpos($alias, '.') === false ? $alias . "." : $alias;
if (!isset(self::$can_modify_bookkeeping_sql_cached[$alias]) || $force) {
$result = $this->loadFiscalPeriods($force, 'active'); // This set $conf->cache['active_fiscal_period_cached']
$result = $this->loadFiscalPeriods($force, 'active');
if ($result < 0) {
return null;
}
@@ -2534,10 +2533,9 @@ class BookKeeping extends CommonObject
foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
$sql_list[$i] = "(";
$sql_list[$i] .= "'".$this->db->idate($fiscal_period['date_start']) . "' <= ".$this->db->sanitize($alias)."doc_date";
// @phan-suppress-next-line PhanTypeMismatchDimAssignment
if (!empty($fiscal_period['date_end'])) {
$sql_list[$i] .= " AND ";
$sql_list[$i] .= $this->db->sanitize($alias)."doc_date <= '" . $this->db->idate((int) $fiscal_period['date_end'])."'";
$sql_list[$i] .= $this->db->sanitize($alias)."doc_date <= '" . $this->db->idate($fiscal_period['date_end'])."'";
}
$sql_list[$i] .= ")";
$i++;
@@ -2597,7 +2595,6 @@ class BookKeeping extends CommonObject
}
if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) {
foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
// @phan-suppress-next-line PhanTypeMismatchDimAssignment
if (!empty($fiscal_period['date_start']) && $fiscal_period['date_start'] <= $bookkeeping->doc_date && (empty($fiscal_period['date_end']) || $bookkeeping->doc_date <= $fiscal_period['date_end'])) {
return 1;
}
@@ -2696,7 +2693,6 @@ class BookKeeping extends CommonObject
if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) {
foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
// @phan-suppress-next-line PhanTypeMismatchDimAssignment
if (!empty($fiscal_period['date_start']) && $fiscal_period['date_start'] <= $date && (empty($fiscal_period['date_end']) || $date <= $fiscal_period['date_end'])) {
return 1;
}

View File

@@ -1,561 +0,0 @@
<?php
/* Copyright (C) 2024 AWeerWolf
* Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file accountancy/class/bookkeepingtemplate.class.php
* \ingroup accountancy
* \brief This file is a CRUD class file for BookkeepingTemplate (Create/Read/Update/Delete)
*/
// Put here all includes required by your class file
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeepingtemplateline.class.php';
/**
* Class for BookkeepingTemplate
*/
class BookkeepingTemplate extends CommonObject
{
/**
* @var string ID of module.
*/
public $module = 'accountancy';
/**
* @var string ID to identify managed object.
*/
public $element = 'accounting_transaction_template';
/**
* @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
*/
public $table_element = 'accounting_transaction_template';
/**
* @var int<0,1>|string 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
*/
public $ismultientitymanaged = 1;
/**
* @var int<0,1> Does object support extrafields ? 0=No, 1=Yes
*/
public $isextrafieldmanaged = 1;
/**
* @var string String with name of icon for bookkeepingtemplate. Must be a 'fa-xxx' fontawesome code (or 'fa-xxx_fa_color_size') or 'bookkeepingtemplate@accountancy' if picto is file 'img/object_bookkeepingtemplate.png'.
*/
public $picto = 'fa-list';
/**
* 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
* Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
* 'label' the translation key.
* 'langfile' the key of the language file for translation.
* 'enabled' is a condition when the field must be managed.
* 'position' is the sort order of field.
* 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
* 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
* 'noteditable' says if field is not editable (1 or 0)
* 'default' is a default value for creation (can still be 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.
* 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
* 'css' is the CSS style to use on field. For example: 'maxwidth200'
* 'help' is a string visible as a tooltip on field
* 'showoncombobox' if value of the field must be visible into the label of the combobox that list record
* 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
* 'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
* 'comment' is not used. You can store here any text of your choice. It is not used by application.
*
* Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
*/
// BEGIN MODULEBUILDER PROPERTIES
/**
* @var array<string,array{type:string,label:string,langfile?:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int<-6,6>|string,alwayseditable?:int<0,1>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,cssview?:string,csslist?:string,help?:string,showoncombobox?:int<0,4>|string,disabled?:int<0,1>,arrayofkeyval?:array<int|string,string>,autofocusoncreate?:int<0,1>,comment?:string,copytoclipboard?:int<1,2>,validate?:int<0,1>,showonheader?:int<0,1>,searchmulti?:int<0,1>,picto?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
*/
public $fields = array(
"rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => 1, 'position' => 1, 'notnull' => 1, "visible" => 0, "noteditable" => 1, "index" => 1, "css" => "left", "comment" => "Id"),
"entity" => array("type" => "integer", "label" => "Entity", "enabled" => 1, 'position' => 5, 'notnull' => 1, "visible" => 0, "index" => 1, "default" => '1'),
"code" => array("type" => "varchar(128)", "label" => "Code", "enabled" => 1, 'position' => 10, 'notnull' => 1, "visible" => 1, "index" => 2, "searchall" => 1, "css" => "minwidth300", "help" => "UniqueCodeForTemplate"),
"label" => array("type" => "varchar(255)", "label" => "Label", "enabled" => 1, 'position' => 20, 'notnull' => 0, "visible" => 1, "css" => "minwidth300"),
"date_creation" => array("type" => "datetime", "label" => "DateCreation", "enabled" => 1, 'position' => 500, 'notnull' => 1, "visible" => -2),
"tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => 1, 'position' => 501, 'notnull' => 0, "visible" => -2),
"fk_user_creat" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserAuthor", "picto" => "user", "enabled" => 1, 'position' => 510, 'notnull' => 1, "visible" => "-2", "csslist" => "tdoverflowmax150"),
"fk_user_modif" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserModif", "picto" => "user", "enabled" => 1, 'position' => 511, 'notnull' => -1, "visible" => "-2", "csslist" => "tdoverflowmax150"),
"import_key" => array("type" => "varchar(14)", "label" => "ImportId", "enabled" => 1, 'position' => 1000, 'notnull' => -1, "visible" => -2),
);
// END MODULEBUILDER PROPERTIES
/**
* @var int ID
*/
public $rowid;
/**
* @var int Entity
*/
public $entity;
/**
* @var string Code
*/
public $code;
/**
* @var string Label
*/
public $label;
/**
* @var int Unix timestamp of creation date
*/
public $date_creation;
/**
* @var int Unix timestamp of last modification
*/
public $tms;
/**
* @var int User ID who created
*/
public $fk_user_creat;
/**
* @var int|null User ID who modified
*/
public $fk_user_modif;
/**
* @var string|null Import key
*/
public $import_key;
/**
* @var string Name of subtable line
*/
public $table_element_line = 'accounting_transaction_template_det';
/**
* @var BookkeepingTemplateLine[] Array of subtable lines
*/
public $lines = array();
/**
* Constructor
*
* @param DoliDb $db Database handler
*/
public function __construct(DoliDB $db)
{
global $conf, $langs;
$this->db = $db;
if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'], $this->fields['code']) && is_array($this->fields['rowid'])) {
$this->fields['rowid']['visible'] = 0;
}
if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
$this->fields['entity']['enabled'] = 0;
}
// Unset fields that are disabled
foreach ($this->fields as $key => $val) {
if (isset($val['enabled']) && empty($val['enabled'])) {
unset($this->fields[$key]);
}
}
// Translate some data of arrayofkeyval
if (is_object($langs)) {
foreach ($this->fields as $key => $val) {
if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
foreach ($val['arrayofkeyval'] as $key2 => $val2) {
$this->fields[$key]['arrayofkeyval'][$key2] = (string) $langs->trans($val2);
}
}
}
}
}
/**
* Create object into database
*
* @param User $user User that creates
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, Id of created object if OK
*/
public function create(User $user, $notrigger = 0)
{
$resultcreate = $this->createCommon($user, $notrigger);
return $resultcreate;
}
/**
* Clone an object into another one
*
* @param User $user User that creates
* @param int $fromid Id of object to clone
* @return mixed New object created, <0 if KO
*/
public function createFromClone(User $user, $fromid)
{
global $langs, $extrafields;
$error = 0;
dol_syslog(__METHOD__, LOG_DEBUG);
$object = new self($this->db);
$this->db->begin();
// Load source object
$result = $object->fetchCommon($fromid);
if ($result > 0 && !empty($object->table_element_line)) {
$object->fetchLines();
}
// Reset some properties
unset($object->id);
unset($object->fk_user_creat);
// Clear fields
$object->code = "COPY_" . $object->code;
$object->label = $langs->trans("CopyOf") . " " . $object->label;
$object->date_creation = dol_now();
// Create clone
$object->context['createfromclone'] = 'createfromclone';
$result = $object->createCommon($user);
if ($result < 0) {
$error++;
$this->setErrorsFromObject($object);
}
if (!$error) {
// Copy Attached Lines
$this->getLinesArray();
foreach ($this->lines as $linetoclone) {
// Clear some info
unset($linetoclone->id);
unset($linetoclone->fk_user_creat);
$linetoclone->fk_transaction_template = $object->id;
// Save in DB
$linetoclone->createCommon($user);
}
}
unset($object->context['createfromclone']);
// End
if (!$error) {
$this->db->commit();
return $object;
} else {
$this->db->rollback();
return -1;
}
}
/**
* Load object in memory from the database
*
* @param int $id Id object
* @param string $code Code
* @param int $noextrafields 0=Default to load extrafields, 1=No extrafields
* @param int $nolines 0=Default to load lines, 1=No lines
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
*/
public function fetch($id, $code = null, $noextrafields = 0, $nolines = 0)
{
$result = $this->fetchCommon($id, $code, '', $noextrafields);
if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
$this->fetchLines($noextrafields);
}
return $result;
}
/**
* Load object lines in memory from the database
*
* @param int $noextrafields 0=Default to load extrafields, 1=No extrafields
* @return BookkeepingTemplateLine[]|int Array of line objects if OK, <0 if KO
*/
public function fetchLines($noextrafields = 0)
{
$this->lines = array();
$objectline = new BookkeepingTemplateLine($this->db);
$result = $objectline->fetchAll('ASC', 'rowid', 0, 0, array('customsql' => 'fk_transaction_template = ' . ((int) $this->id)));
if (is_numeric($result)) {
$this->setErrorsFromObject($objectline);
return $result;
} else {
$this->lines = $result;
return $this->lines;
}
}
/**
* Update object into database
*
* @param User $user User that modifies
* @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, >0 if OK
*/
public function update(User $user, $notrigger = 0)
{
return $this->updateCommon($user, $notrigger);
}
/**
* Delete object in database
*
* @param User $user User that deletes
* @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, >0 if OK
*/
public function delete(User $user, $notrigger = 0)
{
global $conf, $langs;
$error = 0;
$this->db->begin();
// Delete the Lines first
$obj_line = new BookkeepingTemplateLine($this->db);
$sql = "DELETE FROM ".$this->db->prefix().$obj_line->table_element;
$sql .= " WHERE fk_transaction_template = ".((int) $this->id);
dol_syslog(get_class($this)."::delete sql=".$sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->errors[] = $this->db->lasterror();
$error++;
dol_syslog(get_class($this)."::delete error deleting lines: ".$this->db->lasterror(), LOG_ERR);
}
if (empty($error)) {
// Call trigger
if (!$notrigger) {
$result = $this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user);
if ($result < 0) {
$error++;
}
}
}
if (empty($error)) {
// Delete main object
$sql = "DELETE FROM ".$this->db->prefix().$this->table_element;
$sql .= " WHERE rowid = ".((int) $this->id);
dol_syslog(get_class($this)."::delete sql=".$sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (!$resql) {
$this->errors[] = $this->db->lasterror();
$this->error = $this->db->lasterror();
$error++;
dol_syslog(get_class($this)."::delete error deleting main object: ".$this->db->lasterror(), LOG_ERR);
}
}
// Commit or rollback
if (empty($error)) {
$this->db->commit();
return 1;
} else {
$this->error = implode(', ', $this->errors);
$this->db->rollback();
return -1;
}
}
/**
* Delete a line of object in database
*
* @param User $user User that delete
* @param int $idline Id of line to delete
* @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
* @return int >0 if OK, <0 if KO
*/
public function deleteLine(User $user, $idline, $notrigger = 0)
{
$tmpline = new BookkeepingTemplateLine($this->db);
if ($tmpline->fetch($idline) > 0) {
return $tmpline->delete($user);
}
return -1;
}
/**
* Create an array of lines
*
* @return BookkeepingTemplateLine[]|int array of BookkeepingTemplateLine objects if OK, <0 if KO
*/
public function getLinesArray()
{
$this->lines = array();
$objectline = new BookkeepingTemplateLine($this->db);
$result = $objectline->fetchAll('ASC', 'rowid', 0, 0, array('customsql' => 'fk_transaction_template = ' . ((int) $this->id)));
if (is_numeric($result)) {
$this->setErrorsFromObject($objectline);
return $result;
} else {
$this->lines = $result;
return $this->lines;
}
}
/**
* Returns the reference to the following non used object depending on the active numbering module.
*
* @return string Object free reference
*/
public function getNextNumRef()
{
global $langs, $conf;
$langs->load("accountancy");
// Standard numbering - Generate a code based on timestamp
$code = 'TPL' . dol_print_date(dol_now(), '%Y%m%d%H%M%S');
return $code;
}
/**
* Return a link to the object card (with optionally the picto)
*
* @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
* @param string $option On what the link point to ('nolink', ...)
* @param int $notooltip 1=Disable tooltip
* @param string $morecss Add more css on link
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string String with URL
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
{
global $conf, $langs, $hookmanager;
if (!empty($conf->dol_no_mouse_hover)) {
$notooltip = 1;
}
$result = '';
$label = img_picto('', $this->picto) . ' <u>' . $langs->trans("BookkeepingTemplate") . '</u>';
if (isset($this->code)) {
$label .= '<br><b>' . $langs->trans('Code') . ':</b> ' . $this->code;
}
if (isset($this->label)) {
$label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $this->label;
}
$url = DOL_URL_ROOT . '/accountancy/admin/template/card.php?id=' . $this->id;
if ($option != 'nolink') {
// Add param to save lastsearch_values or not
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
if ($save_lastsearch_value == -1 && 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';
}
}
$linkclose = '';
if (empty($notooltip)) {
if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
$label = $langs->trans("ShowBookkeepingTemplate");
$linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
}
$linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
$linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
} else {
$linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
}
if ($option == 'nolink') {
$linkstart = '<span';
} else {
$linkstart = '<a href="' . $url . '"';
}
$linkstart .= $linkclose . '>';
if ($option == 'nolink') {
$linkend = '</span>';
} else {
$linkend = '</a>';
}
$result .= $linkstart;
if ($withpicto) {
$result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
}
if ($withpicto != 2) {
$result .= $this->code;
}
$result .= $linkend;
return $result;
}
/**
* Return label of status
*
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
* @return string Label of status
*/
public function getLibStatut($mode = 0)
{
return $this->LibStatut(1, $mode);
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Return label of a given status
*
* @param int $status Status
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
* @return string Label of status
*/
public function LibStatut($status, $mode = 0)
{
// phpcs:enable
global $langs;
return '';
}
}

View File

@@ -1,368 +0,0 @@
<?php
/* Copyright (C) 2024 AWeerWolf
* Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file accountancy/class/bookkeepingtemplateline.class.php
* \ingroup accountancy
* \brief This file is a CRUD class file for BookkeepingTemplateLine (Create/Read/Update/Delete)
*/
// Put here all includes required by your class file
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
/**
* Class for BookkeepingTemplateLine
*/
class BookkeepingTemplateLine extends CommonObject
{
/**
* @var string ID of module.
*/
public $module = 'accountancy';
/**
* @var string ID to identify managed object.
*/
public $element = 'accounting_transaction_template_det';
/**
* @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
*/
public $table_element = 'accounting_transaction_template_det';
/**
* @var int<0,1>|string 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
*/
public $ismultientitymanaged = 0;
/**
* @var int<0,1> Does object support extrafields ? 0=No, 1=Yes
*/
public $isextrafieldmanaged = 0;
/**
* @var string String with name of icon for bookkeepingtemplateline. Must be a 'fa-xxx' fontawesome code (or 'fa-xxx_fa_color_size') or 'bookkeepingtemplateline@accountancy' if picto is file 'img/object_bookkeepingtemplateline.png'.
*/
public $picto = 'fa-file';
/**
* 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
* Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
* 'label' the translation key.
* 'langfile' the key of the language file for translation.
* 'enabled' is a condition when the field must be managed.
* 'position' is the sort order of field.
* 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
* 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
* 'noteditable' says if field is not editable (1 or 0)
* 'default' is a default value for creation (can still be 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.
* 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
* 'css' is the CSS style to use on field. For example: 'maxwidth200'
* 'help' is a string visible as a tooltip on field
* 'showoncombobox' if value of the field must be visible into the label of the combobox that list record
* 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
* 'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
* 'comment' is not used. You can store here any text of your choice. It is not used by application.
*
* Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
*/
// BEGIN MODULEBUILDER PROPERTIES
/**
* @var array<string,array{type:string,label:string,langfile?:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int<-6,6>|string,alwayseditable?:int<0,1>|string,noteditable?:int<0,1>,default?:string,index?:int,foreignkey?:string,searchall?:int<0,1>,isameasure?:int<0,1>,css?:string,cssview?:string,csslist?:string,help?:string,showoncombobox?:int<0,4>|string,disabled?:int<0,1>,arrayofkeyval?:array<int|string,string>,autofocusoncreate?:int<0,1>,comment?:string,copytoclipboard?:int<1,2>,validate?:int<0,1>,showonheader?:int<0,1>,searchmulti?:int<0,1>}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
*/
public $fields = array(
"rowid" => array("type"=>"integer", "label"=>"TechnicalID", "enabled"=>1, 'position'=>1, 'notnull'=>1, "visible"=>0, "noteditable"=>1, "index"=>1, "css"=>"left", "comment"=>"Id"),
"fk_transaction_template" => array("type"=>"integer", "label"=>"Template", "enabled"=>1, 'position'=>5, 'notnull'=>1, "visible"=>0, "noteditable"=>1, "foreignkey"=>"accounting_transaction_template.rowid"),
"general_account" => array("type"=>"varchar(32)", "label"=>"AccountNumber", "enabled"=>1, 'position'=>10, 'notnull'=>1, "visible"=>1, "css"=>"minwidth100"),
"general_label" => array("type"=>"varchar(255)", "label"=>"AccountLabel", "enabled"=>1, 'position'=>20, 'notnull'=>1, "visible"=>1, "css"=>"minwidth200"),
"subledger_account" => array("type"=>"varchar(32)", "label"=>"SubledgerAccount", "enabled"=>1, 'position'=>30, 'notnull'=>0, "visible"=>1, "css"=>"minwidth100"),
"subledger_label" => array("type"=>"varchar(255)", "label"=>"SubledgerLabel", "enabled"=>1, 'position'=>40, 'notnull'=>0, "visible"=>1, "css"=>"minwidth200"),
"operation_label" => array("type"=>"varchar(255)", "label"=>"OperationLabel", "enabled"=>1, 'position'=>50, 'notnull'=>0, "visible"=>1, "css"=>"minwidth200"),
"debit" => array("type"=>"double(24,8)", "label"=>"Debit", "enabled"=>1, 'position'=>60, 'notnull'=>0, "visible"=>1, "css"=>"maxwidth75 right"),
"credit" => array("type"=>"double(24,8)", "label"=>"Credit", "enabled"=>1, 'position'=>70, 'notnull'=>0, "visible"=>1, "css"=>"maxwidth75 right"),
);
// END MODULEBUILDER PROPERTIES
/**
* @var int ID
*/
public $rowid;
/**
* @var int Foreign key to accounting transaction template
*/
public $fk_transaction_template;
/**
* @var string General account number
*/
public $general_account;
/**
* @var string|null General account label/description
*/
public $general_label;
/**
* @var string|null Subledger account number (auxiliary account)
*/
public $subledger_account;
/**
* @var string|null Subledger account label/description
*/
public $subledger_label;
/**
* @var string Debit amount (stored as string for precision)
*/
public $debit;
/**
* @var string Credit amount (stored as string for precision)
*/
public $credit;
/**
* @var string|null Sense/direction (D for debit, C for credit)
*/
public $sens;
/**
* @var int|null Line position/order
*/
public $position;
/**
* @var integer|''|null Creation date
*/
public $date_creation;
/**
* @var int
*/
public $tms;
/**
* @var int|null User ID who created this line
*/
public $fk_user_creat;
/**
* @var int|null User ID who last modified this line
*/
public $fk_user_modif;
/**
* Constructor
*
* @param DoliDb $db Database handler
*/
public function __construct(DoliDB $db)
{
global $conf, $langs;
$this->db = $db;
if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
$this->fields['rowid']['visible'] = 0;
}
// Unset fields that are disabled
foreach ($this->fields as $key => $val) {
if (isset($val['enabled']) && empty($val['enabled'])) {
unset($this->fields[$key]);
}
}
// Translate some data of arrayofkeyval
if (is_object($langs)) {
foreach ($this->fields as $key => $val) {
if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
foreach ($val['arrayofkeyval'] as $key2 => $val2) {
$this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
}
}
}
}
}
/**
* Create object into database
*
* @param User $user User that creates
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, Id of created object if OK
*/
public function create(User $user, $notrigger = 0)
{
$resultcreate = $this->createCommon($user, $notrigger);
return $resultcreate;
}
/**
* Load object in memory from the database
*
* @param int $id Id object
* @param int $noextrafields 0=Default to load extrafields, 1=No extrafields
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
*/
public function fetch($id, $noextrafields = 0)
{
$result = $this->fetchCommon($id, '', '', $noextrafields);
return $result;
}
/**
* Load list of objects in memory from the database.
*
* @param string $sortorder Sort Order
* @param string $sortfield Sort field
* @param int $limit limit
* @param int $offset Offset
* @param array<string,mixed> $filter Filter array. Example array('mystringfield'=>'value', 'myintfield'=>4, 'customsql'=>...)
* @param string $filtermode Filter mode (AND or OR)
* @return BookkeepingTemplateLine[]|int Array of BookkeepingTemplateLine objects if OK, <0 if KO
*/
public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
{
dol_syslog(__METHOD__, LOG_DEBUG);
$records = array();
$sql = "SELECT ";
$sql .= $this->getFieldList('t');
$sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
if (isset($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
$sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
}
$sql .= " WHERE 1 = 1";
// Manage filter
$sqlwhere = array();
if (count($filter) > 0) {
foreach ($filter as $key => $value) {
if ($key === 'customsql') {
// Never use 'customsql' with a value from user input since it is injected as is. The value must be hard coded.
$sqlwhere[] = $value;
continue;
}
$columnName = preg_replace('/^t\./', '', $key);
if (isset($this->fields[$columnName])) {
$type = $this->fields[$columnName]['type'];
if (preg_match('/^integer/', $type)) {
if (is_int($value)) {
// single value
$sqlwhere[] = $key . " = " . intval($value);
} elseif (is_array($value)) {
if (empty($value)) {
continue;
}
$sqlwhere[] = $key . ' IN (' . $this->db->sanitize(implode(',', array_map('intval', $value))) . ')';
}
continue;
} elseif (in_array($type, array('date', 'datetime', 'timestamp'))) {
$sqlwhere[] = $key . " = '" . $this->db->idate($value) . "'";
continue;
}
}
// when the $key doesn't fall into the previously handled categories, we do as if the column were a varchar/text
if (is_array($value) && count($value)) {
$escapedValues = array();
foreach ($value as $v) {
$escapedValues[] = $this->db->escape($v);
}
$value = implode(',', $escapedValues);
$sqlwhere[] = $key . ' IN (' . $this->db->sanitize($value, 1) . ')';
} elseif (is_scalar($value)) {
if (strpos($value, '%') === false) {
$sqlwhere[] = $key . " = '" . $this->db->sanitize($this->db->escape($value)) . "'";
} else {
$sqlwhere[] = $key . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'";
}
}
}
}
if (count($sqlwhere) > 0) {
$sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")";
}
if (!empty($sortfield)) {
$sql .= $this->db->order($sortfield, $sortorder);
}
if (!empty($limit)) {
$sql .= $this->db->plimit($limit, $offset);
}
$resql = $this->db->query($sql);
if ($resql) {
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < ($limit ? min($limit, $num) : $num)) {
$obj = $this->db->fetch_object($resql);
$record = new self($this->db);
$record->setVarsFromFetchObj($obj);
$records[$record->id] = $record;
$i++;
}
$this->db->free($resql);
return $records;
} else {
$this->errors[] = 'Error '.$this->db->lasterror();
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
return -1;
}
}
/**
* Update object into database
*
* @param User $user User that modifies
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, >0 if OK
*/
public function update(User $user, $notrigger = 0)
{
return $this->updateCommon($user, $notrigger);
}
/**
* Delete object in database
*
* @param User $user User that deletes
* @param int $notrigger 0=launch triggers after, 1=disable triggers
* @return int Return integer <0 if KO, >0 if OK
*/
public function delete(User $user, $notrigger = 0)
{
return $this->deleteCommon($user, $notrigger);
}
}

View File

@@ -2,7 +2,7 @@
/* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2013 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-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
@@ -824,7 +824,7 @@ class Lettering extends BookKeeping
*
* @param int[] $document_ids List of document id
* @param string $doc_type Type of document ('customer_invoice' or 'supplier_invoice', ...)
* @return array<int,array<int,int>>|int<-1,-1> Return integer <0 if error otherwise all linked document ids by group and type [ [ 'doc_type' => [ doc_id, ... ], ... ], ... ]
* @return array<int,array<int,int>>|int<-1,-1> Return integer <0 if error otherwise all linked document ids by group and type [ [ 'doc_type' => [ doc_id, ... ], ... ], ... ]
*/
public function getLinkedDocumentByGroup($document_ids, $doc_type)
{
@@ -910,7 +910,7 @@ class Lettering extends BookKeeping
/**
* Get element ids grouped by link or element in common
*
* @param array<int,array<string,int|string>> $link_by_element List of payment ids by link key
* @param array<int,array<string,int>> $link_by_element List of payment ids by link key
* @param array<string,array<int,int>> $element_by_link List of element ids by link key
* @param string $link_key Link key (used for recursive function)
* @param array<int,int> $current_group Current group (used for recursive function)

View File

@@ -155,8 +155,8 @@ if (empty($reshook)) {
}
} elseif ($action == 'confirm_step_2' && $confirm == "yes" && $user->hasRight('accounting', 'fiscalyear', 'write')) {
$new_fiscal_period_id = GETPOSTINT('new_fiscal_period_id');
$separate_auxiliary_account = GETPOSTINT('separate_auxiliary_account');
$generate_bookkeeping_records = GETPOSTINT('generate_bookkeeping_records');
$separate_auxiliary_account = (!empty(GETPOST('separate_auxiliary_account')) ? 1 : 0);
$generate_bookkeeping_records = (!empty(GETPOST('generate_bookkeeping_records')) ? 1 : 0);
$error = 0;
if ($generate_bookkeeping_records) {

View File

@@ -2191,7 +2191,7 @@ class Adherent extends CommonObject
$now = dol_now();
// Check parameters
if ($this->status == self::STATUS_VALIDATED) {
if ($this->statut == self::STATUS_VALIDATED) {
dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2208,7 +2208,6 @@ class Adherent extends CommonObject
$result = $this->db->query($sql);
if ($result) {
$this->statut = self::STATUS_VALIDATED;
$this->status = self::STATUS_VALIDATED;
// Call trigger
$result = $this->call_trigger('MEMBER_VALIDATE', $user);
@@ -2232,7 +2231,7 @@ class Adherent extends CommonObject
/**
* Function that terminates a member
* Fonction qui resilie un adherent
*
* @param User $user User making change
* @return int Return integer <0 if KO, >0 if OK
@@ -2244,7 +2243,7 @@ class Adherent extends CommonObject
$error = 0;
// Check parameters
if ($this->status == self::STATUS_RESILIATED) {
if ($this->statut == self::STATUS_RESILIATED) {
dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2259,7 +2258,6 @@ class Adherent extends CommonObject
$result = $this->db->query($sql);
if ($result) {
$this->statut = self::STATUS_RESILIATED;
$this->status = self::STATUS_RESILIATED;
// Call trigger
$result = $this->call_trigger('MEMBER_RESILIATE', $user);
@@ -2293,7 +2291,7 @@ class Adherent extends CommonObject
$error = 0;
// Check parameters
if ($this->status == self::STATUS_EXCLUDED) {
if ($this->statut == self::STATUS_EXCLUDED) {
dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2308,7 +2306,6 @@ class Adherent extends CommonObject
$result = $this->db->query($sql);
if ($result) {
$this->statut = self::STATUS_EXCLUDED;
$this->status = self::STATUS_EXCLUDED;
// Call trigger
$result = $this->call_trigger('MEMBER_EXCLUDE', $user);
@@ -2518,7 +2515,7 @@ class Adherent extends CommonObject
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @param int $notooltip 1=Disable tooltip
* @param int $addlinktonotes 1=Add link to notes
* @return string String with URL
* @return string Chaine avec URL
*/
public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
{
@@ -2749,7 +2746,7 @@ class Adherent extends CommonObject
global $conf, $langs;
if ($user->socid) {
return -1; // Protection to prevent calls by external users
return -1; // protection pour eviter appel par utilisateur externe
}
$now = dol_now();
@@ -2924,7 +2921,7 @@ class Adherent extends CommonObject
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Returns the complete DN (Distinguished Name) string in the LDAP directory for the object
* Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
*
* @param array<string,mixed> $info Info array loaded by _load_ldap_info
* @param int<0,2> $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
@@ -3150,7 +3147,7 @@ class Adherent extends CommonObject
$sql = "SELECT count(mc.email) as nb";
$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
$sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with success
$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec success
$resql = $this->db->query($sql);
if ($resql) {

View File

@@ -6,7 +6,7 @@
* Copyright (C) 2018-2019 Thibault Foucart <support@ptibogxiv.net>
* Copyright (C) 2021 Waël Almoman <info@almoman.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-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
@@ -111,10 +111,8 @@ class AdherentType extends CommonObject
"rowid" => array("type" => "integer", "label" => "Ref", "enabled" => "1", 'position' => 10, 'notnull' => 1, "visible" => "1",),
"libelle" => array("type" => "varchar(50)", "label" => "Label", "enabled" => "1", 'position' => 30, 'notnull' => 1, "visible" => "1", "showoncombobox" => 1),
"subscription" => array("type" => "varchar(3)", "label" => "Subscription", "enabled" => "1", 'position' => 35, 'notnull' => 1, "visible" => "1",),
"caneditamount" => array("type" => "integer", "label" => "Caneditamount", "enabled" => "1", 'position' => 40, 'notnull' => 0, "visible" => "1",),
"minimumamount" => array("type" => "double(24,8)", "label" => "MinimumAmount", "enabled" => "1", 'position' => 42, 'notnull' => 0, "visible" => "1",),
"amount" => array("type" => "double(24,8)", "label" => "Amount", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "1",),
"amountformuladescription" => array("type" => "longtext", "label" => "AmountFormulaDescription", "enabled" => "1", 'position' => 46, 'notnull' => 0, "visible" => "1",),
"amount" => array("type" => "double(24,8)", "label" => "Amount", "enabled" => "1", 'position' => 40, 'notnull' => 0, "visible" => "1",),
"caneditamount" => array("type" => "integer", "label" => "Caneditamount", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "1",),
"vote" => array("type" => "varchar(3)", "label" => "Vote", "enabled" => "1", 'position' => 50, 'notnull' => 1, "visible" => "-1",),
"mail_valid" => array("type" => "longtext", "label" => "MailValidation", "enabled" => "1", 'position' => 60, 'notnull' => 0, "visible" => "-3",),
"morphy" => array("type" => "varchar(3)", "label" => "MembersNature", "enabled" => "1", 'position' => 65, 'notnull' => 0, "visible" => "1",),
@@ -162,25 +160,15 @@ class AdherentType extends CommonObject
*/
public $subscription;
/**
* @var int Amount can be chosen by the visitor during subscription (0 or 1)
*/
public $caneditamount;
/**
* @var float|string Minimum Amount for subscription (null or '' means not defined)
*/
public $minimumamount;
/**
* @var float|string Amount for subscription (null or '' means not defined)
*/
public $amount;
/**
* @var string Describe the subscription amount formula to follow
* @var int Amount can be chosen by the visitor during subscription (0 or 1)
*/
public $amountformuladescription;
public $caneditamount;
/**
* @var string Public note
@@ -285,7 +273,7 @@ class AdherentType extends CommonObject
if ($result) {
while ($obj = $this->db->fetch_object($result)) {
//print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
if ($obj->lang == $current_lang) { // if we have the translations in the current language, we load them as main information.
if ($obj->lang == $current_lang) { // si on a les traduct. dans la langue courante on les charge en infos principales.
$this->label = $obj->label;
$this->description = $obj->description;
$this->email = $obj->email;
@@ -507,10 +495,8 @@ class AdherentType extends CommonObject
$sql .= "libelle = '".$this->db->escape($this->label)."',";
$sql .= "morphy = '".$this->db->escape($this->morphy)."',";
$sql .= "subscription = '".$this->db->escape((string) $this->subscription)."',";
$sql .= "caneditamount = ".((int) $this->caneditamount).",";
$sql .= "minimumamount = ".((empty($this->minimumamount) && $this->minimumamount == '') ? "null" : ((float) $this->minimumamount)).",";
$sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? "null" : ((float) $this->amount)).",";
$sql .= "amountformuladescription = '".$this->db->escape($this->amountformuladescription)."',";
$sql .= "caneditamount = ".((int) $this->caneditamount).",";
$sql .= "duration = '".$this->db->escape($this->duration_value.$this->duration_unit)."',";
$sql .= "note = '".$this->db->escape($this->note_public)."',";
$sql .= "vote = ".(int) $this->db->escape((string) $this->vote).",";
@@ -600,7 +586,7 @@ class AdherentType extends CommonObject
*/
public function fetch($rowid)
{
$sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.caneditamount, d.minimumamount, d.amount, d.amountformuladescription, d.mail_valid, d.note as note_public, d.vote";
$sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.caneditamount, d.mail_valid, d.note as note_public, d.vote";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d";
$sql .= " WHERE d.rowid = ".(int) $rowid;
@@ -620,10 +606,8 @@ class AdherentType extends CommonObject
$this->duration_value = (int) substr($obj->duration, 0, dol_strlen($obj->duration) - 1);
$this->duration_unit = substr($obj->duration, -1);
$this->subscription = $obj->subscription;
$this->caneditamount = $obj->caneditamount;
$this->minimumamount = $obj->minimumamount;
$this->amount = $obj->amount;
$this->amountformuladescription = $obj->amountformuladescription;
$this->caneditamount = $obj->caneditamount;
$this->mail_valid = $obj->mail_valid;
$this->note = $obj->note_public; // deprecated
$this->note_public = $obj->note_public;
@@ -798,80 +782,6 @@ class AdherentType extends CommonObject
return $caneditamountbytype;
}
/**
* Return the array of all minimum amounts per membership type id
*
* @param int $status Filter on status of type
* @return array<int,float> Array of membership type
*/
public function minimumAmountByType($status = null)
{
$minimumamountbytype = array();
$sql = "SELECT rowid, minimumamount";
$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);
$minimumamountbytype[$obj->rowid] = (float) $obj->minimumamount;
$i++;
}
}
} else {
print $this->db->error();
}
return $minimumamountbytype;
}
/**
* Return the array of all amount formula's descriptions per membership type id
*
* @param int $status Filter on status of type
* @return array<int,float> Array of membership type
*/
public function amountFormulaDescriptionByType($status = null)
{
$amountformuladescriptionbytype = array();
$sql = "SELECT rowid, amountformuladescription";
$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);
$amountformuladescriptionbytype[$obj->rowid] = $obj->amountformuladescription;
$i++;
}
}
} else {
print $this->db->error();
}
return $amountformuladescriptionbytype;
}
/**
* Return array of Member objects for member type this->id (or all if this->id not defined)
*
@@ -1092,7 +1002,7 @@ class AdherentType extends CommonObject
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Returns full DN description in LDAP directory format for the object
* Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
*
* @param array<string,mixed> $info Info array loaded by _load_ldap_info
* @param int<0,2> $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)

View File

@@ -431,7 +431,7 @@ class Subscription extends CommonObject
* @param string $option Page for link ('', 'nolink', ...)
* @param string $morecss Add more css on link
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string String with URL
* @return string Chaine avec URL
*/
public function getNomUrl($withpicto = 0, $notooltip = 0, $option = '', $morecss = '', $save_lastsearch_value = -1)
{

View File

@@ -6,7 +6,7 @@
* Copyright (C) 2014-2016 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2018-2024 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2021-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Benjamin Falière <benjamin.faliere@altairis.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
*
@@ -503,7 +503,7 @@ if ($search_filter == 'outofdate') {
$sql .= " AND (datefin < '".$db->idate($now)."')";
}
if ($search_status != '') {
// Can be a number or comma separated list of numbers
// Peut valoir un nombre ou liste de nombre separates par virgules
$sql .= " AND d.statut in (".$db->sanitize($db->escape($search_status)).")";
}
if ($search_morphy != '' && $search_morphy != '-1') {

View File

@@ -149,9 +149,7 @@ if (empty($reshook) && $action == 'confirm_create_thirdparty' && $confirm == 'ye
$langs->load("errors");
setEventMessages($company->error, $company->errors, 'errors');
} else {
$object->socid = $result;
$action = 'createsubscription';
$action = 'addsubscription';
}
} else {
setEventMessages($object->error, $object->errors, 'errors');
@@ -250,14 +248,14 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$langs->load("errors");
$errmsg = $langs->trans("ErrorBadDateFormat", $langs->transnoentitiesnoconv("DateSubscription"));
setEventMessages($errmsg, null, 'errors');
$action = 'createsubscription';
$action = 'addsubscription';
}
if (GETPOST('end') && !$datesubend) {
$error++;
$langs->load("errors");
$errmsg = $langs->trans("ErrorBadDateFormat", $langs->transnoentitiesnoconv("DateEndSubscription"));
setEventMessages($errmsg, null, 'errors');
$action = 'createsubscription';
$action = 'addsubscription';
}
if (!$datesubend) {
$datesubend = dol_time_plus_duree(dol_time_plus_duree($datesubscription, $defaultdelay, $defaultdelayunit), -1, 'd');
@@ -266,7 +264,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$error++;
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePayment"));
setEventMessages($errmsg, null, 'errors');
$action = 'createsubscription';
$action = 'addsubscription';
}
// Check if a payment is mandatory or not
@@ -276,7 +274,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'createsubscription';
$action = 'addsubscription';
} else {
// If an amount has been provided, we check also fields that becomes mandatory when amount is not null.
if (isModEnabled('bank') && GETPOST("paymentsave") != 'none') {
@@ -285,26 +283,26 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'createsubscription';
$action = 'addsubscription';
}
if (GETPOST("paymentsave") != 'invoiceonly' && !GETPOST("operation")) {
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'createsubscription';
$action = 'addsubscription';
}
if (GETPOST("paymentsave") != 'invoiceonly' && !(GETPOSTINT("accountid") > 0)) {
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("FinancialAccount"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'createsubscription';
$action = 'addsubscription';
}
} else {
if (GETPOSTINT("accountid")) {
$errmsg = $langs->trans("ErrorDoNotProvideAccountsIfNullAmount");
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'createsubscription';
$action = 'addsubscription';
}
}
}
@@ -337,7 +335,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$db->commit();
} else {
$db->rollback();
$action = 'createsubscription';
$action = 'addsubscription';
}
if (!$error) {
@@ -697,11 +695,11 @@ print dol_get_fiche_end();
// Button to create a new subscription if member no draft (-1) neither resiliated (0) neither excluded (-2)
if ($user->hasRight('adherent', 'cotisation', 'creer')) {
if ($action != 'createsubscription' && $action != 'create_thirdparty') {
if ($action != 'addsubscription' && $action != 'create_thirdparty') {
print '<div class="tabsAction">';
if ($object->status > 0) {
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$rowid.'&action=createsubscription">'.$langs->trans("AddSubscription")."</a></div>";
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$rowid.'&action=addsubscription&token='.newToken().'">'.$langs->trans("AddSubscription")."</a></div>";
} else {
print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("AddSubscription").'</a></div>';
}
@@ -713,7 +711,7 @@ if ($user->hasRight('adherent', 'cotisation', 'creer')) {
/*
* List of subscriptions
*/
if ($action != 'createsubscription' && $action != 'create_thirdparty') {
if ($action != 'addsubscription' && $action != 'create_thirdparty') {
$sql = "SELECT d.rowid, d.firstname, d.lastname, d.societe, d.fk_adherent_type as type,";
$sql .= " c.rowid as crowid, c.subscription,";
$sql .= " c.datec, c.fk_type as cfk_type,";
@@ -822,7 +820,7 @@ if ($action != 'createsubscription' && $action != 'create_thirdparty') {
}
if (($action != 'createsubscription' && $action != 'create_thirdparty')) {
if (($action != 'addsubscription' && $action != 'create_thirdparty')) {
// Show online payment link
// The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods()
include_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
@@ -841,7 +839,7 @@ if (($action != 'createsubscription' && $action != 'create_thirdparty')) {
/*
* Add new subscription form
*/
if (($action == 'createsubscription' || $action == 'create_thirdparty') && $user->hasRight('adherent', 'cotisation', 'creer')) {
if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->hasRight('adherent', 'cotisation', 'creer')) {
print '<br>';
print load_fiche_titre($langs->trans("NewCotisation"));
@@ -934,7 +932,7 @@ if (($action == 'createsubscription' || $action == 'create_thirdparty') && $user
// If customer code was forced to "required", we ask it at creation to avoid error later
if (getDolGlobalString('MAIN_COMPANY_CODE_ALWAYS_REQUIRED')) {
$tmpcompany = new Societe($db);
$tmpcompany->name = (string) $companyname;
$tmpcompany->name = $companyname;
$tmpcompany->get_codeclient($tmpcompany, 0);
$customercode = $tmpcompany->code_client;
$formquestion[] = array(

View File

@@ -2,7 +2,6 @@
/* Copyright (C) 2007-2019 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -345,7 +344,7 @@ if ($rowid && $action != 'edit') {
print '<tr><td>'.$langs->trans("Amount").'</td><td class="valeur"><span class="amount">'.price($object->amount).'</span></td></tr>';
// Label
print '<tr><td>'.$langs->trans("Label").'</td><td class="valeur sensiblehtmlcontent">'.dol_string_onlythesehtmltags(dol_htmlentitiesbr((string) $object->note_public)).'</td></tr>';
print '<tr><td>'.$langs->trans("Label").'</td><td class="valeur sensiblehtmlcontent">'.dol_string_onlythesehtmltags(dol_htmlentitiesbr($object->note_public)).'</td></tr>';
// Bank line
if (isModEnabled("bank") && (getDolGlobalString('ADHERENT_BANK_USE') || $object->fk_bank)) {

View File

@@ -91,15 +91,13 @@ $label = GETPOST("label", "alpha");
$morphy = GETPOST("morphy", "alpha");
$status = GETPOST("status", "intcomma");
$subscription = GETPOSTINT("subscription");
$caneditamount = GETPOSTINT("caneditamount");
$minimumamount = GETPOST('minimumamount', 'alpha');
$amount = GETPOST('amount', 'alpha');
$amountformuladescription = GETPOST("amountformuladescription", 'restricthtml');
$duration_value = GETPOSTINT('duration_value');
$duration_unit = GETPOST('duration_unit', 'alpha');
$vote = GETPOSTINT("vote");
$comment = GETPOST("comment", 'restricthtml');
$mail_valid = GETPOST("mail_valid", 'restricthtml');
$caneditamount = GETPOSTINT("caneditamount");
// Initialize a technical object
$object = new AdherentType($db);
@@ -174,10 +172,8 @@ if ($action == 'add' && $user->hasRight('adherent', 'configurer')) {
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (string) (int) $subscription;
$object->caneditamount = $caneditamount;
$object->minimumamount = ($minimumamount == '' ? '' : price2num($minimumamount, 'MT'));
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->amountformuladescription = trim($amountformuladescription);
$object->caneditamount = $caneditamount;
$object->duration_value = $duration_value;
$object->duration_unit = $duration_unit;
$object->note_public = trim($comment);
@@ -237,10 +233,8 @@ if ($action == 'update' && $user->hasRight('adherent', 'configurer')) {
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (string) (int) $subscription;
$object->caneditamount = $caneditamount;
$object->minimumamount = $minimumamount;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->amountformuladescription = trim($amountformuladescription);
$object->caneditamount = $caneditamount;
$object->duration_value = $duration_value;
$object->duration_unit = $duration_unit;
$object->note_public = trim($comment);
@@ -302,7 +296,7 @@ $totalarray = [
if (!$rowid && $action != 'create' && $action != 'edit') {
//print dol_get_fiche_head([]);
$sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.caneditamount, d.minimumamount, d.amount, d.amountformuladescription, d.vote,";
$sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.caneditamount, d.vote,";
$sql .= " d.statut as status, d.morphy, d.duration,";
$sql .= " d.tms";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d";
@@ -386,20 +380,12 @@ if (!$rowid && $action != 'create' && $action != 'edit') {
print '<th class="center">'.$langs->trans("SubscriptionRequired").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.caneditamount']['checked'])) {
print '<th class="center">'.$langs->trans("CanEditAmountShort").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.minimumamount']['checked'])) {
print '<th class="center">'.$langs->trans("MinimumAmountShort").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.amount']['checked'])) {
print '<th class="center">'.$langs->trans("RecommendedAmount").'</th>';
print '<th class="center">'.$langs->trans("Amount").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.amountformuladescription']['checked'])) {
print '<th class="center">'.$langs->trans("AmountFormulaDescription").'</th>';
if (!empty($arrayfields['t.caneditamount']['checked'])) {
print '<th class="center">'.$langs->trans("CanEditAmountShort").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.vote']['checked'])) {
@@ -437,10 +423,8 @@ if (!$rowid && $action != 'create' && $action != 'edit') {
$membertype->label = $objp->rowid;
$membertype->status = $objp->status;
$membertype->subscription = $objp->subscription;
$membertype->caneditamount = $objp->caneditamount;
$membertype->minimumamount = $objp->minimumamount;
$membertype->amount = $objp->amount;
$membertype->amountformuladescription = $objp->amountformuladescription;
$membertype->caneditamount = $objp->caneditamount;
if ($mode == 'kanban') {
if ($i == 0) {
@@ -499,27 +483,17 @@ if (!$rowid && $action != 'create' && $action != 'edit') {
if (!empty($arrayfields['t.subscription']['checked'])) {
print '<td class="center">'.yn($objp->subscription).'</td>';
}
if (!empty($arrayfields['t.caneditamount']['checked'])) {
print '<td class="center">'.yn($objp->caneditamount).'</td>';
}
if (!empty($arrayfields['t.minimumamount']['checked'])) {
print '<td class="center">'.price($objp->minimumamount).'</td>';
}
if (!empty($arrayfields['t.amount']['checked'])) {
print '<td class="center">';
$amount = (is_null($objp->amount) || $objp->amount === '' ? '' : price($objp->amount));
$minimumamount = (is_null($objp->minimumamount) || $objp->minimumamount === '' ? '' : price($objp->minimumamount));
print '<span class="amount">'.$amount.'</span>';
if ($amount && $amount < (float) getDolGlobalInt("MEMBER_MIN_AMOUNT")) {
print img_warning('Amount lower than minimum of '.price(getDolGlobalInt("MEMBER_MIN_AMOUNT")).' defined in setup');
}
if ($amount && $minimumamount && $amount < $minimumamount) {
print img_warning('Amount lower than minimum of '.price($minimumamount).' defined in setup');
}
print '</td>';
}
if (!empty($arrayfields['t.amountformuladescription']['checked'])) {
print '<td class="center">'.dol_escape_htmltag($objp->amountformuladescription).'</td>';
if (!empty($arrayfields['t.caneditamount']['checked'])) {
print '<td class="center">'.yn($objp->caneditamount).'</td>';
}
if (!empty($arrayfields['t.vote']['checked'])) {
print '<td class="center">'.yn($objp->vote).'</td>';
@@ -598,22 +572,13 @@ if ($action == 'create') {
print $form->selectyesno("subscription", 1, 1);
print '</td></tr>';
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmount")).'</td><td>';
print $form->selectyesno("caneditamount", GETPOSTISSET('caneditamount') ? GETPOST('caneditamount') : 0, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("MinimumAmountShort").'</td><td>';
print '<input name="minimumamount" size="5" value="'.(GETPOSTISSET('minimumamount') ? GETPOST('minimumamount') : price($minimumamount)).'">';
print '</td></tr>';
print '<tr><td>'.$langs->trans("RecommendedAmount").'</td><td>';
print '<tr><td>'.$langs->trans("Amount").'</td><td>';
print '<input name="amount" size="5" value="'.(GETPOSTISSET('amount') ? GETPOST('amount') : '').'">';
print '</td></tr>';
print '<tr><td class="tdtop">'.$langs->trans("AmountFormulaDescription").'</td><td>';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$doleditor = new DolEditor('amountformuladescription', (GETPOSTISSET('amountformuladescription') ? GETPOST('amountformuladescription', 'restricthtml') : $object->amountformuladescription), '', 100, 'dolibarr_notes', '', false, true, isModEnabled('fckeditor'), 15, '90%');
$doleditor->Create();
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmount")).'</td><td>';
print $form->selectyesno("caneditamount", GETPOSTISSET('caneditamount') ? GETPOST('caneditamount') : 0, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("VoteAllowed").'</td><td>';
print $form->selectyesno("vote", GETPOSTISSET("vote") ? GETPOST('vote', 'aZ09') : 1, 1);
@@ -684,29 +649,17 @@ if ($rowid > 0) {
print '</tr>';
// Amount
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmount")).'</td><td>';
print yn($object->caneditamount);
print '</td></tr>';
print '<tr><td class="titlefield">'.$langs->trans("MinimumAmountShort").'</td><td>';
$minimumamount = ((is_null($object->minimumamount) || $object->minimumamount === '') ? '' : price($object->minimumamount));
print $minimumamount;
print '</tr>';
print '<tr><td class="titlefield">'.$langs->trans("RecommendedAmount").'</td><td>';
print '<tr><td class="titlefield">'.$langs->trans("Amount").'</td><td>';
$amount = ((is_null($object->amount) || $object->amount === '') ? '' : price($object->amount));
print '<span class="amount">'.$amount.'</span>';
if ($amount && $amount < (float) getDolGlobalInt("MEMBER_MIN_AMOUNT")) {
print ' '.img_warning('Amount lower than minimum of '.price(getDolGlobalInt("MEMBER_MIN_AMOUNT")).' defined in setup');
}
if ($amount && $minimumamount && $amount < $minimumamount) {
print ' '.img_warning('Amount lower than minimum of '.price($minimumamount).' defined in setup');
}
print '</tr>';
print '<tr><td class="tdtop">'.$langs->trans("AmountFormulaDescription").'</td><td><div class="longmessagecut">';
print dol_string_onlythesehtmltags(dol_htmlentitiesbr($object->amountformuladescription));
print "</div></td></tr>";
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmount")).'</td><td>';
print yn($object->caneditamount);
print '</td></tr>';
print '<tr><td>'.$langs->trans("VoteAllowed").'</td><td>';
print yn($object->vote);
@@ -728,7 +681,7 @@ if ($rowid > 0) {
// Description
print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td><div class="longmessagecut">';
print dol_string_onlythesehtmltags(dol_htmlentitiesbr((string) $object->note_public));
print dol_string_onlythesehtmltags(dol_htmlentitiesbr($object->note_public));
print "</div></td></tr>";
// Welcome email content
@@ -1143,28 +1096,15 @@ if ($rowid > 0) {
print $form->selectyesno("subscription", $object->subscription, 1);
print '</td></tr>';
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmountDetail")).'</td><td>';
print $form->selectyesno("caneditamount", $object->caneditamount, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("MinimumAmountShort").'</td><td>';
$minimumamount = ((is_null($object->minimumamount) || $object->minimumamount === '') ? '' : price($object->minimumamount));
print '<input name="minimumamount" size="5" value="';
print $minimumamount;
print '">';
print '</td></tr>';
print '<tr><td>'.$langs->trans("RecommendedAmount").'</td><td>';
print '<tr><td>'.$langs->trans("Amount").'</td><td>';
$amount = ((is_null($object->amount) || $object->amount === '') ? '' : price($object->amount));
print '<input name="amount" size="5" value="';
print $amount;
print '">';
print '</td></tr>';
print '<tr><td class="tdtop">'.$langs->trans("AmountFormulaDescription").'</td><td>';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
$doleditor = new DolEditor('amountformuladescription', $object->amountformuladescription, '', 220, 'dolibarr_notes', '', false, true, isModEnabled('fckeditor'), 15, '90%');
$doleditor->Create();
print '<tr><td>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmountDetail")).'</td><td>';
print $form->selectyesno("caneditamount", $object->caneditamount, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("VoteAllowed").'</td><td>';

View File

@@ -3,7 +3,7 @@
* Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2011-2013 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -430,9 +430,9 @@ if (getDolGlobalString('BARCODE_USE_ON_PRODUCT') || getDolGlobalString('BARCODE_
print dol_escape_htmltag($obj->label);
print "</td><td>\n";
print $langs->trans('BarcodeDesc'.$obj->encoding);
// print "The EAN consists of 8 characters, 7 digits plus a control digit.";
// print "The use of EAN8 symbols requires subscription to organizations such as GENCOD.";
// print "Numeric codes are used exclusively for the identification of products that are likely to be sold to the general public.";
//print "L'EAN se compose de 8 characters, 7 chiffres plus une cle de verification.<br>";
//print "L'utilisation des symbologies EAN8 impose la souscription et l'abonnement aupres d'organismes comme GENCOD.<br>";
//print "Codes numeriques utilises exclusivement a l'identification des produits susceptibles d'etre vendus au grand public.";
print '</td>';
// Show example
@@ -520,7 +520,7 @@ if (getDolGlobalString('BARCODE_USE_ON_PRODUCT') || getDolGlobalString('BARCODE_
print '<td>'.$langs->trans("GenbarcodeLocation").'</td>';
print '<td width="60" class="center">';
print '<input type="text" size="40" name="GENBARCODE_LOCATION" value="'.getDolGlobalString('GENBARCODE_LOCATION').'">';
if (getDolGlobalString('GENBARCODE_LOCATION') && !@file_exists(getDolGlobalString('GENBARCODE_LOCATION'))) {
if (getDolGlobalString('GENBARCODE_LOCATION') && !@file_exists($conf->global->GENBARCODE_LOCATION)) {
$langs->load("errors");
print '<br><span class="error">'.$langs->trans("ErrorFileNotFound", getDolGlobalString('GENBARCODE_LOCATION')).'</span>';
}

View File

@@ -11,7 +11,7 @@
* Copyright (C) 2011-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2019-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2019-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2020-2022 Open-Dsi <support@open-dsi.fr>
* Copyright (C) 2024-2025 Charlene Benke <charlene@patas-monkey.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
@@ -1053,7 +1053,7 @@ if (empty($reshook)) {
// Modify entry
$sql = "UPDATE ".MAIN_DB_PREFIX.$tablename." SET ";
// Update fields value
// Modifie value of fields
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $tabrowid[$id]."=";
$sql .= "'".$db->escape($rowid)."', ";
@@ -1378,7 +1378,6 @@ if (empty($reshook)) {
*/
$form = new Form($db);
$formother = new FormOther($db);
$title = $langs->trans("DictionarySetup");
@@ -2626,8 +2625,6 @@ if ($id > 0) {
$valuetoshow = price2num($valuetoshow);
} elseif ($value == 'type' && $id == DICT_ACTIONCOMM && !empty($obj->module)) {
$titletoshow = $langs->trans("Module").' '.$obj->module;
} elseif ($value == 'color') {
$valuetoshow = $formother->showColor($obj->{$value}, '');
}
@@ -2832,13 +2829,14 @@ $db->close();
function dictFieldList($fieldlist, $obj = null, $tabname = '', $context = '')
{
global $langs, $db, $mysoc;
global $form, $formother;
global $form;
global $region_id;
global $elementList, $sourceList, $localtax_typeList, $type_vatList;
$formadmin = new FormAdmin($db);
$formcompany = new FormCompany($db);
$formaccounting = new FormAccounting($db);
$formother = new FormOther($db);
$withentity = '';

View File

@@ -662,8 +662,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
'cc' => array('label' => 'Cc', 'data-placeholder' => $langs->trans('SearchString')),
'bcc' => array('label' => 'Bcc', 'data-placeholder' => $langs->trans('SearchString')),
'replyto' => array('label' => 'ReplyTo', 'data-placeholder' => $langs->trans('SearchString')),
'excludeemail' => array('label' => 'EmailCollectorExcludeEmails', 'data-placeholder' => $langs->trans('EmailCollectorExcludeEmailsPlaceholder')),
'excludedomain' => array('label' => 'EmailCollectorExcludeDomains', 'data-placeholder' => $langs->trans('EmailCollectorExcludeDomainsPlaceholder')),
'subject' => array('label' => 'Subject', 'data-placeholder' => $langs->trans('SearchString')),
'body' => array('label' => 'Body', 'data-placeholder' => $langs->trans('SearchString')),
// disabled because PHP imap_search is not compatible IMAPv4, only IMAPv2

View File

@@ -788,7 +788,7 @@ if ($conf->use_javascript_ajax) {
print ajax_constantonoff('MAIN_IMAP_USE_PHPIMAP');
} else {
$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
print $form->selectarray("MAIN_IMAP_USE_PHPIMAP", $arrval, getDolGlobalString("MAIN_IMAP_USE_PHPIMAP"));
print $form->selectarray("MAIN_IMAP_USE_PHPIMAP", $arrval, $conf->global->MAIN_IMAP_USE_PHPIMAP);
}
print '</td>';
print '</tr>';

View File

@@ -156,7 +156,7 @@ if (empty($reshook)) {
}
if (!$error) {
header('Location: ' . $_SERVER['PHP_SELF']);
header('Location: '.DOL_URL_ROOT.'/admin/expensereport_rules.php');
exit;
} else {
$action = '';
@@ -170,7 +170,7 @@ if (empty($reshook)) {
dol_print_error($object->db);
}
header('Location: ' . $_SERVER['PHP_SELF']);
header('Location: ' . DOL_URL_ROOT.'/admin/expensereport_rules.php');
exit;
}

View File

@@ -7,7 +7,7 @@
* Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2020 Tobias Sekan <tobias.sekan@startmail.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -61,7 +61,7 @@ if (!$user->admin) {
*/
$error = 0;
// Set the variable for the number of external RSS
// positionne la variable pour le nombre de rss externes
$sql = "SELECT ".$db->decrypt('name')." as name FROM ".MAIN_DB_PREFIX."const";
$sql .= " WHERE ".$db->decrypt('name')." LIKE 'EXTERNAL_RSS_URLRSS_%'";
//print $sql;

View File

@@ -7,7 +7,7 @@
* Copyright (C) 2005-2011 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2020 Tobias Sekan <tobias.sekan@startmail.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -193,8 +193,7 @@ if ($action == 'updatesocialnetwork') {
$paramsKey = GETPOST('paramsKey', 'array');
$paramsVal = GETPOST('paramsVal', 'array');
$result = getDolGlobalString("SOCIAL_NETWORKS_DATA_".$name);
$result = dolibarr_get_const($db, "SOCIAL_NETWORKS_DATA_".$name, $conf->entity);
$socialNetworkData = json_decode($result, true);
foreach ($paramsKey as $index => $key) {
@@ -245,9 +244,7 @@ if ($action == 'editsocialnetwork' && GETPOST('confirm') == 'yes') {
$paramKey = GETPOST('paramkey', 'alpha');
$key = GETPOST('key', 'alpha');
$name = GETPOST('name');
$result = getDolGlobalString("SOCIAL_NETWORKS_DATA_".$name);
$result = dolibarr_get_const($db, "SOCIAL_NETWORKS_DATA_".$name, $conf->entity);
$socialNetworkData = json_decode($result, true);
unset($socialNetworkData[$paramKey]);
@@ -352,7 +349,7 @@ foreach ($oauthservices as $key => $value) {
/** @phan-var-force array<string, array{label:string, data-html:string, disable?:int, css?:string}> $oauthservices */
if (!isModEnabled('multicompany') || ($user->admin && !$user->entity)) {
print $form->selectarray('OAUTH_SERVICE_SOCIAL_NETWORK', $oauthservicesStringKeys, (string) getDolGlobalString("OAUTH_SERVICE_SOCIAL_NETWORK"));
print $form->selectarray('OAUTH_SERVICE_SOCIAL_NETWORK', $oauthservicesStringKeys, (string) $conf->global->OAUTH_SERVICE_SOCIAL_NETWORK);
} else {
$selectedKey = (string) getDolGlobalString('OAUTH_SERVICE_SOCIAL_NETWORK');
$text = isset($oauthservicesStringKeys[$selectedKey]) ? $oauthservicesStringKeys[$selectedKey]['label'] : '';
@@ -390,17 +387,17 @@ print '<script type="text/javascript">
$(document).ready(function() {
function toggleOAuthServiceDisplay() {
if ($("#radio_oauth").is(":checked")) {
$("#oauth_service_div").show(); // Show the OAuth selector
$("#oauth_service_div").show(); // Afficher le sélecteur OAuth
} else {
$("#oauth_service_div").hide(); // Hide the OAuth selector
$("#oauth_service_div").hide(); // Cacher le sélecteur OAuth
}
}
function toggleAddParamRow() {
if ($("#radio_oauth").is(":checked")) {
$("#add_param_row").hide(); // Hide the entire line
$("#add_param_row").hide(); // Cacher toute la ligne
} else {
$("#add_param_row").show(); // Show the entire line
$("#add_param_row").show(); // Afficher toute la ligne
}
}

View File

@@ -49,7 +49,7 @@ $langs->loadLangs(array("admin", "errors"));
$action = GETPOST('action', 'aZ09');
if (!getDolGlobalString("GEOIP_VERSION")) {
if (!isset($conf->global->GEOIP_VERSION)) {
$conf->global->GEOIP_VERSION = '2';
}

View File

@@ -300,7 +300,7 @@ if ($action == 'update') {
$dirforimage = $conf->mycompany->dir_output . '/logos/';
if ($_FILES[$varforimage]["tmp_name"]) {
$reg = array();
if (preg_match('/([^\\/:]+)$/i', (string) $_FILES[$varforimage]["name"], $reg)) {
if (preg_match('/([^\\/:]+)$/i', $_FILES[$varforimage]["name"], $reg)) {
$original_file = $reg[1];
$isimage = image_format_supported($original_file);

View File

@@ -875,16 +875,14 @@ print '<input type="submit" class="button button-edit reposition" value="'.$lang
print "</td></tr>\n";
print '</form>';
print '<tr class="oddeven"><td>'.$langs->trans("InvoiceCheckPosteriorDate"). '&nbsp;' ;
print $form->textwithpicto('', $langs->trans("InvoiceCheckPosteriorDateHelp"), 1, 'help') . '</td>';
print '<td class="left" colspan="2">';
//if (!getDolGlobalInt('FAC_FORCE_DATE_VALIDATION')) { // If date is forced, this option to check become useless (it should be if you male import manually, it may be not)
print ajax_constantonoff('INVOICE_CHECK_POSTERIOR_DATE');
/*} else {
print img_picto($langs->trans("PreviousOptionGuaranteeThatDateIsAlwaysHigher"), 'switch_off', 'class="opacitymedium"');
}*/
print '</td></tr>';
// Allow external download
print '<tr class="oddeven">';
print '<td>'.$langs->trans("AllowExternalDownload").'</td>';

View File

@@ -118,7 +118,7 @@ $form->load_cache_conditions_paiements();
if (getDolGlobalString('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID') && isset($form->cache_conditions_paiements[getDolGlobalString('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID')]['label'])) {
$item->fieldOutputOverride = $form->cache_conditions_paiements[getDolGlobalString('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID')]['label'];
}
$item->fieldInputOverride = $form->getSelectConditionsPaiements(getDolGlobalInt("INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID"), 'INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID', -1, 1);
$item->fieldInputOverride = $form->getSelectConditionsPaiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID', -1, 1);
/*

View File

@@ -298,11 +298,11 @@ if (function_exists("ldap_connect")) {
if (getDolGlobalString('LDAP_ADMIN_DN') && getDolGlobalString('LDAP_ADMIN_PASS')) {
if ($result == 2) {
print img_picto('', 'info').' ';
print '<span class="ok">'.$langs->trans("LDAPBindOK", $ldap->connectedServer, getDolGlobalString('LDAP_SERVER_PORT'), getDolGlobalString('LDAP_ADMIN_DN'), preg_replace('/./i', '*', getDolGlobalString("LDAP_ADMIN_PASS"))).'</span>';
print '<span class="ok">'.$langs->trans("LDAPBindOK", $ldap->connectedServer, getDolGlobalString('LDAP_SERVER_PORT'), getDolGlobalString('LDAP_ADMIN_DN'), preg_replace('/./i', '*', $conf->global->LDAP_ADMIN_PASS)).'</span>';
print '<br>';
} else {
print img_picto('', 'error').' ';
print '<span class="error">'.$langs->trans("LDAPBindKO", $ldap->connectedServer, getDolGlobalString('LDAP_SERVER_PORT'), getDolGlobalString('LDAP_ADMIN_DN'), preg_replace('/./i', '*', getDolGlobalString("LDAP_ADMIN_PASS"))).'</span>';
print '<span class="error">'.$langs->trans("LDAPBindKO", $ldap->connectedServer, getDolGlobalString('LDAP_SERVER_PORT'), getDolGlobalString('LDAP_ADMIN_DN'), preg_replace('/./i', '*', $conf->global->LDAP_ADMIN_PASS)).'</span>';
print '<br>';
print $langs->trans("Error").' '.$ldap->error;
print '<br>';

View File

@@ -208,14 +208,14 @@ if ($action == 'edit') {
print '<tr class="oddeven"><td>';
print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_UNIT"), $langs->trans("ParameterActiveForNextInputOnly"));
print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalsunit) ? $conf->global->$mainmaxdecimalsunit : getDolGlobalString("MAIN_MAX_DECIMALS_UNIT")).'</td></tr>';
print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalsunit) ? $conf->global->$mainmaxdecimalsunit : $conf->global->MAIN_MAX_DECIMALS_UNIT).'</td></tr>';
print '<tr class="oddeven"><td>';
print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_TOT"), $langs->trans("ParameterActiveForNextInputOnly"));
print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalstot) ? $conf->global->$mainmaxdecimalstot : getDolGlobalString("MAIN_MAX_DECIMALS_TOT")).'</td></tr>';
print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalstot) ? $conf->global->$mainmaxdecimalstot : $conf->global->MAIN_MAX_DECIMALS_TOT).'</td></tr>';
print '<tr class="oddeven"><td>'.$langs->trans("MAIN_MAX_DECIMALS_SHOWN").'</td>';
print '<td align="right">'.(isset($conf->global->$mainmaxdecimalsshown) ? $conf->global->$mainmaxdecimalsshown : getDolGlobalString("MAIN_MAX_DECIMALS_SHOWN")).'</td></tr>';
print '<td align="right">'.(isset($conf->global->$mainmaxdecimalsshown) ? $conf->global->$mainmaxdecimalsshown : $conf->global->MAIN_MAX_DECIMALS_SHOWN).'</td></tr>';
print '<tr class="oddeven"><td>';
print $form->textwithpicto($langs->trans("MAIN_ROUNDING_RULE_TOT"), $langs->trans("ParameterActiveForNextInputOnly"));

View File

@@ -162,7 +162,7 @@ print '<tr class="oddeven"><td>';
$help = img_help(1, $langs->trans("EMailHelpMsgSPFDKIM"));
print $langs->trans("MailingEMailFrom") . ' ' . $help . '</td><td>';
print '<input class="minwidth100" type="text" name="MAILING_EMAIL_FROM" value="' . getDolGlobalString('MAILING_EMAIL_FROM') . '">';
if (getDolGlobalString('MAILING_EMAIL_FROM') && !isValidEmail(getDolGlobalString('MAILING_EMAIL_FROM'))) {
if (getDolGlobalString('MAILING_EMAIL_FROM') && !isValidEmail($conf->global->MAILING_EMAIL_FROM)) {
print ' ' . img_warning($langs->trans("BadEMail"));
}
print '</td>';

View File

@@ -28,6 +28,10 @@
// Load Dolibarr environment
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -36,9 +40,6 @@ require '../main.inc.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("companies", "products", "admin", "mails", "other", "errors"));

View File

@@ -570,21 +570,7 @@ if ($action == 'edit') {
print dol_get_fiche_head($head, 'common_emailing', '', -1);
print '<span class="opacitymedium">'.$langs->trans("EMailsDesc")."</span><br>\n";
print "<br>\n";
print $langs->trans("MAIN_DISABLE_ALL_MAILS");
if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('MAIN_DISABLE_ALL_MAILS', array(), null, 0, 0, 1, 2, 0, 0, '_red').'</a>';
} else {
print yn(getDolGlobalString('MAIN_DISABLE_ALL_MAILS'));
if (getDolGlobalString('MAIN_DISABLE_ALL_MAILS')) {
print img_warning($langs->trans("Disabled"));
}
}
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br><br>\n";
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="noborder centpercent">';

View File

@@ -589,21 +589,7 @@ if ($action == 'edit') {
print dol_get_fiche_head($head, 'common_passwordreset', '', -1);
print '<span class="opacitymedium">'.$langs->trans("EMailsDesc")."</span><br>\n";
print "<br>\n";
print $langs->trans("MAIN_DISABLE_ALL_MAILS");
if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('MAIN_DISABLE_ALL_MAILS', array(), null, 0, 0, 1, 2, 0, 0, '_red').'</a>';
} else {
print yn(getDolGlobalString('MAIN_DISABLE_ALL_MAILS'));
if (getDolGlobalString('MAIN_DISABLE_ALL_MAILS')) {
print img_warning($langs->trans("Disabled"));
}
}
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br><br>\n";
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="noborder centpercent">';

View File

@@ -11,7 +11,7 @@
* Copyright (C) 2011-2016 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2015-2024 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Vincent Maury <vmaury@timgroup.fr>
* Copyright (C) 2025 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
@@ -790,8 +790,8 @@ if ($action == 'create') {
// Line to enter new values (title)
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine the field name based on the possible names
// in the data dictionaries.
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
$valuetoshow = ucfirst($fieldlist[$field]); // Par default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$css = "left";

View File

@@ -564,21 +564,7 @@ if ($action == 'edit') {
print dol_get_fiche_head($head, 'common_ticket', '', -1);
print '<span class="opacitymedium">'.$langs->trans("EMailsDesc")."</span><br>\n";
print "<br>\n";
print $langs->trans("MAIN_DISABLE_ALL_MAILS");
if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('MAIN_DISABLE_ALL_MAILS', array(), null, 0, 0, 1, 2, 0, 0, '_red').'</a>';
} else {
print yn(getDolGlobalString('MAIN_DISABLE_ALL_MAILS'));
if (getDolGlobalString('MAIN_DISABLE_ALL_MAILS')) {
print img_warning($langs->trans("Disabled"));
}
}
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br><br>\n";
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="noborder centpercent">';

View File

@@ -196,7 +196,7 @@ print '<tr class="oddeven"><td>'.$langs->trans("DefaultMenuSmartphoneManager").'
print '<td>';
$formadmin->select_menu(getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED', getDolGlobalString('MAIN_MENU_SMARTPHONE')), 'MAIN_MENU_SMARTPHONE', array_merge($dirstandard, $dirsmartphone), !getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') ? '' : ' disabled');
if (getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') && preg_match('/smartphone/', getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED'))
if (getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') && preg_match('/smartphone/', $conf->global->MAIN_MENU_SMARTPHONE_FORCED)
|| (!getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') && getDolGlobalString('MAIN_MENU_SMARTPHONE') && preg_match('/smartphone/', getDolGlobalString('MAIN_MENU_SMARTPHONE')))) {
print ' '.img_warning($langs->transnoentitiesnoconv("ThisForceAlsoTheme"));
}
@@ -205,7 +205,7 @@ print '</td>';
print '<td>';
$formadmin->select_menu(getDolGlobalString('MAIN_MENUFRONT_SMARTPHONE_FORCED', getDolGlobalString('MAIN_MENUFRONT_SMARTPHONE')), 'MAIN_MENUFRONT_SMARTPHONE', array_merge($dirstandard, $dirsmartphone), !getDolGlobalString('MAIN_MENUFRONT_SMARTPHONE_FORCED') ? '' : ' disabled');
if (getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') && preg_match('/smartphone/', getDolGlobalString("MAIN_MENUFRONT_SMARTPHONE_FORCED"))
if (getDolGlobalString('MAIN_MENU_SMARTPHONE_FORCED') && preg_match('/smartphone/', $conf->global->MAIN_MENUFRONT_SMARTPHONE_FORCED)
|| (!getDolGlobalString('MAIN_MENUFRONT_SMARTPHONE_FORCED') && getDolGlobalString('MAIN_MENU_SMARTPHONE') && preg_match('/smartphone/', getDolGlobalString('MAIN_MENUFRONT_SMARTPHONE')))) {
print ' '.img_warning($langs->transnoentitiesnoconv("ThisForceAlsoTheme"));
}

View File

@@ -3,7 +3,7 @@
* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2009-2011 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2016 Meziane Sof <virtualsof@yahoo.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 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
@@ -513,7 +513,7 @@ if ($action == 'create') {
print ', <span class="opacitymedium">'.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def</span>';
print '</td></tr>';
// Level
// Niveau
//print '<tr><td>'.$langs->trans('Level').'</td><td>'.$menu->level.'</td><td>'.$langs->trans('DetailLevel').'</td></tr>';
// Title

View File

@@ -207,8 +207,8 @@ if ($action == 'up') {
$form = new Form($db);
$formadmin = new FormAdmin($db);
$arrayofjs = array('/public/includes/jquery/plugins/jquerytreeview/jquery.treeview.js', '/public/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js');
$arrayofcss = array('/public/includes/jquery/plugins/jquerytreeview/jquery.treeview.css');
$arrayofjs = array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.js', '/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js');
$arrayofcss = array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.css');
llxHeader('', $langs->trans("Menus"), '', '', 0, 0, $arrayofjs, $arrayofcss, '', 'mod-admin page-menus_index');

View File

@@ -414,9 +414,7 @@ if ($action == 'set' && $user->admin) {
// We made some check against evil eternal modules that try to low security options.
$checkOldValue = getDolGlobalInt('CHECKLASTVERSION_EXTERNALMODULE');
$csrfCheckOldValue = getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN');
$resarray = activateModule($value, 1, 0, 'acceptredirect');
$resarray = activateModule($value);
if ($checkOldValue != getDolGlobalInt('CHECKLASTVERSION_EXTERNALMODULE')) {
setEventMessage($langs->trans('WarningModuleHasChangedLastVersionCheckParameter', $value), 'warnings');
}
@@ -460,11 +458,8 @@ if ($action == 'set' && $user->admin) {
if ($result) {
setEventMessages($result, null, 'errors');
header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : ''));
exit;
}
$resarray = activateModule($value, 0, 1, 'acceptredirect');
$resarray = activateModule($value, 0, 1);
dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1), 'chaine', 0, '', $conf->entity);
if (!empty($resarray['errors'])) {
setEventMessages('', $resarray['errors'], 'errors');
@@ -520,7 +515,6 @@ $filename = array();
$modules = array();
$orders = array();
$categ = array();
$timestoinit = [];
//$publisherlogoarray = array();
$i = 0; // is a sequencer of modules found
@@ -534,7 +528,6 @@ foreach ($modulesdir as $dir) {
//print $dir."\n<br>";
dol_syslog("Scan directory ".$dir." for module descriptor files (modXXX.class.php)");
$handle = @opendir($dir);
$timestart = microtime(true);
if (is_resource($handle)) {
while (($file = readdir($handle)) !== false) {
//print "$i ".$file."\n<br>";
@@ -602,7 +595,6 @@ foreach ($modulesdir as $dir) {
// Define an array $categ with categ with at least one qualified module
$filename[$i] = $modName;
$modules[$modName] = $objMod;
$timestoinit[$modName] = round((microtime(true) - $timestart) * 1000, 3);
// Gives the possibility to the module, to provide his own family info and position of this family
if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
@@ -679,7 +671,7 @@ if ($action == 'reset_confirm' && $user->admin) {
}
$form = new Form($db);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?value='.$value.'&mode='.$mode.$param, $langs->trans('ConfirmUnactivation'), $langs->trans(GETPOST('confirm_message_code')), 'reset', '', 'no', 1, 300, 550);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?value='.$value.'&mode='.$mode.$param, $langs->trans('ConfirmUnactivation'), $langs->trans(GETPOST('confirm_message_code')), 'reset', '', 'no', 1);
}
}
@@ -1231,7 +1223,6 @@ if ($mode == 'common' || $mode == 'commonkanban') {
print '<a href="javascript:document_preview(\''.DOL_URL_ROOT.'/admin/modulehelp.php?id='.((int) $objMod->numero).'\',\'text/html\',\''.dol_escape_js($langs->trans("Module")).'\')">';
print img_picto(($objMod->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule").' - ' : '').$langs->trans("ClickToShowDescription"), $imginfo, '', 0, 0, 0, '', 'purple');
print '</a>';
print ($timestoinit[$modName] > 500 ? img_picto($langs->trans('InitModuleIsSlow'), 'fa-exclamation-circle') : '');
print '</td>';
// Version

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