Compare commits

..

1310 Commits

Author SHA1 Message Date
Dolibot
f3d0aad269 PHPStan > Update baseline 2026-02-25 12:18:25 +00:00
Laurent Destailleur
3d1491d312 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-25 11:17:20 +01:00
Laurent Destailleur
9fc1076361 Add new properties on website pages. 2026-02-25 11:17:08 +01:00
minimexat
28563cd261 fix: bank line tags/categories not displayed on record view (#37311)
* Add POST /supplierorders/{id}/line endpoint to REST API (#35286)

* ✏️ Fix spelling

*  Add postLine endpoint to supplier_orders

* 🐛 Fix accessing this->commande instead of this->order

* PHPStan > Update baseline (#35285)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* clean code bookcal class (#35279)

* clean code bookcal class

* clean code bookcal class

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* feat: Subtotal module (#35290)

* clean code contact class (#35260)

* clean code contact class

* clean code contact class

* clean code

* clean code

* clean code

* clean code

* clean code

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Clean code

* Clean code

* Clean code

* Fix trans in list of technical services of a module

* Fix do not show value of last activation module if na

* Add "__EVENT_DESCRIPTION__" variable (#35302)

To be able to add the event's description in reminder emails.

* Remove old lang files that are too small (moved into other lang files)

* Sync transifex

* Fix size of popup

* Fix missing field migration, fix select2

* Clean code

* NEW public and private note can be shown on contact list

* FIX Edit of email in emailing. Property messtype not set.

* PHPStan > Update baseline (#35305)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* fix missing translation (#35314)

* fix translation missing (#35316)

* fix translation missing

* fix translation missing

* fix missing translations (#35315)

* fix missing translations

* fix missing translations

* makepack : exit if filelist fail (#35312)

* Fix exclusion of files is not consistent

* exit code must be >= 0 (#35311)

* NEW add fields usage_opportunity, usage_task, usage_bill_time for project import (#35301)

* 🐛 Use reception email templates for receptions (#35310)

* fix fatal error (#35284)

* fix fatal error

* Update card.php

* Update product.class.php

* clean code adherent (member) class (#35259)

* clean code adherent (member) class

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* fix

* fix

* fix

* fix

* fix

* fix

---------

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

* FIX: setShippingMethod tigger throwing error (#35320)

* FIX: setShippingMethod tigger throwing error

* Update commonobject.class.php

---------

Co-authored-by: brad <brad@endurotags.com.au>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Prepare ci for tag check

* Prepare code for Loi Finance

* clean code (#35317)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* NEW Feature to merge duplicate members (#35308)

* New merge members

* fix fields

* add trans

* fix CI

* fix Ci

* fix Ci

* fix CI

* Fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* fix CI (#35328)

* fix CI

* Update interfaces.class.php

* Update interfaces.class.php

* Update interfaces.class.php

* Update interfaces.class.php

* Update interfaces.class.php

* fix

* fix

* FIX: Update order line (#35321)

Co-authored-by: brad <brad@endurotags.com.au>

* Fix missing translation (#35322)

* fix missing translation

* fix missing translation

* fix missing translation

* fix missing translation

* NEW : Add hooks in webportal (#35326)

* fix missing translation (#35323)

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

* add picto (#35329)

* add picto

* fix padding

* clean code (#35333)

* clean code

* clean code

* clean code

* fix pictos (#35334)

* PHPStan > Update baseline (#35336)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* fix pictos (#35335)

* fix pictos (#35337)

* clean code (#35338)

* clean code

* clean code

* clean code

* clean code

* clean code

* fix civility_id for webportal member (#35339)

* fix civility_id for webportal member

* Update html.formcardwebportal.class.php

* fix

* fix

* fix

* fix date

* fix translation

* add doc

* clean code (#35340)

* clean code

* clean code

* clean code

* add check in dolibarr phpinfo page (#35332)

* add check in phpinfo page

* Update phpinfo.php

---------

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

* Clean code

* FIX Debug bad path used into webportal. Missing http headers in login.

* bcmath is used by swiftmail authent, not implemented.

* Fix date update

* CSS

* FIX webportal must not use resources out public dir neither external
files.

* Clean code. Removed octicons directory.

* css

* css

* Fix bad tab underlined in display setup

* Fix bad recording of custom CSS in webportal

* Debug webportal

* Fix css

* css

* clean code (#35341)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code expedition class (#35327)

* clean code expedition class

* clean code expedition class

* clean code expedition class

* clean code expedition class

* clean code expedition class

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* clean code

* clean code (#35343)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code (#35344)

* clean code

* clean code

* clean code

* clean code

* clean code

* NEW add private and public note on ticket (#35303)

* Update copyright and add note fields in SQL

* Add note_public and note_private columns to llx_ticket

* Implement notes tab in ticket details

* Add fk_user_modif column to llx_ticket table

* Add fk_user_modif column to llx_ticket table

* Add files via upload

* Add private and public note fields to ticket class

* Update ticket.class.php

* Update ticket.class.php

* Update note.php

* Update note.php

* Update note.php

---------

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

* PHPStan > Update baseline (#35342)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* add doc (#35345)

* clean code

* clean code

* clean code (#35346)

* clean code

* clean code

* added tag mass action (#35347)

* Error: When creating an invoice for a supplier order with a negative value #30516

Error: When creating an invoice for a supplier order with a negative value #30516

* Update html.form.class.php

Modifications made related to the issue
Search for variants by EAN #34567

* Update html.form.class.php

I change :

if(getDolGlobalString('SEARCH_VARIANTS_OF_EAN13')){
with
if (getDolGlobalString('SEARCH_VARIANTS_OF_EAN13')) {

and 

SEARCH_VARIANTS_OF_EAN13
into
PRODUIT_ATTRIBUTES_HIDECHILD_BUT_ALLOW_SEARCH_IN_EAN13

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* added tag mass action

added tag mass action

* Update list.php

---------

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

* NEW dol_sort_array can be used with 2 sorting criteria.

* Fix warning

* CSS

* Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop

* CSS

* fix CI (#35353)

* fix CI

* Update header.tpl.php

* Update style.css.php

* Update webportal.main.inc.php

* Update files.lib.php

* Clean code

* clean code (#35350)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code (#35355)

* Debug v23

* Fix warning

* Fix phan

* fix CI (#35359)

* fix CI

* Update card.php

* QUAL: The library timepicker.js has been removed. Was not used by
Dolibarr.

* Fix changelog

* Try git commit

* CSS

* Fix warnings

* Fix try to work on multientity even if cron disable don entity 1.

* Debug v23

* clean code (#35365)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code (#35352)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* Clean code

* Clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* fix CI (#35361)

* fix CI

* Update msg-commit

* Update ruleset.xml

* Debug script

* New develop import export product customer price (#35349)

* NEW import/export product customer price

* back travis and more

* back travis 2

* Fix syntax error

* clean code (#35358)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

---------

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

* FIX The write_file function should return -1 if an error exists (#35368)

* Error: When creating an invoice for a supplier order with a negative value #30516

Error: When creating an invoice for a supplier order with a negative value #30516

* Update html.form.class.php

Modifications made related to the issue
Search for variants by EAN #34567

* Update html.form.class.php

I change :

if(getDolGlobalString('SEARCH_VARIANTS_OF_EAN13')){
with
if (getDolGlobalString('SEARCH_VARIANTS_OF_EAN13')) {

and 

SEARCH_VARIANTS_OF_EAN13
into
PRODUIT_ATTRIBUTES_HIDECHILD_BUT_ALLOW_SEARCH_IN_EAN13

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* Update html.form.class.php

* added tag mass action

added tag mass action

* Update list.php

* Update pdf_crabe.modules.php

The write_file function as its own documentation describes returns 1 0 a value minus 0 if an error exists. Therefore, if there is an error in the hook more than saving the error, it must return 0 since an error occurred

* Update pdf_crabe.modules.php

---------

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

* Fix complete #35368

* Fix:prevent handling update action by  generic include of actions_addupdatedelete.inc.php (#35369)

* Fix:prevent handling update action by  generic include of actions_addupdatedelete.inc.php

Fix:
To prevent handling update action by generic post update action in inventories at /core/actions_addupdatedelete.inc.php, we need to unset $action variable, otherwise $object fileds are filled with with empty values.

* Update inventory.php

---------

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

* clean code (#35367)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

---------

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

* CSS

* Allowed commit

* fix missing translation (#35378)

* clean code (#35379)

* clean code

* clean code

* clean code

* clean code

* Clean code

* add filter by invoice categories in the statistics module (#35388)

add filter by invoice categories in the statistics module

* Clean code

* FIX delivery triggers and mail templates: correct inconsistencies in email triggers and templates` (#35264)

* `fix(delivery): correct inconsistencies in email triggers and templates`

**Body:**
- Adjusted email trigger names from `RECEPTION_*` to `SHIPPING_*`.
- Updated parameters and placeholders for shipment email tracking.
- Removed redundant `reception_send` entry in mail templates for shipping.

* `fix(delivery): update email triggers and templates for deliveries`

**Body:**
- Replaced email trigger `SHIPPING_SENTBYMAIL` with `DELIVERY_SENTBYMAIL`.
- Updated template references from `shipping_*` to `delivery_*` for consistency.
- Modified tracking ID format from `shi` to `del` in `card.php`.
- Added `MailToSendDelivery` language entry for email labels.
- Adjusted mail templates to include `delivery_send` entries.

* FIX CI

* Clean code

* Clean code

* Clean code

* Clean code

* Test

* Clean code with rector

* Fix bad var

* Add constant MAIN_USE_TITLE_FOR_USER to show a property that is not used

* Clean corrupted data

* Doc

* Fix trans

* fix CI 🐛 (#35392)

* add picto

* fix padding

* fix CI

* Update user.class.php

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Refactor VAT array handling in PDF generation (#35395)

$this->tva_array[$vatrate.($vatcode ? ' ('.$vatcode.')' : '')]['amount'] is present on 2 part of the if

* fix Objectlink api (#35402)

* fix objectlink api

* fix objectlink api

* fix objectlink api

---------

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

* feat: add contact list parameter to ticket API endpoints to control contact data retrieval (#35404)

* Qual: Update phan baseline (#35405)

* NEW add supplier invoice, order and supplier order tag filter and bulk insert and statistics order and supplier order (#35399)

* add own supplier invoice tag filter and bulk insert

add own supplier invoice tag filter and bulk insert

* Update list.php

change format

* Bulk edit commande tags

Bulk edit commande tags

* Label filter orders and supplier order statistics

Label filter orders and supplier order statistics

* Supplier Order Label Filter and Mass Action for Supplier Order Labels

Supplier Order Label Filter and Mass Action for Supplier Order Labels

* Update index.php

change format

* Update list.php

change format

* Update index.php

change format

* Update index.php

change format

---------

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

* Repair recalculateinvoicetotal (#35381)

* PHPStan > Update baseline

* FIX#33963 - Enabling foreign key field to allow mandatory parameter saving

* Added author to copyright

* Correction calcul du total des taxes

* Travis

* code format

* espaces superflus

* bis

* Update repair.php

* Update repair.php

* PHPStan > Update baseline

* set paid = 1 when total_ttc equals sum of payments

* current upstream file

---------

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Fix sub BOM quantities (#35371)

* FIX: reqursive bom quantities

Correctly handle quantities on BOM recursion. Current behavior is that
sub BOM total quantity is multiplied by parent quantity for that line,
the expected behaviour is that the parent BOM would be including sub BOM
on a per unit base.

* Simplified code

* Update objectline_view.tpl.php

* Update bom.class.php

* Update bom.class.php

* Update bom.class.php

* Update bom.class.php

---------

Co-authored-by: brad <brad@endurotags.com.au>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Fix roundind using stock accuracy ('MS')

* Cehojac/issue35362 (#35364)

* intervencions api call dont show the objects relations
Fixes #35362

* feat: add loadlinkedobjects parameter to control linked object loading in interventions API

thank you for the recomendarion @eldy !!!!

* Clean code for PDF invoices

* Trans

* Move doc for git commit template

* Clean code

* Clean code

* Enhance AI setup and log report

* Enhance AI setup and log report

* FIX Bad management of carriage return when requesting IA API.

* Trans

* fix CI (#35409)

* fix CI

* fix

* Qual: Fix phan notices (#35406)

* fix CI

* fix

* Qual: Fix newly appeard phan notices

# Qual: Fix newly appeard phan notices

Fix notices that appearce sin a previous phan report - some of these
notices are masked by the current baseline.

---------

Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: Frédéric FRANCE <frederic.france@free.fr>

* Fix syntax

* Problem in Gantt view. Tasks in project (#35412)

Fixes #35411

* fix reminders sms (#35398)

* fix reminders sms

* fix reminders sms

* fix reminders sms

* fix reminders sms

* fix durations

* fix durations

* fix durations

* fix durations

* fix durations

* fix durations

* fix durations

* fix durations

* fix

* fix

* fix

* fix

* fix

* fix

* fix

---------

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

* Fix default mode is edit

* NEW More webportal fonctions - Can add shared files and thirdparty documents (#35391)

* Create documentlist.controller.class.php

Intégration de mon portail client personnalisé avec GED
attention 
class/sontext.class.php devra aussi être modifier.

* Update context.class.php

ajout du ged 
pour les fichiers joints par tiers.

* Update context.class.php

ajout d'accès à fichiers joints du tiers.

* Update menu.tpl.php

ajout du menu accès au GED

* Update README.md

* Update README.md

* Update README.md

* Add files via upload

document utile sert a partager via le GED de dolibarr des fichiers avec tous les clients utilisateur du webportal.

* Update context.class.php

ajout dans le menu de deux controleur suplémentaire.

* Update menu.tpl.php

ajoute des deux chapitre dans le menu

* Update README.md

* Update README.md

* Update menu.tpl.php

document format change

* Add files via upload

mises à jour et normalisation fichiers

* Add files via upload

ajout webportal.lang

* Update README.md

* Delete htdocs/webportal/documentutile.controller.class.php

* Update menu.tpl.php

* Update README.md

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update menu.tpl.php

* Update menu.tpl.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update README.md

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update README.md

* Create webportal.lang

* Update webportal.lang

* Update webportal.lang

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update website.lang

* Delete htdocs/langs/fr_FR/webportal.lang

* Delete htdocs/langs/en_US/webportal.lang

* Update README.md

* Update README.md

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Create abstractdocument.controller.class.php

* Update website.lang

* Update website.lang

* Update website.lang

* Update README.md

* Update README.md

* Update abstractdocument.controller.class.php

* Update shareddocuments.controller.class.php

* Update abstractdocument.controller.class.php

* Update abstractdocument.controller.class.php

* Update README.md

* Update context.class.php

* Update README.md

* Update abstractdocument.controller.class.php

* Update abstractdocument.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update menu.tpl.php

* Update documentlist.controller.class.php

* Update abstractdocument.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update shareddocuments.controller.class.php

* Update documentlist.controller.class.php

* Update menu.tpl.php

* Update menu.tpl.php

* Update README.md

* Update context.class.php

* Update documentlist.controller.class.php

* Update menu.tpl.php

* Update menu.tpl.php

* Update context.class.php

* Update documentlist.controller.class.php

---------

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

* Debug v23

* Debug setup reminders v23

* clean code (#35396)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* fix

---------

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

* clean code (#35387)

* clean code

* clean code

* clean code

* clean code

* clean code

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

---------

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

* fix translation member (#35415)

* Complete parameter for api hook

* add getTimespent on api task (#35263)

* add getTimespent on api task

* Fix return statement in api_tasks.class.php

* Fix return statement in api_tasks.class.php

* Fix formatting and spacing in getTimespent method

* Fix formatting of if statement in getTimespent method

* Update api_tasks.class.php

---------

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

* Clean code. Replace property with local variable.

* Clean code

* QUAL: Removed deprecated properties user_valid, user->creation,
user_modification replaced with user_ceation_id, user_validation_id and
user_modification_id.

* Removed deprecated property ->projet (replace with ->project)

* Fix hack to avoid infinite loop in restler when xdebug is on

* Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop

* clean code (#35419)

* clean code

* clean code

* PHPStan > Update baseline (#35420)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* Fix CI

* Fix color of status

* Update recap-fourn.php (#35417)

* Update recap-fourn.php

The key improvement is that now the balance calculation works correctly with descending order of movements. The balance will show the most recent transaction with the cumulative total of all transactions, and older transactions will show their respective balances as of that time.
This implementation now matches the behavior of compta\recap-compta.php where the balance is calculated from bottom to top when the movements are displayed in descending order.

* Update recap-fourn.php

The key improvement is that now the balance calculation works correctly with descending order of movements. The balance will show the most recent transaction with the cumulative total of all transactions, and older transactions will show their respective balances as of that time.
This implementation now matches the behavior of compta\recap-compta.php where the balance is calculated from bottom to top when the movements are displayed in descending order.

* Update recap-fourn.php

fix reordering by date column

* Update recap-fourn.php

* Update recap-fourn.php

---------

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

* CSS

* Fix CI

* clean code (#35423)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* NEW Add hook initialization for interventions API (#35203)

* NEW Add hook initialization for interventions API

the goal is to enhance the search function on the api (by sample add linked contact or user name)

* Clean up whitespace in api_interventions.class.php

* Fix parameter reference in executeHooks call

* Update api_interventions.class.php

* Update action name in API intervention hooks

* Add 'apimethod' to parameters in API hook

* Update api_interventions.class.php

* Update api_interventions.class.php

---------

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

* Fix 34301 Project selector on supplier proposal filters incorrectly by thirdparty, ignoring global constant (#34498)

* Fix 34301

* Fix issue #34301

* Fix issue #34301

* Update card.php

* Update card.php

---------

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

* QUAL replace $conf->XXX->dir_output by getMultidiroutput (#34446)

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

* replace $conf->XXX->dir output by GetMultidir0utput

---------

Co-authored-by: Theobald <f.moreau@theobald-groupe.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Code comment

* FIX - MRP MO Product to Consume (#35424)

* FIX - MRP MO Product to Consume

Fixes MO Product to Consume when recursive BOM's are used, the product
to consume only includes the BOM line items instead of BOM product

* fix php-stan errors

* fix phan analysis errors

* fix phan analysis errors take 2

---------

Co-authored-by: brad <brad@endurotags.com.au>

* spellcheck war

* Fix select technical id

* fix usage of recipient translation (#35437)

* fix usage of recipient translation

* fix usage of recipient translation

* fix usage of recipient translation

* PHPStan > Update baseline (#35433)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* clean code (#35442)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* Add intuitive table selection (#35444)

Add intuitive table selection with class .row-with-select
Added to propal, order and invoice list

* clean code (#35427)

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

---------

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

* Debug v23

* PHPStan > Update baseline (#35452)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* new: add otherCurlOptions to getURLContent (#35454)

* clean code (#35447)

* clean code

* clean code

* clean code

* contact deletion in api_orders class for internal and external (#35455)

* contact deletion in api_orders class for internal and external

* Update api_orders.class.php

---------

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

* Add check for invoice status before line deletion (#35456)

* Add check for invoice status before line deletion

* Change invoice status check from fk_statut to status

* Test CI

* NEW Make the public contact form with experimental status

* NEW Make the public contact form with experimental status

* NEW API User - Remove user from group (#35453)

* NEW API User - Remove user from group

* Update api_users.class.php

* Update api_users.class.php

---------

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

* clean code (#35451)

* clean code

apiroute is interventions

* Update api_interventions.class.php

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* fix bad condition

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

* clean code

---------

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

* clean code (#35462)

* clean code

* clean code

* clean code

* clean code

* clean code

* Add fields for actioncomm to fix #35422

* Use fields into the list of events

* Debug v23

* FIX: Error on add contact (#35460)

* FIX: Error on add contact

Trigger COMMANDE_ADD_CONTACT causing error when adding a contact to and
order, this fix updates the COMMANDE prefix to ORDER

* FIX: delete contact

This fixes the trigger call for delete contact on orders

* FIX: Update patch

Updated to reflect recent PR to add TRIGGER_PREFIX to commande class

* Update commonobject.class.php

Reduce risk of regression

---------

Co-authored-by: brad <brad@endurotags.com.au>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Clean code

* Doc

* Fix CI

* Fix link to ref of salary payment

* Fix MRP: Add hook calculateCostsBomAfter to alter BOM costs (#35465)

* fix doc (#35416)

* fix doc

* Update commonobject.class.php

* Update mo.class.php

* FIX missing entity filter (#35461)

* Add post-processing hook `calculateCostsBomAfter` in BOM cost calculations

---------

Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: Regis Houssin <regis.houssin@inodbox.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* FIX price.php (#32181)

* FIX price.php

https://github.com/Dolibarr/dolibarr/issues/32180

* Update price.php

* Update price.php

---------

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

* NEW: extrafields: add field to link a field to a module (#34416)

* NEW: extrafields: add field to link a field to a module

* Update 22.0.0-23.0.0.sql

* Update llx_extrafields.sql

* Update 22.0.0-23.0.0.sql

---------

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

* add current date link on Date Delivery Planned (#29876)

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

* fix(bank): fetch bank line object before view to display categories correctly

---------

Co-authored-by: Fabian Volkers <33686912+FabianVolkers@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: HENRY Florian <florian.henry@open-concept.pro>
Co-authored-by: ldestailleur <eldy@destailleur.fr>
Co-authored-by: Liammer <104431491+Liammer@users.noreply.github.com>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: ThomasNgr-OpenDSI <tnegre@open-dsi.fr>
Co-authored-by: Bradley Jarvis <brad@pocketinnovations.com.au>
Co-authored-by: brad <brad@endurotags.com.au>
Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com>
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: kkhelifa-opendsi <kkhelifa@open-dsi.fr>
Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com>
Co-authored-by: Yamil Esteban Garcia <120027058+developmentOYR@users.noreply.github.com>
Co-authored-by: atm-GregM <85485123+atm-GregM@users.noreply.github.com>
Co-authored-by: Bahfir Abbes <bafbes@gmail.com>
Co-authored-by: VIAL-GOUTEYRON Quentin <quentin.vial-gouteyron@atm-consulting.fr>
Co-authored-by: Carlos Herrera <cehojac@gmail.com>
Co-authored-by: MDW <mdeweerd@users.noreply.github.com>
Co-authored-by: Vincent de Grandpré <vincent@de-grandpre.quebec>
Co-authored-by: Frédéric FRANCE <frederic.france@free.fr>
Co-authored-by: webmaster67 <46778677+bigbears67@users.noreply.github.com>
Co-authored-by: ChristosK. <99069049+christoskaterini@users.noreply.github.com>
Co-authored-by: Vincent Maury <artec.vm@arnac.net>
Co-authored-by: vmaury <vmaury@vmaury-ThinkPad-X240>
Co-authored-by: Chloe-Moreau-2009 <chloe.moreau2009@gmail.com>
Co-authored-by: Theobald <f.moreau@theobald-groupe.com>
Co-authored-by: Anthony Damhet <73399671+EchoLoGeek@users.noreply.github.com>
Co-authored-by: kaantopkaya <kaan.topkaya@koesio.com>
Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com>
Co-authored-by: Regis Houssin <regis.houssin@inodbox.com>
Co-authored-by: Norbert Penel <homer8173@gmail.com>
Co-authored-by: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com>
Co-authored-by: Florian Hödl <27991923+f-hoedl@users.noreply.github.com>
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
2026-02-25 00:32:39 +01:00
David Beniamine
a2397ff88b Improve user card performance by avoid mysql OR (#37125)
* Improve user card performance by avoid mysql OR

* Negate first condition to avoid duplicates in UNION

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-24 19:27:40 +01:00
Alexandre SPANGARO
a94c77edd0 NEW Accountancy - Multi reports system (#37248)
* CSS

* CSS

* Fix phpunit

* More legal info

* CI

* Fix CI

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Protect module

* Add currency

* CSS

* WIP LNE

* Fix navigation

* cs

* Debug registration process

* Debug setup navigation

* CI

* CI

* Factorize code

* Fix CI

* Fix CI

* Fix CI

* CI

* CI

* CI

* CI

* Disable phan on v23

* CI

* CI

* FIX: missing include for blockedlog lib (#37165)

* Debug CI

* fix ternary always true (#37161)

* fix ternary always true

* Update requests.php

* Update registration.php

---------

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

* CI

* FIX: missing include for blockedlog lib (#37165)

* FIX #37134 Use json_encode for IMAP search logging in EmailCollector (#37135)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch) as each line becomes a separate log entry.

Using json_encode() produces single-line structured output that works
correctly with all log aggregation tools.

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

* Populate syslog with placeholder (#37163)

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

* Doc

* datamodel for user change password next time (#37155)

* Qual: Update phan baseline (#37172)

* Fix typo in file path (#37160)

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

* Fix phpunit

* Complete call to setStatus so we have a trigy as 4th parameter (help to
fix the #37129)

* FIX Product - Warning on admin (#37157)

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

* FIX Product - Warning on admin + CSS (#37158)

* FIX Product - Warning on admin

* CSS

---------

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

* CI

* CI

* CI

* Avoid error if include fails

* More functions in blacklist (even if nw we use the whitelist by default)

* #37166 [SQL] add: email template for ticket admin creation (#37182)

* Replace var_export with new function formatLogObject (#37178)

* FIX BOM - Class product missing, column offset and information recording (form/input overlap) in admin (#37177)

* FIX BOM - Class product missing in admin

* Fix column offset and information recording (form/input overlap)

* ci

* ci

* FIX Intracommreport - Warning & link problem on tab (#37176)

* FIX Bank transfer admin - Warning & save 0 on constant PAYMENTBYBANKTRANSFER_ADDDAYS (#37175)

* Look and feel v24

* Update default time handling in index.php (#37150)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix CI

* Add template in migration

* fix phpdoc comment (#37184)

* fix phpdoc comment

* fix phpdoc comment

---------

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

* CI

* Fix phpstan

* Replace var_export by formatLogObject (continued) (#37188)

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

* Debug amount suggested on membership public form

* Issue 36923 Fix session title handling in survey creation (#37105)

* Issue 36923 Fix session title handling in survey creation

* Change input field to use id attribute for title

---------

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

* fix phpstan errors blocking action baseline (#37189)

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* refresh baseline

* QUAL Replace var_export() with json_encode() in dol_syslog() calls (#37138)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch, Graylog) as each line becomes a separate
log entry.

json_encode() produces single-line structured output that works correctly
with all log aggregation tools. This pattern is already used elsewhere
in Dolibarr (accountancy, install modules).

Files changed:
- core/class/commoninvoice.class.php (payment intent logging)
- core/class/commonobject.class.php (payment terms logging)
- core/modules/mailings/advthirdparties.modules.php (mailing targets)
- core/modules/oauth/google_oauthcallback.php (userinfo logging)
- core/modules/oauth/generic_oauthcallback.php (userinfo logging)
- public/payment/newpayment.php (GET/POST debug logging)
- public/payment/paymentok.php (payment tag logging)
- public/stripe/ipn.php (Stripe event data logging)
- paypal/lib/paypal.lib.php (PayPal response logging)
- api/index.php (API debug logging)
- stripe/class/stripe.class.php (payment/setup intent logging)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Fix CI

* CI

* Check if upload_max_filesize is not empty

* clean code

* Debug v23

* CI

* Fix #33521 VAT total false (#36990)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix : delete $this->vat_rate

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* NEW #25829 Automatically send the invoice generated from a template (#36967)

* Update DB

* ADD email template

* Ajout d'une clé de trad

* Ajout des traductions

* Suppression des traductions, sauf en_US

* Add flag auto send

* Modif form + cron auto send

* Suppression auto_send

* correction loopError

* ajout du selected au model de mail

* Prise en compte default model

* Fix pre-commit

* ménage

* precommit

* Correction Phan

* Correction Phan

* Correction, double cal du trigger

---------

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

* Develop force user change pass userclass (#37174)

* datamodel for user change password next time

* add force_pass_change in user object

* Initialize force_pass_change to 0

---------

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

* Another step for #37171

* Qual: Partial phan run on PR's, complete run on integration branches (#37186)

* Qual: Partial phan run on PR's, complete on main

# Qual: Partial phan run on PR's, complete on main

The selection is based on the branch name.
To run a complete phan run in a PR, the branch name of the PR must include phan_full.
This can help to fix remaining phan issue before re-integrating to the develop branch.

* qual: Update workflow and pre-commit configurations

- Enable phan workflow by uncommenting the relevant lines
- Update actionlint version to v1.7.10
- Add manual stage to actionlint hook in pre-commit-config.yaml

* qual: Update Phan analysis conditions

The conditions for running Phan analysis have been updated to include an additional check for branches containing 'phan_full'.

* qual: Update Phan workflow

- Replace github.event.ref with github.ref_name
- Add FILE_CHANGE_LIST environment variable for better file handling
- Update file list creation and usage in the workflow

* qual: Update Phan workflow conditions

Fix the branch reference (head_ref in PR, ref_name otherwise)

* Add step for debug information

* Remove debug step

* Fix: Missing initialisations members/new.php

Following a suppression of assignments, the variables disabledphy and disabledmor were undefined.

* fix: Update budget selection dropdown arguments in member creation form

Correct the arguments in the member creation form.

* qual: Add cs2pr to phan workflow

- Add cs2pr to the tools list in the phan workflow
- Change the output mode of phan to checkstyle
- Add a step to add results to PR as Github notices
- Add a step to provide phan log as artifact

* qual: Update Phan workflow to use environment variable for file list

The change fixes the Phan workflow to use the environment variable `$FILE_CHANGED_LIST` to clear the file

---------

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

* Fix phan

* Fix phan

* Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0

* Doc

* Qual: Fix ambigious redirect error on Phan workflow (#37200)

# Qual: Fix ambigious redirect error on Phan workflow

Rewrote the shell command that is supposed to suppress a file contents
but is flagged by the environment.

* PHPStan > Update baseline (#37197)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* Typo fix (#37195)

* Debug v23 - filters on agenda pages

* css

* css

* css

* qual: Update PHPStan workflow to run on all files in integration (#37207)

The PHPStan workflow has been updated to run on all files in integration branches.

* Fix CI

* Add hook in isEditable()

* Debug v23

* CLOSE #37190 ODT Templates for thirdparties - Birthday is returned in epoch format (#37198)

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

* fix: Remove HTML from accounting menu tooltips in eldy theme (#37203)

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

* Qual: Update spelling (#37199)

* Qual: Update spelling for pre-select variants

# Qual: Update spelling for pre-select variants

In English, preselect is without the hyphen.  Update text and made some translations
related to preselect.

* Qual: Update composant to component and/or adequate translation.

# Qual: Update composant to component and/or adequate translation.

"Composant(s)" was mostly referenced in french file/class comments.
Updated

* Qual: Fix misspellings related to "criteria"

# Qual: Fix misspellings related to "criteria"

* Qual: Fix produt misspellings

# Qual: Fix produt misspellings

Change 'produt' to 'product'.

* Qual: Update French comments with "composants"

#Qual: Update French comments with "composants"

- Translating French comments to English (avoid codespell notice)

* Qual: Fixed typo 'bad practive' to 'bad practice'

# Qual: Fixed typo 'bad practive' to 'bad practice'

* Qual: Update phan.yml to exclude specific files from analysis

- Added file exclusion pattern to match phan configuration
- Added check for empty file list to avoid unnecessary phan execution

* Qual: Update file filtering in phan.yml workflow

The change updates the file filtering process in the phan.yml workflow to correctly redirect the output of the grep command to a temporary file.

* Qual: Ignore $systemfunction always exists

---------

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

* Error handling methods for commonobject (#37201)

* Error handling methods for commonobject (#37201)

* NEW Can request and force user to change its password (#37196)

* force user to change password : redirect to user card on login

* force user to change password : redirect to user card on login

* redirect to a dedicated page

* bad old idea : self change passwd on user card + edit mode and rights: it makes a hole on security check

* only apply on dolibarr auth mode context

* only on dolibarr auth mode context

* Fix force_pass_change SQL assignment logic

---------

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

* Doc

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Prepare 23.0

* Qual: Ignore exit code from `grep -v` in phan flow (#37213)

# Qual: Ignore exit code from `grep -v` in phan flow

`grep -v` returns 1 when the resulting filtered list is empty and would stop the execution.
This is fixed with `|| true` to have a final exit code that is 0.

* WIP LNE

* Debug v23

* Debug v23

* WIP LNE

* FIX Bad header name

* Fix CSP for ping

* Compatibility with multicompany

* Debug

* Fix include

* FIX phpdoc on createFixedAmountDiscount() (#37212)

* FIX phpdoc on createFixedAmountDiscount

* FIX phpdoc

---------

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

* Fix in card css modal display (#36569)

* Fix display of cards in a modal

* fix php stan

* fix php stan

* Try a change to force CI

---------

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

* NEW Accountancy - Multi reports system

* Button style

* CI

* CI

* CI

* CI

* CI

* CI

* CI

* More complete data on pings.

* Debug v23

* Debug initdemo

* Debug initdemo

* Debug initdemo

* Debug v23

* Update initdemo

* Update initdemo

* Cleaner GET call

* Add id of perm in url

* Init demo for v24

* Fix translation of "various payment" (not english, not pro) with the
term used in english to mean "Opérations diverses (OD)"

* Sync transifex

* CSS

* Trans

* Doc

* Trans

* Debug v23

* Debug v23

* Trans

* Debug v24

* Debug v23

* Debug v23

* WIP

* Debug v23

* Debug v23

* Debug v24

* Work on LNE

* WIP LNE

* Debug v24

* Doc

* Translation

* Sync transifex

* Debug

* Debug

* Debug

* Responsive

* Dev control archive integrity

* Debug

* Update supplier_proposal.lang (#37238)

* add company name on dropdown contract list (#37245)

* Clean dump file

* Fix CI

* FIX #37246 Modifying resteapayer calculation for credit note (#37247)

* Add 'type' parameter to completeTabsHead hook (#37235)

* #37257 FIX for piesemicircle (#37258)

* Fix #37227 Fix #37233

* Fix #37227 Fix #37233

* QUAL French comment in English (#37225)

* Edit label of $fields

* QUAL French comment in English

* Bump actions/upload-artifact from 4 to 6 (#37250)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* UI/UX : Transfert feedback css from experimental to core (#37226)

* Transfert feedback css from experimental to core

* fix php phan

* Fix phan

* Fix phan

* Fix phan

* Missing label

* Debug

* Add method to chech if invoice can be replaced

* Fix return

* Debug v24

* Fix CI

* fix commoninvoice.class.php (#37267)

* fix commoninvoice.class.php

* Update commoninvoice.class.php

* CI

* CI

* Debug v23

* CI

* Fix CI

* Debug v23

* clean code pdf.lib.php (#37265)

* clean code pdf.lib.php

* Update pdf.lib.php

* Update pdf.lib.php

---------

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

* FixCI

* FIX: linktoref should be able to receive more than 255 chars (#37262)

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: Yamil Esteban Garcia <120027058+developmentOYR@users.noreply.github.com>
Co-authored-by: Noé Cendrier <81741011+altairis-noe@users.noreply.github.com>
Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: minimexat <minimexat@gmail.com>
Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
Co-authored-by: MDW <mdeweerd@users.noreply.github.com>
Co-authored-by: evarisk-kilyan <kilyan.evarisk@gmail.com>
Co-authored-by: Vanyo <vanyolai@gmail.com>
Co-authored-by: jeremydassaud <49372108+jeremydassaud@users.noreply.github.com>
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Vincent Maury <artec.vm@arnac.net>
Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Vincent Penel <vincent.penel@atm-consulting.fr>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Joris Le Blansch <jleblansch@gmail.com>
Co-authored-by: intelliking <tyleradams93226@gmail.com>
Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com>
Co-authored-by: John BOTELLA <68917336+thersane-john@users.noreply.github.com>
Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com>
Co-authored-by: demiton <fabien.cisse@gmail.com>
Co-authored-by: Jyhere <jyhere@gmail.com>
Co-authored-by: Delthair <41671350+Delthair@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 18:57:35 +01:00
MDW
e773d3bb81 Qual: Fix hurl installation instructions, upgrade beautysh hook (#37218)
* Qual: Update beautysh hook version to v6.4.2

Update the beautysh hook version from v6.2.1 to v6.4.2 to allow running it on trixie / python 3.13.

* Fix: Installation instructions for hurl

# Fix: Installation instructions for hurl

Variable expansions were not quoted as needed and resulted in undesired expansions.
Fixed in echo commands by using single quotes.

* Qual: Add .sh file type to .editorconfig

Adds support for .sh file type in .editorconfig to ensure tab indentation style.
2026-02-24 18:41:51 +01:00
Laurent Destailleur
90070c8c7e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-24 18:18:15 +01:00
Laurent Destailleur
374d609ce8 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-24 18:12:05 +01:00
Lucky
db3df89ee2 New options for withdraw control (#37179)
* New options for withdraw control

Add a new option "WITHDRAW_STRICT_CHECK_AMOUNT"
Transfer request control is based solely on the supplier invoice amount:
By default, once a request is made, even if its amount is less than the invoice amount, no additional requests can be made until the original request is validated (integrated into a transfer slip).
With this option, the control is applied to the sum of all requests, even if they are not integrated into a SEPA transfer slip.
The control verifies that the total sum of the requests never exceeds the invoice total.
By default, one or more requests exceeding the invoice amount can be entered; this option prevents this behavior.

This behavior is more logical and user-friendly, especially when transfer requests are made by technicians or buyers and the SEPA files are created by the accounting department.

* fix

* Update commoninvoice.class.php

* fichier lang

* Cast remaining amounts to float for precision

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-24 18:06:31 +01:00
Pierre Ardoin
df352dfbb3 NEW Support for __AUTHOREMAIL__ in fixed notifications (#37285)
* Update notification.php

* Update notify.class.php

* Update mails.lang

* Update mails.lang

* Update notify.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-24 17:53:24 +01:00
Alexandre SPANGARO
a7a5e211c2 NEW Accountancy - Transaction template system (#37286)
* NEW Accountancy - Transaction template system

* CI

* CI

* CI

* CI

* CI

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-24 17:50:20 +01:00
Charlène Benke
65516a3f99 Refactor notification type handling in card.php (#37321)
* Refactor notification type handling in card.php

we have email and sms feature
but it seems that sms is not well manager

Furthermore, it's not possible to manage other notifications (on a smartphone app, for example).

Ideally, this should be put in a dictionary.

* Initialize num variable before query execution

* Update card.php
2026-02-24 17:41:12 +01:00
MDW
84e509394c Fix: CI (#37324)
* Fix: key is never 'PAYMENT_CUSTOMER_CREATE'

* Fix: Update include path and formatting

- Update include path for versionmod.inc.php
- Apply code formatting

* Qual: Ignore phpstan notice

# Qual: Ignore phpstan notice

- Country code is already FR, but test can be useful in the future, so ignoring the notice.
- Code formatting

* Qual: Try exact match to suppress phpstan notice

# Qual: Try exact match to suppress phpstan notice
2026-02-24 17:35:35 +01:00
Ahmed Galadima
bb8285cb4d Fix recruitment API candidature creation validation (#37331)
Signed-off-by: Ahmed Galadima <ahmed.galadima@hotmail.com>
Co-authored-by: Ahmed Galadima <ahmed.galadima@hotmail.com>
2026-02-24 17:32:46 +01:00
Alexandre SPANGARO
36b07475dc Typo (#37326) 2026-02-24 17:30:44 +01:00
Laurent Destailleur
06d1b2bc14 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-24 14:16:44 +01:00
Laurent Destailleur
a705472811 Add usleep 2026-02-24 14:16:34 +01:00
Eric - CAP-REL
ff146c4713 handle race condition user with no right - prevent infinite loop (#37220) 2026-02-23 20:12:44 +01:00
John BOTELLA
3d88e03c88 UIUX : Dolibarr js context from experimental to core (#37228)
* NEW Use the js lib into htdocs/public/includes instead of htdocs/includes

* New LNE Collect of buisness informations (#37084)

* Working LNE ping

* remove GPDA

* Add of other informations

* remove testing var

* fix Ci

* fix Ci

* fix ci

* fix CI

* Fix Ci

* fix Ci

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>

* CI

* CI

* CI

* CI

* Clean code. File not used.

* CSS

* CSS

* Fix phpunit

* More legal info

* CI

* Fix CI

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Protect module

* Add currency

* CSS

* WIP LNE

* Fix navigation

* cs

* Debug registration process

* Debug setup navigation

* CI

* CI

* Factorize code

* Fix CI

* Fix CI

* Fix CI

* CI

* CI

* CI

* CI

* Disable phan on v23

* CI

* CI

* FIX: missing include for blockedlog lib (#37165)

* Debug CI

* fix ternary always true (#37161)

* fix ternary always true

* Update requests.php

* Update registration.php

---------

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

* CI

* FIX: missing include for blockedlog lib (#37165)

* FIX #37134 Use json_encode for IMAP search logging in EmailCollector (#37135)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch) as each line becomes a separate log entry.

Using json_encode() produces single-line structured output that works
correctly with all log aggregation tools.

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

* Populate syslog with placeholder (#37163)

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

* Doc

* datamodel for user change password next time (#37155)

* Qual: Update phan baseline (#37172)

* Fix typo in file path (#37160)

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

* Fix phpunit

* Complete call to setStatus so we have a trigy as 4th parameter (help to
fix the #37129)

* FIX Product - Warning on admin (#37157)

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

* FIX Product - Warning on admin + CSS (#37158)

* FIX Product - Warning on admin

* CSS

---------

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

* CI

* CI

* CI

* Avoid error if include fails

* More functions in blacklist (even if nw we use the whitelist by default)

* #37166 [SQL] add: email template for ticket admin creation (#37182)

* Replace var_export with new function formatLogObject (#37178)

* FIX BOM - Class product missing, column offset and information recording (form/input overlap) in admin (#37177)

* FIX BOM - Class product missing in admin

* Fix column offset and information recording (form/input overlap)

* ci

* ci

* FIX Intracommreport - Warning & link problem on tab (#37176)

* FIX Bank transfer admin - Warning & save 0 on constant PAYMENTBYBANKTRANSFER_ADDDAYS (#37175)

* Look and feel v24

* Update default time handling in index.php (#37150)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix CI

* Add template in migration

* fix phpdoc comment (#37184)

* fix phpdoc comment

* fix phpdoc comment

---------

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

* CI

* Fix phpstan

* Replace var_export by formatLogObject (continued) (#37188)

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

* Debug amount suggested on membership public form

* Issue 36923 Fix session title handling in survey creation (#37105)

* Issue 36923 Fix session title handling in survey creation

* Change input field to use id attribute for title

---------

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

* fix phpstan errors blocking action baseline (#37189)

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* refresh baseline

* QUAL Replace var_export() with json_encode() in dol_syslog() calls (#37138)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch, Graylog) as each line becomes a separate
log entry.

json_encode() produces single-line structured output that works correctly
with all log aggregation tools. This pattern is already used elsewhere
in Dolibarr (accountancy, install modules).

Files changed:
- core/class/commoninvoice.class.php (payment intent logging)
- core/class/commonobject.class.php (payment terms logging)
- core/modules/mailings/advthirdparties.modules.php (mailing targets)
- core/modules/oauth/google_oauthcallback.php (userinfo logging)
- core/modules/oauth/generic_oauthcallback.php (userinfo logging)
- public/payment/newpayment.php (GET/POST debug logging)
- public/payment/paymentok.php (payment tag logging)
- public/stripe/ipn.php (Stripe event data logging)
- paypal/lib/paypal.lib.php (PayPal response logging)
- api/index.php (API debug logging)
- stripe/class/stripe.class.php (payment/setup intent logging)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Fix CI

* CI

* Check if upload_max_filesize is not empty

* clean code

* Debug v23

* CI

* Fix #33521 VAT total false (#36990)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix : delete $this->vat_rate

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* NEW #25829 Automatically send the invoice generated from a template (#36967)

* Update DB

* ADD email template

* Ajout d'une clé de trad

* Ajout des traductions

* Suppression des traductions, sauf en_US

* Add flag auto send

* Modif form + cron auto send

* Suppression auto_send

* correction loopError

* ajout du selected au model de mail

* Prise en compte default model

* Fix pre-commit

* ménage

* precommit

* Correction Phan

* Correction Phan

* Correction, double cal du trigger

---------

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

* Develop force user change pass userclass (#37174)

* datamodel for user change password next time

* add force_pass_change in user object

* Initialize force_pass_change to 0

---------

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

* Another step for #37171

* Qual: Partial phan run on PR's, complete run on integration branches (#37186)

* Qual: Partial phan run on PR's, complete on main

# Qual: Partial phan run on PR's, complete on main

The selection is based on the branch name.
To run a complete phan run in a PR, the branch name of the PR must include phan_full.
This can help to fix remaining phan issue before re-integrating to the develop branch.

* qual: Update workflow and pre-commit configurations

- Enable phan workflow by uncommenting the relevant lines
- Update actionlint version to v1.7.10
- Add manual stage to actionlint hook in pre-commit-config.yaml

* qual: Update Phan analysis conditions

The conditions for running Phan analysis have been updated to include an additional check for branches containing 'phan_full'.

* qual: Update Phan workflow

- Replace github.event.ref with github.ref_name
- Add FILE_CHANGE_LIST environment variable for better file handling
- Update file list creation and usage in the workflow

* qual: Update Phan workflow conditions

Fix the branch reference (head_ref in PR, ref_name otherwise)

* Add step for debug information

* Remove debug step

* Fix: Missing initialisations members/new.php

Following a suppression of assignments, the variables disabledphy and disabledmor were undefined.

* fix: Update budget selection dropdown arguments in member creation form

Correct the arguments in the member creation form.

* qual: Add cs2pr to phan workflow

- Add cs2pr to the tools list in the phan workflow
- Change the output mode of phan to checkstyle
- Add a step to add results to PR as Github notices
- Add a step to provide phan log as artifact

* qual: Update Phan workflow to use environment variable for file list

The change fixes the Phan workflow to use the environment variable `$FILE_CHANGED_LIST` to clear the file

---------

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

* Fix phan

* Fix phan

* Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0

* Doc

* Qual: Fix ambigious redirect error on Phan workflow (#37200)

# Qual: Fix ambigious redirect error on Phan workflow

Rewrote the shell command that is supposed to suppress a file contents
but is flagged by the environment.

* PHPStan > Update baseline (#37197)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* Typo fix (#37195)

* Debug v23 - filters on agenda pages

* css

* css

* css

* qual: Update PHPStan workflow to run on all files in integration (#37207)

The PHPStan workflow has been updated to run on all files in integration branches.

* Fix CI

* Add hook in isEditable()

* Debug v23

* CLOSE #37190 ODT Templates for thirdparties - Birthday is returned in epoch format (#37198)

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

* fix: Remove HTML from accounting menu tooltips in eldy theme (#37203)

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

* Qual: Update spelling (#37199)

* Qual: Update spelling for pre-select variants

# Qual: Update spelling for pre-select variants

In English, preselect is without the hyphen.  Update text and made some translations
related to preselect.

* Qual: Update composant to component and/or adequate translation.

# Qual: Update composant to component and/or adequate translation.

"Composant(s)" was mostly referenced in french file/class comments.
Updated

* Qual: Fix misspellings related to "criteria"

# Qual: Fix misspellings related to "criteria"

* Qual: Fix produt misspellings

# Qual: Fix produt misspellings

Change 'produt' to 'product'.

* Qual: Update French comments with "composants"

#Qual: Update French comments with "composants"

- Translating French comments to English (avoid codespell notice)

* Qual: Fixed typo 'bad practive' to 'bad practice'

# Qual: Fixed typo 'bad practive' to 'bad practice'

* Qual: Update phan.yml to exclude specific files from analysis

- Added file exclusion pattern to match phan configuration
- Added check for empty file list to avoid unnecessary phan execution

* Qual: Update file filtering in phan.yml workflow

The change updates the file filtering process in the phan.yml workflow to correctly redirect the output of the grep command to a temporary file.

* Qual: Ignore $systemfunction always exists

---------

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

* Error handling methods for commonobject (#37201)

* Error handling methods for commonobject (#37201)

* NEW Can request and force user to change its password (#37196)

* force user to change password : redirect to user card on login

* force user to change password : redirect to user card on login

* redirect to a dedicated page

* bad old idea : self change passwd on user card + edit mode and rights: it makes a hole on security check

* only apply on dolibarr auth mode context

* only on dolibarr auth mode context

* Fix force_pass_change SQL assignment logic

---------

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

* Doc

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Prepare 23.0

* Qual: Ignore exit code from `grep -v` in phan flow (#37213)

# Qual: Ignore exit code from `grep -v` in phan flow

`grep -v` returns 1 when the resulting filtered list is empty and would stop the execution.
This is fixed with `|| true` to have a final exit code that is 0.

* WIP LNE

* Debug v23

* Debug v23

* WIP LNE

* FIX Bad header name

* Fix CSP for ping

* Compatibility with multicompany

* Debug

* Fix include

* Transfert feedback css from experimental to core

* Dolibarr JS context Tools from experiemntal to Core

* Fix lang public mode

* fix php phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix phan

* Fix multi instance of Dolibarr on same Domain

* remove french comment

* FIX phpdoc on createFixedAmountDiscount() (#37212)

* FIX phpdoc on createFixedAmountDiscount

* FIX phpdoc

---------

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

* Fix path

* Fix in card css modal display (#36569)

* Fix display of cards in a modal

* fix php stan

* fix php stan

* Try a change to force CI

---------

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

* More complete data on pings.

* Debug v23

* Debug initdemo

* Debug initdemo

* Debug initdemo

* Debug v23

* Update initdemo

* Update initdemo

* Cleaner GET call

* Add id of perm in url

* Init demo for v24

* Fix translation of "various payment" (not english, not pro) with the
term used in english to mean "Opérations diverses (OD)"

* Sync transifex

* CSS

* Trans

* Doc

* Trans

* Debug v23

* Debug v23

* Trans

* Debug v24

* Debug v23

* Debug v23

* WIP

* Debug v23

* Debug v23

* Debug v24

* Work on LNE

* WIP LNE

* Debug v24

* Doc

* Translation

* Sync transifex

* Debug

* Debug

* Debug

* Responsive

* Dev control archive integrity

* Debug

* Update supplier_proposal.lang (#37238)

* add company name on dropdown contract list (#37245)

* Clean dump file

* Fix CI

* FIX #37246 Modifying resteapayer calculation for credit note (#37247)

* Add 'type' parameter to completeTabsHead hook (#37235)

* #37257 FIX for piesemicircle (#37258)

* Fix #37227 Fix #37233

* Fix #37227 Fix #37233

* QUAL French comment in English (#37225)

* Edit label of $fields

* QUAL French comment in English

* Bump actions/upload-artifact from 4 to 6 (#37250)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* UI/UX : Transfert feedback css from experimental to core (#37226)

* Transfert feedback css from experimental to core

* fix php phan

* Fix phan

* Fix phan

* Fix phan

* Missing label

* Debug

* Debug savedemo

* Fix mention

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com>
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: Yamil Esteban Garcia <120027058+developmentOYR@users.noreply.github.com>
Co-authored-by: Noé Cendrier <81741011+altairis-noe@users.noreply.github.com>
Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: minimexat <minimexat@gmail.com>
Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
Co-authored-by: MDW <mdeweerd@users.noreply.github.com>
Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com>
Co-authored-by: evarisk-kilyan <kilyan.evarisk@gmail.com>
Co-authored-by: Vanyo <vanyolai@gmail.com>
Co-authored-by: jeremydassaud <49372108+jeremydassaud@users.noreply.github.com>
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Vincent Maury <artec.vm@arnac.net>
Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Vincent Penel <vincent.penel@atm-consulting.fr>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Joris Le Blansch <jleblansch@gmail.com>
Co-authored-by: intelliking <tyleradams93226@gmail.com>
Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com>
Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com>
Co-authored-by: demiton <fabien.cisse@gmail.com>
Co-authored-by: Jyhere <jyhere@gmail.com>
Co-authored-by: Delthair <41671350+Delthair@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 20:11:39 +01:00
Lucky
6041233c4b Fix_massaction_withdraw_control (#37237)
* CI

* CI

* CI

* CI

* Clean code. File not used.

* CSS

* CSS

* Fix phpunit

* More legal info

* CI

* Fix CI

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Fix: IRPF tax not applied when creating invoice from project times (#37077)

* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

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

* Protect module

* Add currency

* CSS

* WIP LNE

* Fix navigation

* cs

* Debug registration process

* Debug setup navigation

* CI

* CI

* Factorize code

* Fix CI

* Fix CI

* Fix CI

* CI

* CI

* CI

* CI

* Disable phan on v23

* CI

* CI

* FIX: missing include for blockedlog lib (#37165)

* Debug CI

* fix ternary always true (#37161)

* fix ternary always true

* Update requests.php

* Update registration.php

---------

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

* CI

* FIX: missing include for blockedlog lib (#37165)

* FIX #37134 Use json_encode for IMAP search logging in EmailCollector (#37135)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch) as each line becomes a separate log entry.

Using json_encode() produces single-line structured output that works
correctly with all log aggregation tools.

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

* Populate syslog with placeholder (#37163)

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

* Doc

* datamodel for user change password next time (#37155)

* Qual: Update phan baseline (#37172)

* Fix typo in file path (#37160)

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

* Fix phpunit

* Complete call to setStatus so we have a trigy as 4th parameter (help to
fix the #37129)

* FIX Product - Warning on admin (#37157)

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

* FIX Product - Warning on admin + CSS (#37158)

* FIX Product - Warning on admin

* CSS

---------

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

* CI

* CI

* CI

* Avoid error if include fails

* More functions in blacklist (even if nw we use the whitelist by default)

* #37166 [SQL] add: email template for ticket admin creation (#37182)

* Replace var_export with new function formatLogObject (#37178)

* FIX BOM - Class product missing, column offset and information recording (form/input overlap) in admin (#37177)

* FIX BOM - Class product missing in admin

* Fix column offset and information recording (form/input overlap)

* ci

* ci

* FIX Intracommreport - Warning & link problem on tab (#37176)

* FIX Bank transfer admin - Warning & save 0 on constant PAYMENTBYBANKTRANSFER_ADDDAYS (#37175)

* Look and feel v24

* Update default time handling in index.php (#37150)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix file path comment in supplier invoice module (#37133)

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

* Fix CI

* Add template in migration

* fix phpdoc comment (#37184)

* fix phpdoc comment

* fix phpdoc comment

---------

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

* CI

* Fix phpstan

* Replace var_export by formatLogObject (continued) (#37188)

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

* Debug amount suggested on membership public form

* Issue 36923 Fix session title handling in survey creation (#37105)

* Issue 36923 Fix session title handling in survey creation

* Change input field to use id attribute for title

---------

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

* fix phpstan errors blocking action baseline (#37189)

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* refresh baseline

* QUAL Replace var_export() with json_encode() in dol_syslog() calls (#37138)

var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch, Graylog) as each line becomes a separate
log entry.

json_encode() produces single-line structured output that works correctly
with all log aggregation tools. This pattern is already used elsewhere
in Dolibarr (accountancy, install modules).

Files changed:
- core/class/commoninvoice.class.php (payment intent logging)
- core/class/commonobject.class.php (payment terms logging)
- core/modules/mailings/advthirdparties.modules.php (mailing targets)
- core/modules/oauth/google_oauthcallback.php (userinfo logging)
- core/modules/oauth/generic_oauthcallback.php (userinfo logging)
- public/payment/newpayment.php (GET/POST debug logging)
- public/payment/paymentok.php (payment tag logging)
- public/stripe/ipn.php (Stripe event data logging)
- paypal/lib/paypal.lib.php (PayPal response logging)
- api/index.php (API debug logging)
- stripe/class/stripe.class.php (payment/setup intent logging)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* Fix CI

* CI

* Check if upload_max_filesize is not empty

* clean code

* Debug v23

* CI

* Fix #33521 VAT total false (#36990)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix : delete $this->vat_rate

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* NEW #25829 Automatically send the invoice generated from a template (#36967)

* Update DB

* ADD email template

* Ajout d'une clé de trad

* Ajout des traductions

* Suppression des traductions, sauf en_US

* Add flag auto send

* Modif form + cron auto send

* Suppression auto_send

* correction loopError

* ajout du selected au model de mail

* Prise en compte default model

* Fix pre-commit

* ménage

* precommit

* Correction Phan

* Correction Phan

* Correction, double cal du trigger

---------

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

* Develop force user change pass userclass (#37174)

* datamodel for user change password next time

* add force_pass_change in user object

* Initialize force_pass_change to 0

---------

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

* Another step for #37171

* Qual: Partial phan run on PR's, complete run on integration branches (#37186)

* Qual: Partial phan run on PR's, complete on main

# Qual: Partial phan run on PR's, complete on main

The selection is based on the branch name.
To run a complete phan run in a PR, the branch name of the PR must include phan_full.
This can help to fix remaining phan issue before re-integrating to the develop branch.

* qual: Update workflow and pre-commit configurations

- Enable phan workflow by uncommenting the relevant lines
- Update actionlint version to v1.7.10
- Add manual stage to actionlint hook in pre-commit-config.yaml

* qual: Update Phan analysis conditions

The conditions for running Phan analysis have been updated to include an additional check for branches containing 'phan_full'.

* qual: Update Phan workflow

- Replace github.event.ref with github.ref_name
- Add FILE_CHANGE_LIST environment variable for better file handling
- Update file list creation and usage in the workflow

* qual: Update Phan workflow conditions

Fix the branch reference (head_ref in PR, ref_name otherwise)

* Add step for debug information

* Remove debug step

* Fix: Missing initialisations members/new.php

Following a suppression of assignments, the variables disabledphy and disabledmor were undefined.

* fix: Update budget selection dropdown arguments in member creation form

Correct the arguments in the member creation form.

* qual: Add cs2pr to phan workflow

- Add cs2pr to the tools list in the phan workflow
- Change the output mode of phan to checkstyle
- Add a step to add results to PR as Github notices
- Add a step to provide phan log as artifact

* qual: Update Phan workflow to use environment variable for file list

The change fixes the Phan workflow to use the environment variable `$FILE_CHANGED_LIST` to clear the file

---------

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

* Fix phan

* Fix phan

* Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0

* Doc

* Qual: Fix ambigious redirect error on Phan workflow (#37200)

# Qual: Fix ambigious redirect error on Phan workflow

Rewrote the shell command that is supposed to suppress a file contents
but is flagged by the environment.

* PHPStan > Update baseline (#37197)

Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>

* Typo fix (#37195)

* Debug v23 - filters on agenda pages

* css

* css

* css

* qual: Update PHPStan workflow to run on all files in integration (#37207)

The PHPStan workflow has been updated to run on all files in integration branches.

* Fix CI

* Add hook in isEditable()

* Debug v23

* CLOSE #37190 ODT Templates for thirdparties - Birthday is returned in epoch format (#37198)

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

* fix: Remove HTML from accounting menu tooltips in eldy theme (#37203)

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

* Qual: Update spelling (#37199)

* Qual: Update spelling for pre-select variants

# Qual: Update spelling for pre-select variants

In English, preselect is without the hyphen.  Update text and made some translations
related to preselect.

* Qual: Update composant to component and/or adequate translation.

# Qual: Update composant to component and/or adequate translation.

"Composant(s)" was mostly referenced in french file/class comments.
Updated

* Qual: Fix misspellings related to "criteria"

# Qual: Fix misspellings related to "criteria"

* Qual: Fix produt misspellings

# Qual: Fix produt misspellings

Change 'produt' to 'product'.

* Qual: Update French comments with "composants"

#Qual: Update French comments with "composants"

- Translating French comments to English (avoid codespell notice)

* Qual: Fixed typo 'bad practive' to 'bad practice'

# Qual: Fixed typo 'bad practive' to 'bad practice'

* Qual: Update phan.yml to exclude specific files from analysis

- Added file exclusion pattern to match phan configuration
- Added check for empty file list to avoid unnecessary phan execution

* Qual: Update file filtering in phan.yml workflow

The change updates the file filtering process in the phan.yml workflow to correctly redirect the output of the grep command to a temporary file.

* Qual: Ignore $systemfunction always exists

---------

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

* Error handling methods for commonobject (#37201)

* Error handling methods for commonobject (#37201)

* NEW Can request and force user to change its password (#37196)

* force user to change password : redirect to user card on login

* force user to change password : redirect to user card on login

* redirect to a dedicated page

* bad old idea : self change passwd on user card + edit mode and rights: it makes a hole on security check

* only apply on dolibarr auth mode context

* only on dolibarr auth mode context

* Fix force_pass_change SQL assignment logic

---------

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

* Doc

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION

* Prepare 23.0

* Qual: Ignore exit code from `grep -v` in phan flow (#37213)

# Qual: Ignore exit code from `grep -v` in phan flow

`grep -v` returns 1 when the resulting filtered list is empty and would stop the execution.
This is fixed with `|| true` to have a final exit code that is 0.

* WIP LNE

* Debug v23

* Debug v23

* WIP LNE

* FIX Bad header name

* Fix CSP for ping

* Compatibility with multicompany

* Debug

* Fix include

* Fix_massaction_withdraw_control

Include pending transfer receipt amounts in bank transfer request validation

This code ensures that when creating a new bank transfer request for a supplier invoice, the system also checks for amounts that are already in generated but unprocessed transfer receipts.

Summary:
The second query ($sqlPending2) retrieves pending amounts from the prelevement_lignes table where the transfer receipt has been created but not yet executed (status = 0 or NULL).

This prevents users from requesting a bank transfer that would exceed the invoice total by accounting for:

Pending requests not yet included in any transfer receipt
Amounts already included in transfer receipts waiting to be processed

* FIX phpdoc on createFixedAmountDiscount() (#37212)

* FIX phpdoc on createFixedAmountDiscount

* FIX phpdoc

---------

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

* Fix in card css modal display (#36569)

* Fix display of cards in a modal

* fix php stan

* fix php stan

* Try a change to force CI

---------

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

* More complete data on pings.

* Debug v23

* Debug initdemo

* Debug initdemo

* Debug initdemo

* Debug v23

* Update initdemo

* Update initdemo

* Cleaner GET call

* Add id of perm in url

* Init demo for v24

* Fix translation of "various payment" (not english, not pro) with the
term used in english to mean "Opérations diverses (OD)"

* Sync transifex

* CSS

* Trans

* Doc

* Trans

* Debug v23

* Debug v23

* Trans

* Debug v24

* Debug v23

* Debug v23

* WIP

* Debug v23

* Debug v23

* Debug v24

* Work on LNE

* WIP LNE

* Debug v24

* Doc

* Translation

* Sync transifex

* Debug

* Debug

* Debug

* Responsive

* Dev control archive integrity

* Debug

* Update supplier_proposal.lang (#37238)

* add company name on dropdown contract list (#37245)

* Clean dump file

* Fix CI

* FIX #37246 Modifying resteapayer calculation for credit note (#37247)

* Add 'type' parameter to completeTabsHead hook (#37235)

* #37257 FIX for piesemicircle (#37258)

* Fix #37227 Fix #37233

* Fix #37227 Fix #37233

* QUAL French comment in English (#37225)

* Edit label of $fields

* QUAL French comment in English

* Bump actions/upload-artifact from 4 to 6 (#37250)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* UI/UX : Transfert feedback css from experimental to core (#37226)

* Transfert feedback css from experimental to core

* fix php phan

* Fix phan

* Fix phan

* Fix phan

* Missing label

* Debug

* traduction for massaction withdrawal control

* Add method to chech if invoice can be replaced

* Fix return

* Debug v24

* Fix CI

* fix commoninvoice.class.php (#37267)

* fix commoninvoice.class.php

* Update commoninvoice.class.php

* CI

* CI

* Debug v23

* CI

* Fix CI

* Debug v23

* clean code pdf.lib.php (#37265)

* clean code pdf.lib.php

* Update pdf.lib.php

* Update pdf.lib.php

---------

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

* FixCI

* FIX: linktoref should be able to receive more than 255 chars (#37262)

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

* NEW Increase satement decription to 12 on card payment, 22 on sepa

* CI

* Restore deleted file

* Add $dolibarr_main_restrict_eval_methods to install step1.php (#37268)

Since this variable has a significant impact in future versions of Dolibarr, it is preferable that it be directly included in the conf.php file created during installation.

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: Yamil Esteban Garcia <120027058+developmentOYR@users.noreply.github.com>
Co-authored-by: Noé Cendrier <81741011+altairis-noe@users.noreply.github.com>
Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: minimexat <minimexat@gmail.com>
Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
Co-authored-by: MDW <mdeweerd@users.noreply.github.com>
Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com>
Co-authored-by: evarisk-kilyan <kilyan.evarisk@gmail.com>
Co-authored-by: Vanyo <vanyolai@gmail.com>
Co-authored-by: jeremydassaud <49372108+jeremydassaud@users.noreply.github.com>
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Vincent Maury <artec.vm@arnac.net>
Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Vincent Penel <vincent.penel@atm-consulting.fr>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Joris Le Blansch <jleblansch@gmail.com>
Co-authored-by: intelliking <tyleradams93226@gmail.com>
Co-authored-by: Benjamin Falière <121813548+BenjaminFlr@users.noreply.github.com>
Co-authored-by: John BOTELLA <68917336+thersane-john@users.noreply.github.com>
Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com>
Co-authored-by: demiton <fabien.cisse@gmail.com>
Co-authored-by: Jyhere <jyhere@gmail.com>
Co-authored-by: Delthair <41671350+Delthair@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 20:09:42 +01:00
splohmer
f919a83721 FIX upload of files with multiple spaces via drag'n'drop flow (#37271)
* Debug savedemo

* Fix mention

* FIX upload of files with multiple spaces via drag'n'drop flow

Currently there are two ways to upload files to products, orders, etc. via the "old" way and the document tab and the "new" flow via drag'n'drop on the main tab of the object.

Both ways triggering completely different code paths. In the end the new way uses dol_sanitzieFileName to sanitize the name of the file and the old way uses dol_string_nohtmltag (both from functions.lib.php).

One of the main difference between the two mentioned functions is that in the old way multiple spaces behind each other are replaced by a single space. E.g. "A␠␠B␠␠␠C␠␠D" is tranformed to "A␠B␠C␠D".

This is needed to make sure that the files are properly uploaded and can be later also downloaded correctly.

How to reproduce?
Upload a file like "test␠␠test.txt" via the drag'n'drop flow and try to download it from the document tab. This is not working. You can see the file but cannot download it. The same flow via the input field of the document tab is working correctly.

* typo in comment

* FIX Phan warnings (unrelated to feature)

* FIX Phan warnings (unrelated to feature)

* FIX Phan warnings (unrelated to feature)

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 20:08:30 +01:00
William Mead
c8111f9726 QUAL updated projects API PHPDoc (#37275)
* Debug savedemo

* Fix mention

* Fix pdf font for CZ

* Added project API class and methods since tag

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 20:07:15 +01:00
minimexat
472665c038 fix(adherents): show cotisation create form for members with existing subscriptions (#37312)
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 20:05:26 +01:00
Laurent Destailleur
7e20cd27f6 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 19:55:37 +01:00
Laurent Destailleur
de9bf13ddd Fix SQL 2026-02-23 19:31:44 +01:00
Laurent Destailleur
06e67ee3da Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 12:23:34 +01:00
William Mead
f15efe2ca8 Added data pagination for index method (#37302)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:47:39 +01:00
Erwan-Wiwit
08feb72c6c Add hook stripeWebhookEvent in Stripe IPN for external modules (#37293)
* Add hook stripeWebhookEvent in Stripe IPN for external modules

Allow external modules to intercept and handle Stripe webhook events
via the standard Dolibarr hook system. The hook is called before the
built-in event processing, and modules can return >0 to stop default
processing if they handled the event entirely.

Hook context: stripeipn
Hook method: stripeWebhookEvent
Parameters: event (full Stripe event), servicestatus, service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix phpstan: instantiate HookManager before use in ipn.php

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:43:25 +01:00
minimexat
dd3709be29 fix: use ob_end_clean() instead of ob_end_flush() in readfileLowMemory() (#37298)
* fix: use ob_end_clean() instead of ob_end_flush() in readfileLowMemory() (fixes #37239)

* fix: use robust ob level cleanup loop per hregis review

---------

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:36:32 +01:00
Laurent Destailleur
dad5f55081 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 01:31:13 +01:00
Laurent Destailleur
717f315551 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 01:30:54 +01:00
Laurent Destailleur
c15994cbf8 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-23 01:29:51 +01:00
Laurent Destailleur
6b228411de Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-02-23 01:28:59 +01:00
Laurent Destailleur
f87a5ab46a Remove beautysh 2026-02-23 01:21:39 +01:00
Lucas Marcouiller
be46c48f55 fix some technical debt (#37296)
* fix some technical debt

* fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:17:17 +01:00
minimexat
9dd8492475 fix: add class existence check after failed include in barcode.php (#37297)
* fix: add class existence check after failed include in barcode.php (fixes #37249)

* fix: move continue into catch block per reviewer feedback

* fix: add continue in catch block per hregis review

* fix: replace invalid continue with $error++ in printsheet.php catch block

---------

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:15:53 +01:00
minimexat
79c6f82841 fix: add class existence check after failed include in barcode.php (#37297)
* fix: add class existence check after failed include in barcode.php (fixes #37249)

* fix: move continue into catch block per reviewer feedback

* fix: add continue in catch block per hregis review

* fix: replace invalid continue with $error++ in printsheet.php catch block

---------

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:15:29 +01:00
atm-corentin
020f552410 Adjust tracking number height calculation in PDF generation (#37289) 2026-02-23 01:05:35 +01:00
William Mead
ff7e2c4292 Updated PHPDoc with since tag (#37300)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 01:03:57 +01:00
splohmer
00a64df8e4 NEW Add Hook for adapting virtual stock in replenish screen (#37290)
* Add Hook for adapting virtual stock in replenish screen 

Currently it is only possible to hook in the loadvirtualstock hook to adapt the virtual stock by external modules. The newer version of the replenish screen doesn't use this hook anymore (by loading stock from product object) as it now uses faster sql queries. Therefore the external module cannot adapt this area and there is an missmatch of the view in replenish.php and the stock tab of the product.

* fix phan warning
2026-02-23 01:03:21 +01:00
Laurent Destailleur
7de8680a37 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 00:58:50 +01:00
Laurent Destailleur
dc29ebfb87 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-23 00:58:04 +01:00
Laurent Destailleur
cbdeebd338 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-23 00:57:52 +01:00
Laurent Destailleur
e31e6371e3 CI 2026-02-23 00:55:32 +01:00
ThomasNgr-OpenDSI
0b34a66fe6 FIX : filters on contract services list (#37274)
- when filtering on inactive services with pagination, clicking on 'next page' will lose filter for 'inactive' status.
- when filtered on 'active / expired' or 'active / not expired', the '(not) expired' part was lost after navigating to next/prev page
2026-02-23 00:43:23 +01:00
Regis Houssin
d3652eac53 FIX avoid php error for phpinfo_array() function (#37292) 2026-02-23 00:42:24 +01:00
MDW
095f72a3a7 Qual: Update pre-commit hooks and dependencies (#37313)
Updated the following pre-commit hooks and dependencies:
- gitleaks: v8.29.0 -> v8.30.0
- actionlint: v1.7.10 -> v1.7.11
- yamllint: v1.37.1 -> v1.38.0
- sqlfluff: 3.3.1 -> 4.0.4
- Added LT15 to exclude_rules in pyproject.toml (new since 3.3.1)

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 00:41:04 +01:00
William Mead
9560eb00bd Updated PHPDoc with since tag (#37299)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 00:40:39 +01:00
minimexat
4117aa4e31 fix(expedition): add 'shipping' as valid modulepart alias in dol_check_secure_access_document (#37307)
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
2026-02-23 00:39:44 +01:00
minimexat
e52c212a81 fix(expedition): add 'shipping' as valid modulepart alias in dol_check_secure_access_document (#37307)
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
2026-02-23 00:38:56 +01:00
MDW
1a8f540dc8 Fix: CI (#37320)
* Fix: http_response_code type

# Fix: http_response_code type

- Fixed http_response_code type

* Fix: Initialize refcashcontrol variable

Initialize refcashcontrol variable to 0 to ensure it is defined before use in the invoice.php script.

* Fix: Remove redundant check for BILL_SENTBYMAIL & $object type

# Fix: Remove redundant check for BILL_SENTBYMAIL & $object type

- Removed redundant check for BILL_SENTBYMAIL

* Fix: Correct date calculation for full year cash control

# Fix: Correct date calculation for full year cash control

Calculates the start date by subtracting one year from the end date.

* Qual: Add default batch value for invoice processing

# Qual: Add default batch value for invoice processing

Adds default empty string for the batch variable.

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-23 00:35:33 +01:00
Laurent Destailleur
de8f15ce38 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-23 00:11:16 +01:00
Laurent Destailleur
fe4648657e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-22 23:53:46 +01:00
Laurent Destailleur
2d5b6ea490 CI 2026-02-22 23:53:27 +01:00
Charlène Benke
f810a89977 verify if Hierarchical Responsible is allowed to validate holiday/exp (#37315)
* verify if Hierarchical Responsible is allowed to validate holiday/expense

* Add messages for holiday and expense report approval

* Add French translations for approval messages
2026-02-22 23:41:35 +01:00
Laurent Destailleur
cea9183889 CI 2026-02-22 23:40:56 +01:00
Laurent Destailleur
3fa9d82ca5 Fix CI 2026-02-22 23:15:20 +01:00
Laurent Destailleur
95e941dd23 Trans 2026-02-22 17:33:26 +01:00
Laurent Destailleur
68385e59d0 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-22 17:16:20 +01:00
Laurent Destailleur
e3e15e5df1 Add option MAIN_JQUERY_JNOTIFY_UNDER_MENU to have notification under
menu (not a so good idea, under menu is blocking the use of navigation
buttons needing to wait more often the notif disappear).
2026-02-22 17:16:09 +01:00
Laurent Destailleur
0ca643dffb sync transifex 2026-02-22 17:09:40 +01:00
hansemschnokeloch
e728453b7a Log message additionnal info (#37215) 2026-02-22 01:22:08 +01:00
Laurent Destailleur
c73820a931 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-21 23:50:34 +01:00
Laurent Destailleur
2821d18720 Doc 2026-02-21 23:50:24 +01:00
Laurent Destailleur
0eeac1817d FIX fail2ban rules 2026-02-21 23:50:18 +01:00
evarisk-kilyan
3d2c20193f #37185 [Workflow] add: ticket workflow read ticket when assign someone (#37187)
* #37185 [Workflow] add: ticket workflow read ticket when assign someone

* #37185 [Workflow] remove: double quote

* #37185 [Ticket] fix: move conf to ticket conf

* #37185 [Ticket] fix: typo
2026-02-21 23:28:21 +01:00
Laurent Destailleur
cdbd56c0ba Clean code 2026-02-21 22:34:37 +01:00
Laurent Destailleur
bb8290ef23 Demo 2026-02-21 18:32:13 +01:00
Laurent Destailleur
7df18dbad8 Clean scripts 2026-02-21 12:28:45 +01:00
Laurent Destailleur
63ed00fdba Fix CI 2026-02-21 12:22:59 +01:00
Sylvain Legrand
b34fb98b52 Update commande.class.php (#37301)
the empty qty logic → special_code = 3 ("Option" line) is not respected, unlike Propal which works correctly.
2026-02-21 12:09:17 +01:00
Jyhere
48cb31224e FIX: MAIN_FEATURES_LEVEL typo errors (#37304) 2026-02-21 12:03:15 +01:00
Laurent Destailleur
ac8af31c51 Fix CI 2026-02-21 11:56:15 +01:00
Laurent Destailleur
7728f8c895 WIP LNE 2026-02-21 11:44:43 +01:00
Laurent Destailleur
acc5f754e6 Removed the header that was a copy past, but this file was authored by
one dev only
2026-02-21 10:28:13 +01:00
minimexat
9e3f3e70d6 fix(product): default empty/null price_base_type to HT instead of treating as TTC (#37309)
Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-21 06:51:59 +01:00
MDW
829ea724cd Qual: Update codespell skip pattern to exclude blockedlog demo archives files (#37306)
# Qual: Update codespell skip pattern to exclude blockedlog demo archives files

The skip pattern in the pyproject.toml file has been updated to exclude additional files, specifically those in the dev/initdemo/documents_demo/blockedlog/archives/ directory.
2026-02-21 06:48:47 +01:00
Laurent Destailleur
c1db001cd8 Doc 2026-02-20 20:09:13 +01:00
Laurent Destailleur
4f17908c59 WIP LNE 2026-02-20 19:21:34 +01:00
Laurent Destailleur
12f0351deb Reduce size of blockedlogs 2026-02-20 19:09:16 +01:00
Laurent Destailleur
8efce11329 Add pos_number in blockedlog 2026-02-20 18:51:38 +01:00
Laurent Destailleur
80d48a0d52 Debug 2026-02-20 16:58:00 +01:00
Laurent Destailleur
9a9784238c Debug 2026-02-20 16:50:53 +01:00
Laurent Destailleur
97dcd936df Add hooks 2026-02-20 13:29:30 +01:00
Laurent Destailleur
a2fb7eea1b Regression 2026-02-20 12:43:49 +01:00
Laurent Destailleur
38ca2ddefe Trans 2026-02-20 12:41:39 +01:00
Laurent Destailleur
a318ee912b Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-20 12:40:11 +01:00
Laurent Destailleur
b2fc785985 Label 2026-02-20 12:40:01 +01:00
Laurent Destailleur
e8a053f1df Add link 2026-02-20 12:33:28 +01:00
Laurent Destailleur
2c6a346811 Add info link to for credit note 2026-02-20 12:26:50 +01:00
Laurent Destailleur
89634f83da Add discount of line in invoice 2026-02-20 12:22:43 +01:00
Laurent Destailleur
d6b780eab3 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-20 11:37:28 +01:00
Laurent Destailleur
3c531d2058 Add remise_percent in unalterablelog 2026-02-20 11:37:13 +01:00
Laurent Destailleur
4fb2746e6f Debug 2026-02-20 01:02:58 +01:00
Laurent Destailleur
a4d5990c2e Add full version 2026-02-20 00:49:35 +01:00
Laurent Destailleur
4a212daf49 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-20 00:30:35 +01:00
Laurent Destailleur
9738ce853a WIP LNE 2026-02-20 00:27:56 +01:00
Laurent Destailleur
11d4fafca0 Version module 2026-02-19 22:29:20 +01:00
Laurent Destailleur
dec4b2b0a2 More complet command 2026-02-19 03:25:15 +01:00
Laurent Destailleur
0250d5de8a CI 2026-02-19 03:09:27 +01:00
Laurent Destailleur
e6cb968eff Debug use gmt in v2 lines 2026-02-19 03:04:53 +01:00
Laurent Destailleur
970b07f646 Doc 2026-02-19 01:16:29 +01:00
Laurent Destailleur
5bf181adf7 Test 2026-02-19 01:01:46 +01:00
Laurent Destailleur
5033716755 Move files 2026-02-18 23:56:08 +01:00
Laurent Destailleur
b0489d32ab Fix unexpected exit 2026-02-18 23:33:57 +01:00
Laurent Destailleur
35caafadb7 Debug v24 2026-02-18 23:03:16 +01:00
Laurent Destailleur
23da8b6934 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-18 03:34:33 +01:00
Laurent Destailleur
aac5629f55 Fix save/initdemo 2026-02-18 03:30:40 +01:00
Laurent Destailleur
9b7afdcbbd Doc 2026-02-18 03:20:12 +01:00
Vincent Maury
d4ff519b75 Fix Product Api Update price (#37209)
If product prices is set to "price by client" sell price is never updated by API
2026-02-17 20:31:03 +01:00
Joachim Kueter
deeb710d2b FIX #37259 - Reverse Charge also for non-EEC countries (#37260)
See issue #37259:

Currently, reverse charge is only applied, if the supplier is based in the EEC.

At least for a German B2B customers, reverse charge has to get applied to any supplier outside of the home country.

The fix is non-invasive by providing a const ACCOUNTING_REVERSE_CHARGE_ALSO_NON_EEC to allow for a broader application of the already implemented RC rules.
2026-02-17 18:04:02 +01:00
VIAL-GOUTEYRON Quentin
81ac910ede FIX: align permission checks for product batches with rights class aliases (#37263) 2026-02-17 17:37:19 +01:00
tcesar
41294d5a27 Fix export extra-fields of warehouses (#37264) 2026-02-17 14:36:54 +01:00
Anthony Berton
03ab77c861 setPaymentTerms (#37232)
Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 01:37:13 +01:00
Laurent Destailleur
da4baf4255 CI 2026-02-16 21:43:56 +01:00
Laurent Destailleur
bff98ad817 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-02-16 21:11:20 +01:00
Laurent Destailleur
7ccd12e865 Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-02-16 21:08:22 +01:00
Laurent Destailleur
e64ab3c751 Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2026-02-16 20:51:44 +01:00
Laurent Destailleur
6adc5dc78d Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2026-02-16 20:47:21 +01:00
Laurent Destailleur
2a41e1f714 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-02-16 20:44:36 +01:00
Günter Lukas
917c2d6be8 Add check for empty delivery date before setting (#37254) 2026-02-16 20:12:21 +01:00
Joachim Kueter
7a37ebbeb3 FIX: Clean filenames with double spaces (#37256)
* Clean filenames with double spaces

If a filename contains double spaces, it can get uploaded in Dolibarr exactly as it is.

When listing the file or trying to download it, the dolibarr functions clear double spaces in the filename. In particular the alpha parameter for GETPOST.

This results in files being uploaded (e.g. attachments for invoices) than can get listed but remain inaccessible and even cannot get deleted via UI. 

We either need to fix all these places to accept double spaces or we change a single location, when we sanitize filenames.

* removed white space
2026-02-16 20:03:22 +01:00
Alexandre SPANGARO
83b137d854 FIX Luxembourg VAT rate by default (17% since 2024-01-01) (#37255) 2026-02-16 20:01:27 +01:00
Laurent Destailleur
9f4674806e Fix CI 2026-02-16 20:00:45 +01:00
Alexandre SPANGARO
30f7f34708 FIX Societe - Wrong control on update of VAT Intra (#37224) 2026-02-16 19:54:09 +01:00
Laurent Destailleur
ed868d6dd3 FIX #37072 2026-02-12 18:56:00 +01:00
ThomasNgr-OpenDSI
a8e0508343 Sec: Can init a page with php content without permission for php content (#37211)
edition (reported by phdwg1410)

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-12 16:30:45 +01:00
Eric - CAP-REL
e850355b30 Refactor GitHub Actions workflow steps
Remove depends on gh and only use curl and requests on github api ...
2026-02-12 09:37:04 +01:00
Alexandre SPANGARO
673659de98 FIX Accountancy - Update height of the export popup (#37206) 2026-02-12 01:23:06 +01:00
Laurent Destailleur
1a83124ca6 FIX closing an deposit invoice when payment was too high. 2026-02-12 00:38:04 +01:00
Laurent Destailleur
718f318089 Fix error when setup not complete. 2026-02-11 22:53:55 +01:00
Laurent Destailleur
da6de62ad9 Fix log 2026-02-11 20:37:57 +01:00
Laurent Destailleur
7a1a00e5d3 Complete examplefor tooltip to setup a virtual host 2026-02-11 18:44:15 +01:00
Laurent Destailleur
bf9e154deb Fix init ref 2026-02-11 18:07:37 +01:00
Laurent Destailleur
094e42fd4f Fix init ref 2026-02-11 18:03:03 +01:00
Laurent Destailleur
5846921e37 Sec: Can init a page with php content without permission for php content
edition (reported by phdwg1410)
2026-02-11 17:53:09 +01:00
Laurent Destailleur
d87b93cebd Fix missing br 2026-02-11 16:46:16 +01:00
Vincent Penel
e43438cc7b Fix/ticket status (#37129)
* set oldCopy and Status

* Update ticket.class.php

* Question Eldy

* Fix event status change

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:40:05 +01:00
ThomasNgr-OpenDSI
0b8e0c4765 FIX display of DLC/DLUO in tooltip (#37164) 2026-02-10 15:30:40 +01:00
atm-jonathan
4532d69220 Add missing CSRF tokens in bank left menu links (#37181)
* Add missing CSRF tokens in bank left menu links

* clean QUAL

* Update eldy.lib.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:15:43 +01:00
Alexandre SPANGARO
0cc80e65ed FIX SQL Error on VAT not defined in product card (#37159) 2026-02-09 18:33:54 +01:00
kkhelifa-opendsi
7b5ddac963 FIX: Backport fix on v20 for result page of compta (/compta/resultat/index.php) (#37127)
* FIX: Backport fix on v20 for result page of compta (/compta/resultat/index.php). The expense report were not included when the module was activated

* Update index.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 22:25:58 +01:00
yveslg
4951edfbd0 Fix/accountancy pdf wrong labels (#37153)
* FIX #37147 Limit account fetch to active chart of accounts in PDF exports

When multiple chart of accounts have the same account number, the PDF
exports (balance and ledger) could retrieve the wrong account label.

* FIX #37147 Decode HTML entities in balance PDF account group labels

The balance PDF export was displaying HTML entities (like &EACUTE;) instead
of properly decoded characters (like É) in account group labels.
2026-02-08 20:09:40 +01:00
Laurent Destailleur
e596bdada1 Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2026-02-08 15:53:06 +01:00
Laurent Destailleur
7f9bdc5f45 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2026-02-08 15:50:12 +01:00
Laurent Destailleur
b220cf0832 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-02-08 15:48:06 +01:00
Eric - CAP-REL
94d4f2661d MEMBER_ADDON does not exists, MEMBER_CODEMEMBER_ADDON is the right key (#37151) 2026-02-08 15:38:36 +01:00
Laurent Destailleur
9ec77dada2 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-02-08 14:54:15 +01:00
Laurent Destailleur
afc3879d84 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-02-08 14:53:59 +01:00
Florian Hödl
4660d0eec9 FIX #37118 Add missing require_once for CMailFile and functions2 in advtargetemailing (#37136)
Co-authored-by: Florian Hödl <florian@hoedl.co>
2026-02-08 14:47:11 +01:00
Alexandre SPANGARO
7bb57721bb FIX Invoice - Don't show discount on credit note type (#37145) 2026-02-08 14:29:25 +01:00
Laurent Destailleur
01e947cfad Rename var 2026-02-08 13:10:29 +01:00
Joachim Kueter
3361d4b0ba Fix: auto-generate pdf from odt-templates also for not yet validatedocuments (#37082)
* Fix: auto-generate pdf from odt-templates also for not yet validated documents

Not validated documents have a ref containing (PROV

When auto-generating pdf documents from odt documents is activated, this fails for not validated documents: the brackets ( ) in the ref are getting escaped twice which leads the pdf generation to fail.

The change removes the double escaping, the$command is already escaped before. With this change, also for unvalidated documents, pdf documents are getting generated.

* replace ( ) for escapeshellcmd

temporarily replace ( ) by placeholders to avoid them getting escaped

check that no placeholder injection happened before

apply to both execmethods (1 and 2)

* Retrigger check
2026-02-08 00:04:45 +01:00
Anthony Berton
6ef62a45b5 FIX - getModuleDirForApiClass for propal (#37098)
Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-02-07 23:44:57 +01:00
Francis Appels
7eae776e13 Fix #37089, still some checks on PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE (#37115) 2026-02-07 23:28:36 +01:00
atm-lucas
251b57641b fix timespent in timeline (#37132) 2026-02-07 22:53:52 +01:00
Laurent Destailleur
2b3ae6c2d7 Add logs 2026-02-06 13:16:16 +01:00
Laurent Destailleur
da0ece345f Fix label 2026-02-06 13:06:16 +01:00
Laurent Destailleur
173c6865cb Test CI 2026-02-06 13:05:21 +01:00
Vincent Penel
59ce599ba5 set oldCopy and Status (#37117)
* set oldCopy and Status

* Update ticket.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-06 12:18:36 +01:00
Laurent Destailleur
66c552ccb2 Removed not used file 2026-02-06 02:39:30 +01:00
ThomasNgr-OpenDSI
0f378d5ecf Fix : PR #36804 includes a regression that blocks navigation between pages (#36821) 2026-02-05 12:52:50 +01:00
Eric Seigne
07a3d0e4b7 auto assign PR on 18.0 / Unable to resolve action cli/gh-action, repository not found 2026-02-05 09:43:02 +01:00
Francis Appels
6ce11adba1 FIX: #36944 father kits with lot (#37089) 2026-02-04 21:22:59 +01:00
Benjamin Falière
72ed29a599 FIX(API, thirdparties): get fixed amount discounts (#37068)
Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr>
2026-02-04 14:50:21 +01:00
Benjamin Falière
e2aed0f5c1 FIX: #36989 private mention on ticket pdf (#37079)
Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr>
2026-02-04 14:41:29 +01:00
Frédéric FRANCE
f7092b4377 fix CI v21 (#37035)
* fix CI v21

* Update functions.lib.php
2026-01-31 20:30:12 +01:00
atm-lucas
87f81fb853 fix column total ht pdf espadon (#37038) 2026-01-31 20:26:31 +01:00
Laurent Destailleur
2e768edbb2 Close #37034 2026-01-30 13:32:34 +01:00
Laurent Destailleur
6b73bb78a4 CI 2026-01-30 13:22:02 +01:00
Lucas Marcouiller
aa33f7c155 Fix duplicate button for delivery reciept creation on shipment object (#36914)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-29 22:55:02 +01:00
Sylvain Legrand
70b3be5e7f Fix from V22 (#35559)
Using a packaging with a float value less than 1 (0.1, 0.5, etc.) generates a 500 error (division by 0)

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
2026-01-29 13:02:25 +01:00
Eric Seigne
07ff579416 auto assign PR to 18 thanks to copilot 2026-01-29 10:01:29 +01:00
HENRY Florian
51e61c8ef3 FIX: missing code to add Ressource to event on creation card (#37002) 2026-01-28 15:17:39 +01:00
Laurent Destailleur
e69d016b9f Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2026-01-27 10:45:17 +01:00
Laurent Destailleur
53dbc754f6 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-01-27 10:43:41 +01:00
Laurent Destailleur
a9dcecbc2f Merge branch '16.0' of git@github.com:/Dolibarr/dolibarr.git into 17.0 2026-01-27 10:43:20 +01:00
Laurent Destailleur
5d524f7973 Merge branch '15.0' of git@github.com:Dolibarr/dolibarr.git into 16.0 2026-01-27 10:43:01 +01:00
Laurent Destailleur
1b2f16b01a Fix ci 2026-01-27 10:42:37 +01:00
Laurent Destailleur
b623ea1f57 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-26 19:22:43 +01:00
Laurent Destailleur
360718fa7b Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-01-26 19:19:13 +01:00
Laurent Destailleur
c6a398639c Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2026-01-26 19:17:02 +01:00
Laurent Destailleur
c933e4a25a Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2026-01-26 19:05:17 +01:00
Laurent Destailleur
449870d347 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2026-01-26 19:05:09 +01:00
Laurent Destailleur
bf09f22239 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-01-26 18:58:35 +01:00
Laurent Destailleur
5595cdbb25 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-01-26 18:58:26 +01:00
Laurent Destailleur
dece1bc0f7 Merge branch '16.0' of git@github.com:/Dolibarr/dolibarr.git into 17.0 2026-01-26 18:57:53 +01:00
Laurent Destailleur
a0e2235adf Merge branch '15.0' of git@github.com:Dolibarr/dolibarr.git into 16.0 2026-01-26 18:56:40 +01:00
Laurent Destailleur
bec138412b Merge branch '14.0' of git@github.com:Dolibarr/dolibarr.git into 15.0 2026-01-26 18:56:02 +01:00
Francis Appels
8c179fad46 FIX: #36493 (#36853) for having parent kit stock changes you need to set PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE constant. (#36970)
* FIX: #36493 and #36853 Disable parent kit stock change should be optional.

* Revert "FIX: #36493 and #36853 Disable parent kit stock change should be optional."

This reverts commit 09bc922e2f.

* White space to have title in changelog
2026-01-26 16:14:21 +01:00
Alexandre SPANGARO
e3323c3ff1 Remove message for Invoice Situation level 2 - Need more test (#36987) 2026-01-26 11:49:46 +01:00
Alexandre SPANGARO
c1ab24f227 FIX #36980 Accounting - Error on create return operation (#36982) 2026-01-25 14:14:24 +01:00
Joachim Kueter
685ec96807 FIX #36961 - not showing financial data related to task times (#36963)
* FIX #36961 - not showing financial data related to task times

see detailed description in issue #36961

when users have minimal rights to just record their task times, they should not see the calculated hourly rates

* Minor change

* Update element.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-25 14:12:40 +01:00
Anthony Berton
8dafeb0984 FIX - Save param SYSTEMTOOLS_MYSQLDUMP and SYSTEMTOOLS_POSTGRESQLDUMP (#36791)
* FIX - Save param SYSTEMTOOLS_MYSQLDUMP and SYSTEMTOOLS_POSTGRESQLDUMP

* Fix copyright formatting for Anthony Berton

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-01-24 16:28:08 +01:00
Anthony Berton
adc4405d98 FIX - Select warehouse on propal create (#36745)
* FIX - Select warehouse on propal create

* Solve CI Errror

* clean

* clean

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 16:26:14 +01:00
Anthony Berton
9f972a7b4f FIX - Select warehouse on propal list (#36746)
* FIX - Select warehouse on propal list

* Solve CI error

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-01-24 16:23:36 +01:00
Alexandre SPANGARO
ee32411d6a FIX Contract - Wrong button to edit contract odt path (#36965)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 00:00:14 +01:00
Laurent Destailleur
7842897373 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-23 20:45:31 +01:00
Laurent Destailleur
364a3d3614 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-23 20:44:18 +01:00
NicolasL-SCOPEN
63fd9d326d Fix: subtotal lines from order to purchase order break lines on new document (#36973)
* Added a fix to prevent origin subtotal order lines from breaking purchase order lines

* Refactored code and fixed formating
2026-01-23 19:53:30 +01:00
noec764
c19e4e33cb FIX: Massaction Create Bills from expedition (#36958)
Co-authored-by: Noé <noe@scopen.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-23 18:29:12 +01:00
Joachim Kueter
835d3811a4 FIX #36960 - User can access some data (product price, invoice amount) without having the respective rights (#36962)
* FIX #36960 - User can access some data (product price, invoice amount) without having the respective rights

See detailed description in issue #36960

Product price and invoice amount was shown to users without checking right to read.

* removed white space

* Minor change

to trigger checks again

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-23 17:55:03 +01:00
Laurent Destailleur
7c9eb40000 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-23 17:15:26 +01:00
Laurent Destailleur
f44dc26e63 Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2026-01-23 17:14:48 +01:00
Laurent Destailleur
36b681153e Fix CI 2026-01-23 17:14:17 +01:00
Laurent Destailleur
059656b5ef Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-23 16:56:00 +01:00
Laurent Destailleur
be0f368629 Fix CI 2026-01-23 16:55:48 +01:00
HENRY Florian
926ed04ebe fix: PHP fatal error on php 8.2 Unsupported operand types: string * string (#36930) 2026-01-20 13:58:17 +01:00
ThomasNgr-OpenDSI
a025628c97 FIX concatenation of labels in extrafields (#36888)
IF:
- The extrafield is of type "Select from list"
- AND it would use a join as table
- AND the label would be a concatenation of fields from both tables
THEN, the EF value could not be displayed (showOutputField os showInputField).

example of syntax that would trigger this error : `commande c INNER JOIN llx_societe s ON s.rowid = c.fk_soc:s.nom|c.ref:c.rowid::`

This commit fixes this.
2026-01-19 20:36:37 +01:00
Laurent Destailleur
b304e13499 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-19 14:50:31 +01:00
boudet jean pascal
f9c8164e57 FIX: [BOM] Reset date_creation when cloning a BOM" -m "The creation date of the source object was preserved. This fix ensures the new object gets the current timestamp. (#36898)
Co-authored-by: jpb <jean-pascal.boudet@atm-consulting>
2026-01-19 14:38:13 +01:00
atm-lucas
39d30a23fe Duplicates in the result of the SQL query (#36913) 2026-01-19 13:44:09 +01:00
Alexandre SPANGARO
048d71dec3 FIX warnings with GETPOSTDATE and saverestore (#36886) 2026-01-16 02:54:27 +01:00
atm-vincent-p
d4d3c2089e Fix type contact translation (#36891) 2026-01-16 02:37:58 +01:00
Zakaria Boushaba
e18526dec5 Fix: Add SEARCH_LIMIT_AJAX constant support to select_produits_list() (#36893)
Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa>
2026-01-16 02:33:43 +01:00
Lucas Marcouiller
7c11c3a2a5 Fix #36290 (#36875)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-15 01:48:26 +01:00
Laurent Destailleur
7df6595351 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-01-13 16:04:30 +01:00
Laurent Destailleur
2cfdbd6b5f Try to use PR ID instead of PR url 2026-01-13 16:04:20 +01:00
ThomasNgr-OpenDSI
00d1bbce9c FIX: on event create/edit card, when adding a user, the reminder info was lost. (#36857)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-13 11:39:46 +01:00
Joachim Kueter
7f407a1183 FIX #36866 Project/Time Spent: changing a lined of consumed time does not store changed task assignment (#36867)
On the tab Project/Time Spent there is a list of consumed time, spent on the tasks of the project. Each line is showing a pencil icon to allow a modification of the data.

In edit mode, the assigned task can get changed to a different task of the project. Upon saving the edits, this change is getting ignored, the old task is still assigned:

We need to update the fk_element referencing the task, but we also need to adjust the values for duration_effective of both affected tasks (old and new).
2026-01-13 11:39:15 +01:00
ThomasNgr-OpenDSI
2e7ab21d01 FIX #GHSA-w5j3-8fcr-h87w (#36868)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-13 11:37:36 +01:00
atm-vincent-p
de96c57acf FIX contact type translation (#36863) 2026-01-13 11:35:32 +01:00
Laurent Destailleur
fcef8ec922 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2026-01-12 16:12:29 +01:00
Laurent Destailleur
4c1cde76d5 Fix warning 2026-01-12 16:12:18 +01:00
Braito
362113e653 Fix/emailcollector isanswer dolibarr references 22.0 (#36859)
* fix(emailcollector): accept replies via Dolibarr References

* style(emailcollector): fix indentation

---------

Co-authored-by: braito4 <braito4@users.noreply.github.com>
2026-01-12 15:56:50 +01:00
Alexandre SPANGARO
6b19b592ad FIX Accountancy - Add validation for overlapping fiscal year dates (#36836)
* FIX Accountancy - Add validation for overlapping fiscal year dates

* Optimize

* CI
2026-01-11 13:02:31 +01:00
Laurent Destailleur
04787d8cb0 FIX icon of mastodon social network 2026-01-11 12:57:26 +01:00
Laurent Destailleur
39ed2ece8f Backport fix for #36850 2026-01-11 12:48:58 +01:00
Expresion
6d6dfb3a5e Fix numeric input parsing to support comma as decimal separator (#36845)
* Fix numeric input parsing to support comma as decimal separator

GETPOSTINT()  only handles integer values and fails when input uses a comma as decimal

* Update dispatch.php

* Change GETPOST to GETPOSTFLOAT for price input

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-10 18:25:06 +01:00
Laurent Destailleur
608f89e882 Fix CI 2026-01-10 18:12:56 +01:00
Benjamin Falière
7b6051a0d0 FIX(ticket): check on TICKET_IMAGE_PUBLIC_INTERFACE (#36833)
* FIX(ticket): check on TICKET_IMAGE_PUBLIC_INTERFACE

Must use getDolGlobalString instead of getDolGlobalInt here

* Add contributor

---------

Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr>
2026-01-10 17:46:45 +01:00
Laurent Destailleur
6fabf82f1d Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2026-01-10 17:45:28 +01:00
Laurent Destailleur
b3669d4333 Try to fix script 2026-01-10 17:45:20 +01:00
Mathieu Moulin
a5b106fe70 Fix error removing reception with product batches (eatby/sellby) (#36846) 2026-01-10 17:30:45 +01:00
lvessiller-opendsi
f497a6a4fe FIX warning accountancy export from external module (#36832) 2026-01-08 18:54:15 +01:00
Eric - CAP-REL
db3d8a0a1a Merge pull request #35863 from RyAbn/18.0_FIX_CMailFile_syslog_message
FIX: php8.1 warning in syslog message
2026-01-08 09:56:27 +01:00
Eric - CAP-REL
d5cab67f4c Fix log message for empty cid_list
apply same fix as 20.0 to avoid conflicts on next merges
2026-01-08 09:55:28 +01:00
Eric - CAP-REL
85a0383b46 Merge branch '18.0' into 18.0_FIX_CMailFile_syslog_message 2026-01-08 09:52:47 +01:00
Eric - CAP-REL
c981b7ccb6 Merge pull request #36343 from noec764/18_FIX_socid_undefined
FIX: TakePos sometimes thirdpartyid = undefined
2026-01-08 09:47:52 +01:00
lvessiller-opendsi
590bf2dd0e Merge pull request #36616 from rycks/18_fix_ticket_double_slash_on_url
remove slash like other parts of dolibarr code for TICKET_URL_PUBLIC_…
2026-01-08 09:41:28 +01:00
lvessiller-opendsi
c25dda01b4 Merge pull request #36815 from lemathou/mmi-fix-reception-delete-stock-mvt
FIX : remove stock correctly when reception is deleted (like 82e092f)
2026-01-08 09:30:04 +01:00
Laurent Destailleur
f450dd00a8 Merge branch '18.0' into mmi-fix-reception-delete-stock-mvt 2026-01-07 18:41:06 +01:00
Mathieu Moulin
ad3304832d FIX : remove stock correctly when reception is deleted (like 82e092f) 2026-01-06 15:32:59 +01:00
lvessiller-opendsi
c33b7e0bf1 FIX finished regex in product import (#36770) 2025-12-30 11:03:20 +01:00
Eric Seigne
c017ea0341 Merge branch '18_fix_ticket_double_slash_on_url' of github.com:rycks/dolibarr into 18_fix_ticket_double_slash_on_url 2025-12-18 09:36:48 +01:00
Eric Seigne
eb4d9dec53 thanks to lionel : remove view.php in default value like other part of dolibarr 2025-12-18 09:36:45 +01:00
Laurent Destailleur
2ca80ffa67 Merge branch '18.0' into 18_fix_ticket_double_slash_on_url 2025-12-17 13:27:57 +01:00
Eric Seigne
8d84cec3ca remove slash like other parts of dolibarr code for TICKET_URL_PUBLIC_INTERFACE 2025-12-11 10:43:24 +01:00
Noé
2ee07bb049 FIX: Remove <?= 2025-12-04 17:27:57 +01:00
Noé
3416c6ccc0 FIX: getDolGlobalInt 2025-11-27 10:00:43 +01:00
Noé
92197cb100 FIX: php echo instead of <? 2025-11-21 16:06:09 +01:00
Noé
9319059349 FIX: Sometimes socid = undefined 2025-11-20 14:01:29 +01:00
Laurent Destailleur
1eed0e18a9 Update CMailFile.class.php 2025-10-21 02:11:56 +02:00
Laurent Destailleur
2153dbb0f1 Update CMailFile.class.php 2025-10-21 02:09:51 +02:00
Ryad ABANI
52446678d0 FIX: php8.1 warning in syslog message 2025-10-20 16:23:22 +02:00
Laurent Destailleur
b986f2f1a7 Debug v24 2025-03-05 11:13:24 +01:00
Laurent Destailleur
74157e15d2 Debug 2025-03-05 10:17:10 +01:00
Laurent Destailleur
fb70814412 Debug v24 2025-02-05 15:36:32 +01:00
Laurent Destailleur
c295e97f9c Debug 2025-02-05 14:59:32 +01:00
Laurent Destailleur
8478c38477 Debug 2025-02-05 13:57:10 +01:00
Laurent Destailleur
f6db26a21d Trans 2025-02-05 13:14:56 +01:00
Laurent Destailleur
3b9f0d9ce6 Clean code 2025-02-05 13:13:34 +01:00
Laurent Destailleur
ca41760a68 Add example of blockedlog archive file 2025-02-05 13:00:48 +01:00
Laurent Destailleur
483523e24c CSS 2025-02-05 11:52:09 +01:00
Laurent Destailleur
935374d368 Debug v24 2025-02-05 11:47:52 +01:00
Laurent Destailleur
5ea91b5399 Add example of blockedlog archive file 2025-02-05 11:11:51 +01:00
Laurent Destailleur
e09180ce0c Debug 2025-02-05 09:39:21 +01:00
Laurent Destailleur
de56758859 Fix pdf font for CZ 2026-02-18 11:36:17 +01:00
Laurent Destailleur
cc6b3f968c Fix mention 2026-02-18 03:45:33 +01:00
Laurent Destailleur
70d711e083 Debug savedemo 2026-02-18 03:36:56 +01:00
Laurent Destailleur
10beb6cfc6 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-01-16 12:52:41 +01:00
Laurent Destailleur
f72245353f Debug send email for takepos 2025-01-16 12:52:03 +01:00
Laurent Destailleur
717af97307 Fix reply to 2025-01-16 12:29:00 +01:00
Laurent Destailleur
ef7f607978 Debug v23 2025-01-16 12:24:02 +01:00
Noé Cendrier
429f01e72a FIX: linktoref should be able to receive more than 255 chars (#37262)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 17:25:19 +01:00
Laurent Destailleur
9ff8eb695e Debug v23 2026-02-17 16:59:07 +01:00
Laurent Destailleur
753d89d4ca Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-17 15:58:20 +01:00
Laurent Destailleur
cd6a3b8767 Debug v23 2026-02-17 15:58:10 +01:00
Frédéric FRANCE
ba01664d57 fix commoninvoice.class.php (#37267)
* fix commoninvoice.class.php

* Update commoninvoice.class.php
2026-02-17 15:32:16 +01:00
Laurent Destailleur
158119361f Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-16 21:44:56 +01:00
Laurent Destailleur
5433a5642d Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-16 21:21:13 +01:00
Laurent Destailleur
02f23d5193 Fix #37227 Fix #37233 2026-02-16 20:54:57 +01:00
Laurent Destailleur
7a73ad9566 Fix #37227 Fix #37233 2026-02-16 20:43:36 +01:00
Laurent Destailleur
96cd5b9afb Debug v23 2026-02-16 02:08:37 +01:00
Laurent Destailleur
1d3cfdb654 Debug v23 2026-02-16 01:22:30 +01:00
Laurent Destailleur
808a3f820c Debug v23 2026-02-16 01:22:21 +01:00
Laurent Destailleur
4e8f3b921f CSS 2026-02-15 22:52:38 +01:00
Laurent Destailleur
d1977c8e56 Add id of perm in url 2026-02-15 20:59:01 +01:00
Laurent Destailleur
62c6d8cbb8 Cleaner GET call 2026-02-15 20:49:39 +01:00
Laurent Destailleur
ba1cecb17e Update initdemo 2026-02-15 19:56:21 +01:00
Laurent Destailleur
0b81bef078 Debug v23 2026-02-12 21:46:15 +01:00
Laurent Destailleur
daa109f1d5 Prepare 23.0 2026-02-12 19:47:00 +01:00
hansemschnokeloch
c820404856 Error handling methods for commonobject (#37201) 2026-02-12 16:43:24 +01:00
Laurent Destailleur
caa5d7b347 Debug v23 2026-02-12 16:23:43 +01:00
Laurent Destailleur
6d48243b68 Add hook in isEditable() 2026-02-12 16:01:54 +01:00
Laurent Destailleur
8b0ed977e8 css 2026-02-12 13:27:44 +01:00
Laurent Destailleur
d51f2b0c34 css 2026-02-12 13:26:16 +01:00
Laurent Destailleur
85ccca6ca3 Debug v23 - filters on agenda pages 2026-02-12 01:22:01 +01:00
Laurent Destailleur
f23e6b541a Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-12 00:38:48 +01:00
Laurent Destailleur
a139ab1b20 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-11 21:17:08 +01:00
Laurent Destailleur
fa55a2987a Doc 2026-02-11 21:10:27 +01:00
Laurent Destailleur
9743441127 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-11 21:07:06 +01:00
Laurent Destailleur
1de655faaa Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-11 18:46:34 +01:00
Laurent Destailleur
44fcbb4c18 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-11 18:46:21 +01:00
Laurent Destailleur
97a3cf5f0c CI 2026-02-11 03:03:00 +01:00
Laurent Destailleur
785d94bc13 Debug v23 2026-02-11 03:01:00 +01:00
Laurent Destailleur
404f7288d9 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-11 02:26:06 +01:00
Laurent Destailleur
dac3b74111 clean code 2026-02-11 02:25:01 +01:00
Laurent Destailleur
bbbf405d3a Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-10 20:18:58 +01:00
Laurent Destailleur
d278909f5b Debug amount suggested on membership public form 2026-02-10 19:56:55 +01:00
hansemschnokeloch
6d0e42a82e Fix file path comment in supplier invoice module (#37133)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:32:41 +01:00
Alexandre SPANGARO
26787b8666 FIX Bank transfer admin - Warning & save 0 on constant PAYMENTBYBANKTRANSFER_ADDDAYS (#37175) 2026-02-10 15:15:26 +01:00
Alexandre SPANGARO
033667e0cc FIX Intracommreport - Warning & link problem on tab (#37176) 2026-02-10 15:11:30 +01:00
Alexandre SPANGARO
7801d27d82 FIX BOM - Class product missing, column offset and information recording (form/input overlap) in admin (#37177)
* FIX BOM - Class product missing in admin

* Fix column offset and information recording (form/input overlap)
2026-02-10 15:07:45 +01:00
Laurent Destailleur
3339d78245 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-10 14:41:52 +01:00
Laurent Destailleur
db5154871c More functions in blacklist (even if nw we use the whitelist by default) 2026-02-10 14:41:36 +01:00
Alexandre SPANGARO
178d6dbadc FIX Product - Warning on admin + CSS (#37158)
* FIX Product - Warning on admin

* CSS

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 00:47:23 +01:00
Alexandre SPANGARO
f9aaaffcd1 FIX Product - Warning on admin (#37157)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 00:46:51 +01:00
Laurent Destailleur
49f44ab3c0 Fix phpunit 2026-02-10 00:01:48 +01:00
Noé Cendrier
016e3901c3 FIX: missing include for blockedlog lib (#37165) 2026-02-09 23:07:39 +01:00
Laurent Destailleur
fc2888b42d CI 2026-02-09 23:01:01 +01:00
Laurent Destailleur
4aae67aa27 Disable phan on v23 2026-02-09 19:58:02 +01:00
Laurent Destailleur
ccaf2eae29 Fix CI 2026-02-09 19:20:26 +01:00
Laurent Destailleur
75378a3eed Fix CI 2026-02-09 19:17:27 +01:00
Laurent Destailleur
1ee972d997 Fix CI 2026-02-09 19:16:55 +01:00
Laurent Destailleur
b69f2b81dd CI 2026-02-09 18:41:19 +01:00
Laurent Destailleur
f69d0dd04e CI 2026-02-09 18:39:44 +01:00
Laurent Destailleur
1950fbdd5f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-09 16:40:24 +01:00
Laurent Destailleur
d711c93577 cs 2026-02-09 16:40:13 +01:00
Yamil Esteban Garcia
62779ae0bc Fix: IRPF tax not applied when creating invoice from project times (#37077)
* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 03:56:16 +01:00
Laurent Destailleur
3b441d22f6 CSS 2026-02-09 00:34:53 +01:00
Laurent Destailleur
5e3c3fd582 Fix package debian 2026-02-08 22:48:23 +01:00
Jarvis
07cb0adade Update modProduct.class.php (#37087)
Fix: allow import of sell_or_eat_by_mandatory for products

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 22:27:12 +01:00
Laurent Destailleur
a7a7dfb738 Debug v23 2026-02-08 21:34:12 +01:00
Laurent Destailleur
008a22eb17 Fix spellcheck 2026-02-08 21:24:34 +01:00
Laurent Destailleur
79bf9a0a4b Add error message 2026-02-08 20:40:25 +01:00
Laurent Destailleur
c386f94fab Debug v23 - Filter on action type ko 2026-02-08 19:33:09 +01:00
Laurent Destailleur
1173164d7e Debug v23 - Filter on action type ko 2026-02-08 19:30:17 +01:00
Laurent Destailleur
3b6c448787 Debug v23 - Min price was wrong in multicurrency mode 2026-02-08 18:52:24 +01:00
Laurent Destailleur
ba28d16da4 Sec: Add param $dolibarr_website_allow_custom_php to block by default
any PHP content in website module.
2026-02-08 17:41:42 +01:00
Laurent Destailleur
8feb5275ba Debug v23 2026-02-08 15:38:19 +01:00
Laurent Destailleur
8d96ed3a03 Debug v23 2026-02-08 15:02:48 +01:00
Laurent Destailleur
4a7c6c6700 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-08 14:55:13 +01:00
Vanyo
534995dd6c Initialize arrayforbutaction before hook (#37149) 2026-02-08 14:44:29 +01:00
Laurent Destailleur
d0c5d523a3 FIX Show total on multicurrency only if currency are the same on all
lines
2026-02-08 13:59:19 +01:00
Laurent Destailleur
574b4b5d62 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-08 13:12:52 +01:00
Laurent Destailleur
713918dadf Debug v23 2026-02-08 13:05:57 +01:00
Laurent Destailleur
0111114502 Fix CI 2026-02-08 00:19:56 +01:00
adamhocini
79ba81a75d Correct linked_objects assignment for 'propal' #Wrong sourcetype 'commande' instead of 'propal' when creating recurring invoice template from invoice linked to proposal #37099 @defrance (#37112)
* Correct linked_objects assignment for 'propal'

@defrance Adam Hocini

* Refactor linked objects assignment for proposals

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 00:11:46 +01:00
DarmonNoah
08040ec30e Fixed Bug : email sending test #36741 (#37107)
Fixed Bug : email sending test #36741
@defrance 
-->
Issue fixed
The problem was caused by initializing $result = 0 in core/actions_sendmails.inc.php.
When sending a test email from Setup → Emails, there is no $object to fetch. As a result, $result remained 0 and the code incorrectly triggered ErrorFailedToReadObject.

The fix consists in explicitly setting $result = 1 when no $object is provided (test email / generic email context). This correctly treats the absence of an object as a valid case and restores the ability to send test emails, while keeping $result properly initialized.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 00:11:36 +01:00
AnthoXic
51c7074687 Update card.php (#37108)
@defrance https://github.com/Dolibarr/dolibarr/issues/36767
2026-02-07 23:41:34 +01:00
Laurent Destailleur
ce6802ab77 Edit form must match have order of field similat to create form 2026-02-07 23:25:50 +01:00
Laurent Destailleur
6bc3bb0761 More debug info 2026-02-07 22:28:11 +01:00
Laurent Destailleur
a48485195f Fix CI 2026-02-07 22:03:11 +01:00
Laurent Destailleur
556b103dc6 Fix max 2026-02-07 21:57:02 +01:00
Laurent Destailleur
205cb50766 Debug v23 2026-02-07 21:55:20 +01:00
Laurent Destailleur
2ceadc0741 css 2026-02-07 21:39:27 +01:00
Laurent Destailleur
c852aa346a Fix the limit 2026-02-07 21:38:51 +01:00
Laurent Destailleur
c352ae9615 Debug v23 2026-02-07 21:31:33 +01:00
Laurent Destailleur
8d54cac841 Code comment 2026-02-07 21:03:04 +01:00
Laurent Destailleur
fab3521672 Clean code 2026-02-07 20:44:03 +01:00
Laurent Destailleur
012c1fb078 Debug v23 - sql request for list of actioncomm must not use a OR 2026-02-07 20:07:09 +01:00
Laurent Destailleur
7b91fdcfa5 Better rate showing 2026-02-07 17:22:46 +01:00
Laurent Destailleur
50e7d41f7a Fix missing lagal requirement 2026-02-07 17:09:43 +01:00
Laurent Destailleur
447242b3d5 Debug v23 2026-02-07 15:43:49 +01:00
Laurent Destailleur
529db21a6c Debug extrafields chckbxlist v23 2026-02-07 14:56:58 +01:00
Laurent Destailleur
943827834c Clean code 2026-02-07 13:21:53 +01:00
Laurent Destailleur
d11c85be43 Debug v23 2026-02-07 12:06:35 +01:00
Laurent Destailleur
c92a6aaf04 Debug v23 2026-02-07 10:26:57 +01:00
Laurent Destailleur
bbac3b9a4a Add tool to fix data of payments not correctly linked to bank (need
hidden option to allow this data correction)
2026-02-06 18:05:53 +01:00
Laurent Destailleur
8a4d4a8056 Fix when thirdparty found twice. 2026-02-06 13:42:47 +01:00
Laurent Destailleur
7e3df7c5f8 FIX Error on large product database 2026-02-06 03:11:52 +01:00
Laurent Destailleur
081e05047d Fix var 2026-02-06 02:41:22 +01:00
Florian Hödl
65224fe6cc fix(emailcollector): prevent PHPIMAP body carryover between emails (#37121)
Reset global variables $htmlmsg, $plainmsg, and $attachments before
processing each email in PHPIMAP mode to prevent email body content
from previous email carrying over into the next one.

This issue only affected Microsoft OAuth (PHPIMAP) mode. When an email
had no plain-text body but the previous email did, the previous email's
plain-text would incorrectly be used for the current email.

The $charset variable is intentionally not reset as PHPIMAP handles
charset internally, unlike native IMAP mode.

Also standardized array syntax to use array() consistently per Dolibarr
coding conventions.

Co-authored-by: Florian Hödl <florian@hoedl.co>
2026-02-06 02:38:35 +01:00
Laurent Destailleur
30e8eff3d9 css 2026-02-04 19:47:40 +01:00
Laurent Destailleur
cabc42f308 Close #36975 2026-02-04 18:05:40 +01:00
Laurent Destailleur
1ede9e3630 Fix comment and keep external modules out of core modules 2026-02-04 17:36:44 +01:00
Charlène Benke
ca64d18833 family assignment logic on user perms of external modules (#36456)
* family assignment logic on user perms of external modules

Updated family assignment logic to default to 'other' if family does not exist in $familyinfo.

* Update copyright year for Charlene Benke
2026-02-04 17:19:43 +01:00
Vanyo
2304e4ccfe Change translation function to transnoentities (#37065)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-04 15:09:23 +01:00
Laurent Destailleur
4fdbfcf581 Debug v23 2026-02-04 14:24:18 +01:00
Charlène Benke
2a157d1aec bad link on sql in fichinter list (#37081) 2026-02-04 14:20:01 +01:00
Laurent Destailleur
456affb148 Debug v23 2026-02-03 19:06:49 +01:00
Laurent Destailleur
4cdd513914 css 2026-02-03 17:57:18 +01:00
Laurent Destailleur
cd71bf33ca Debug v23 2026-02-03 14:38:03 +01:00
Laurent Destailleur
581aafdbff CSS on current day 2026-02-03 12:30:03 +01:00
Laurent Destailleur
ac5b2c994b css 2026-02-03 12:09:54 +01:00
Laurent Destailleur
29cadfb644 Debug v23 2026-02-03 11:36:51 +01:00
Laurent Destailleur
276cbb2cd7 Trans 2026-02-03 11:32:11 +01:00
Laurent Destailleur
de4dd2e735 Link and filter on ountry for holiday types 2026-02-03 11:23:48 +01:00
Laurent Destailleur
fe6b6a8e42 Debug v23 2026-02-02 20:52:20 +01:00
Laurent Destailleur
3379457ed7 Fix situation invoice 2026-02-02 20:03:36 +01:00
Laurent Destailleur
b28c19d48d Fix sql syntax error 2026-02-02 16:19:37 +01:00
Laurent Destailleur
9ce603eb97 Fix CSS 2026-02-02 16:12:21 +01:00
Laurent Destailleur
c2574715f1 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-02 15:54:18 +01:00
Laurent Destailleur
440050b7a8 Debug v23 2026-02-02 15:53:41 +01:00
Alexandre SPANGARO
4faef8f791 NEW Accountancy - Select between accrual accounting and cash accounting (#37050) 2026-02-01 18:09:24 +01:00
Laurent Destailleur
3a67d56a4f Fix CI 2026-02-01 02:33:07 +01:00
Jyhere
b74382c7e2 FIX: Add htmlname and selectedrate to parameters array for hook (#36998)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 02:09:40 +01:00
Laurent Destailleur
3eed365991 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-01 02:08:29 +01:00
Alexandre SPANGARO
51b66f0c17 Warning on account model (#37042)
* Error on account model

* Simplify rowid assignment in accountmodel.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 02:01:16 +01:00
Laurent Destailleur
280fb84147 Clean comment 2026-02-01 01:52:58 +01:00
Alexandre SPANGARO
19a29402de Warning on export/import - Add isset() protection in Export::load_arrays() & Import::load_arrays() (#37043)
* Warning on export - Add isset() protection in Export::load_arrays()

* Warning on import - Add isset() protection in Import::load_arrays()

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 01:27:33 +01:00
Laurent Destailleur
01faea65d5 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-02-01 01:02:52 +01:00
Laurent Destailleur
265acd7133 Fix CI 2026-02-01 01:01:49 +01:00
Laurent Destailleur
a71e07c6e4 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-30 13:33:27 +01:00
Laurent Destailleur
8d7588fbf6 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-30 13:24:28 +01:00
Laurent Destailleur
4fd58bf4ea CI 2026-01-30 13:21:27 +01:00
Frédéric FRANCE
00bc3e60d9 fix CI (#37033) 2026-01-30 13:09:17 +01:00
Laurent Destailleur
92e655a28d Debug v23 - Fix ipn for dispute and withdraw funds. 2026-01-30 05:48:51 +01:00
Laurent Destailleur
39ca59eb37 FIX Division by zero 2026-01-30 03:20:29 +01:00
Laurent Destailleur
805f0ed971 Debug v24 2026-01-30 03:14:22 +01:00
Laurent Destailleur
8923cd9ac0 Fix when there is more than 99 direct debit in same month 2026-01-30 03:14:06 +01:00
Laurent Destailleur
413021900a CSS 2026-01-30 03:13:09 +01:00
Laurent Destailleur
0b891d1790 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-30 03:11:29 +01:00
Laurent Destailleur
7c02095d4d Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-30 00:54:49 +01:00
Laurent Destailleur
78b21d26d1 Debug v23 2026-01-30 00:12:46 +01:00
Frédéric FRANCE
479fcde7e9 fix facture.class.php (#37031) 2026-01-30 00:06:29 +01:00
Laurent Destailleur
26630a746b Debug v23 2026-01-29 23:45:05 +01:00
Laurent Destailleur
6469399afc Clean code 2026-01-29 23:15:17 +01:00
Laurent Destailleur
6b0a3e0f68 FIX Pb in total price of line when adding the discount of a down payment
when unit price was using a high accuracy.
2026-01-29 23:15:07 +01:00
Laurent Destailleur
75ae360898 Fix type 2026-01-29 15:20:52 +01:00
Laurent Destailleur
0e4243a994 Debug v23 2026-01-29 15:13:29 +01:00
Laurent Destailleur
416370eddf Fix label of dispute 2026-01-29 13:44:25 +01:00
Laurent Destailleur
e4d4f65b27 Fix syntax error 2026-01-29 13:31:35 +01:00
Laurent Destailleur
285371f49e Debug v23 - fix code for rounding 2026-01-29 13:01:49 +01:00
Laurent Destailleur
ca017aa342 Debug v23 2026-01-29 10:55:21 +01:00
Laurent Destailleur
28925a4fa1 css 2026-01-28 19:19:59 +01:00
atm-jonathan
65c38c92fb prevent ST_AsWKT() (#37013)
* prevent ST_AsWKT()

* Update commonobject.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-28 18:21:50 +01:00
hansemschnokeloch
192ac39831 Remove jstz.min.js from JavaScript array (#37017)
jstz.min.js was deleted in 5599ac733b
2026-01-28 18:01:39 +01:00
Laurent Destailleur
67fe092db0 Fix error message 2026-01-28 12:55:15 +01:00
Laurent Destailleur
a02cf18703 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-28 12:51:14 +01:00
Laurent Destailleur
62fe933b79 Doc 2026-01-28 12:50:39 +01:00
Laurent Destailleur
cbc64dfcbf Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-27 23:29:29 +01:00
Laurent Destailleur
47f8bec9ce Better error management 2026-01-27 23:28:49 +01:00
Laurent Destailleur
abb195ff68 Log 2026-01-27 23:04:33 +01:00
Laurent Destailleur
84ef61596d Better log 2026-01-27 23:02:53 +01:00
Laurent Destailleur
050f3ec78a Debug v23 2026-01-27 16:52:49 +01:00
Laurent Destailleur
812ea8f66f Debug v23 2026-01-27 16:23:39 +01:00
Laurent Destailleur
cd0b8ceab5 Debug v23 2026-01-27 16:21:35 +01:00
Laurent Destailleur
4017f8166e Doc 2026-01-27 14:47:04 +01:00
Laurent Destailleur
2d4e09b519 Fix trans and warning 2026-01-27 14:26:39 +01:00
Laurent Destailleur
08bf5af5d4 Default value 2026-01-27 13:46:35 +01:00
Laurent Destailleur
97b7e52a97 Add the registration page 2026-01-27 01:13:22 +01:00
Laurent Destailleur
70089d2e4d Prepare v23 2026-01-26 22:38:38 +01:00
Laurent Destailleur
48f067fdfc Set default value to on 2026-01-26 20:09:10 +01:00
Laurent Destailleur
4224c9fc05 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-26 19:34:10 +01:00
Laurent Destailleur
299380057b Debug v23 2026-01-26 18:41:07 +01:00
Laurent Destailleur
7e29718148 CSS v23 2026-01-26 15:17:28 +01:00
Laurent Destailleur
1db633ee43 Debug v23 2026-01-26 15:09:45 +01:00
Laurent Destailleur
e6fc383355 CSS v23 2026-01-26 15:06:18 +01:00
Laurent Destailleur
3e2217c47f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-26 14:32:40 +01:00
Laurent Destailleur
35847a94f0 Debug v23 2026-01-26 14:32:30 +01:00
Alexandre SPANGARO
7efb82fc79 Update VAT rate by default (#36988)
* Update VAT rate for Nederland

* Update VAT rate for Italy
2026-01-26 11:48:34 +01:00
Laurent Destailleur
98cba6a94a Trans 2026-01-25 16:01:31 +01:00
Laurent Destailleur
3822ae8e77 Debug v23 2026-01-25 15:52:25 +01:00
Laurent Destailleur
e3eb12c9d7 Debug v23 - Fix trans 2026-01-25 15:33:19 +01:00
Braito
388c25f588 Fix SMTP OAuth refresh scopes (#36950)
Recreate the OAuth service with its configured scopes when refreshing an access token (required by some providers like Microsoft v2).

Also keep the previous refresh token when the refreshed token does not include one (e.g. Google returns it only once).

Co-authored-by: caminotravelcenter <caminotravelcenter@localhost>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 20:13:35 +01:00
Laurent Destailleur
a452dfb596 FIX substitution of vars in donation templates 2026-01-24 17:41:06 +01:00
Laurent Destailleur
1ddbaf1181 Debug v23 - navigation into fiscal years 2026-01-24 15:57:40 +01:00
Laurent Destailleur
1eb0970e11 Fix ci 2026-01-24 15:10:33 +01:00
Laurent Destailleur
c134da09ea Debug v23 2026-01-24 14:53:17 +01:00
Alexandre SPANGARO
17c50b10a3 Fix CSS (#36977)
* Fix CSS

* Hide on smartphone

* Same on journal view

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 14:02:21 +01:00
Laurent Destailleur
023c7f4d1b Fix ci 2026-01-24 13:58:07 +01:00
Laurent Destailleur
ea69506e53 Fix code action 2026-01-24 13:54:57 +01:00
Laurent Destailleur
ed84b59f22 Fix ci 2026-01-24 13:43:20 +01:00
Laurent Destailleur
ebbaeb5129 Clean code 2026-01-23 22:34:17 +01:00
Laurent Destailleur
b79814f864 Debug v23 - Stock management on parent kit does not work yet (for example when creating/closing shipment). Edit interface to be more clear with that. 2026-01-23 22:32:32 +01:00
Laurent Destailleur
2fc7d78709 Debug v23 2026-01-23 19:18:13 +01:00
Laurent Destailleur
5e176ab605 Fix count into badge 2026-01-23 19:14:45 +01:00
Laurent Destailleur
daae0f6f82 Fix select resource 2026-01-23 18:34:31 +01:00
Charlène Benke
42d270d3df Change resource selection index from 1 to 2 (#36955)
fix warning causing by returning array (1 to 2) and suppress search button (0 to 2)
2026-01-23 18:34:26 +01:00
Laurent Destailleur
39d39f475d Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-23 17:46:38 +01:00
Zakaria Boushaba
6a6994cbdc fix: exclude special lines from supplier order dispatch count (#36964)
Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa>
2026-01-23 16:57:49 +01:00
Lucas Marcouiller
efa4a27b2a Fix bad trans for member subscription on import (#36969)
* Fix bad trans for member subscription on import

* fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-23 16:52:44 +01:00
Lucas Marcouiller
4c0f567ced Fix email collector ticket fetch (#36968)
* Fix email collector ticket fetch

* fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-23 16:52:39 +01:00
Laurent Destailleur
081a1abbe8 Debug v23 2026-01-23 16:49:49 +01:00
Laurent Destailleur
ecee7722c5 Fix CSS 2026-01-23 16:31:51 +01:00
Laurent Destailleur
9a6f9c6190 Trans 2026-01-23 14:31:34 +01:00
Laurent Destailleur
3fc7f06a30 Fix CI 2026-01-23 13:46:42 +01:00
Laurent Destailleur
35285756a9 Fix label 2026-01-22 16:42:23 +01:00
Laurent Destailleur
5e406a945b Fix message on button tooltip 2026-01-22 16:41:11 +01:00
Laurent Destailleur
882dc419d4 Label 2026-01-21 21:49:13 +01:00
Laurent Destailleur
669e2bd726 Need a label for autorecord stripe payouts 2026-01-21 21:48:28 +01:00
Laurent Destailleur
34a195c810 Fix label 2026-01-21 21:46:38 +01:00
Laurent Destailleur
0e960ea32d Fix round in stripe amount 2026-01-21 21:00:37 +01:00
Laurent Destailleur
4e9965ea70 Fix log 2026-01-21 19:19:57 +01:00
Laurent Destailleur
585c4ae04e Log 2026-01-21 19:15:52 +01:00
Laurent Destailleur
ff1bf6b2df Add log 2026-01-21 18:47:04 +01:00
Laurent Destailleur
12ca0fc894 Debug v23 2026-01-21 18:27:18 +01:00
splohmer
f39ef3d5c7 FIX missmatch of permission check of button and action of cancel delivery note (expedition) (#36943)
In expedition/card.php there is the action "confirm_cancel" which checks for the right supprimer of expedition. The corresponding UI Button checks for creer of expedition. This means some people can see the button, but nothing happens when clicking on it (also no error message).
2026-01-21 14:25:40 +01:00
Laurent Destailleur
0daf289924 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-21 12:31:51 +01:00
Laurent Destailleur
d4602e6b6f Fix ci 2026-01-21 12:31:38 +01:00
Lucas Marcouiller
7c533b7068 Fix email layout selector for product (#36948)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-21 12:28:05 +01:00
Laurent Destailleur
b0a67d5c4d Fix ci 2026-01-21 12:27:46 +01:00
Laurent Destailleur
068fdc9431 Debug v23 2026-01-21 12:02:13 +01:00
Laurent Destailleur
ec77531a2a Debug v23 2026-01-21 11:58:56 +01:00
Laurent Destailleur
70d7357128 Debug v23 2026-01-21 11:35:36 +01:00
Laurent Destailleur
f8d9a2e829 Fix css and responsive pb 2026-01-21 11:16:10 +01:00
Laurent Destailleur
7e17711871 Fix trans 2026-01-21 00:58:54 +01:00
Laurent Destailleur
b769c1a8b0 Fix css 2026-01-21 00:47:25 +01:00
Laurent Destailleur
f8123ebc64 CSS 2026-01-20 23:49:36 +01:00
Laurent Destailleur
5e72196245 Fix link 2026-01-20 23:43:58 +01:00
Laurent Destailleur
9aa5bf4aef Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-20 14:54:01 +01:00
Laurent Destailleur
aee871f0b5 Debug v23 2026-01-20 14:53:50 +01:00
Alexandre SPANGARO
b2c5ee5c4a FIX Accountancy - Chart of account - Some problem on backtopage (#36910)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-20 11:35:02 +01:00
Laurent Destailleur
99d1aad0b2 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-20 02:11:52 +01:00
Laurent Destailleur
cba8ccaa32 Fix PROPAL_ENABLE_NEGATIVE_QTY and ORDER_ENABLE_NEGATIVE_QTY 2026-01-20 02:11:14 +01:00
Laurent Destailleur
3e3e2a3759 Fix CI 2026-01-19 21:06:51 +01:00
Laurent Destailleur
8757990a52 Try to force phan version 2026-01-19 20:46:11 +01:00
Laurent Destailleur
dec35ff489 Merge manually #36851 emailcollector phpimap in reply to oauth v22. 2026-01-19 20:33:47 +01:00
Laurent Destailleur
28cdf7d121 Close #36889 manually, too many conflict due to non atomic PR. 2026-01-19 19:47:36 +01:00
Laurent Destailleur
3f14dc0562 Fix CI 2026-01-19 19:07:29 +01:00
Laurent Destailleur
1175f20f97 Fix CI 2026-01-19 19:07:14 +01:00
Laurent Destailleur
7d62a04fda Fix CI 2026-01-19 18:16:57 +01:00
Laurent Destailleur
6cde33dfd1 Try to fix ci 2026-01-19 18:00:48 +01:00
Laurent Destailleur
07d10fdb22 CI 2026-01-19 17:36:11 +01:00
Laurent Destailleur
e00086d057 Fix ci 2026-01-19 17:34:05 +01:00
Laurent Destailleur
e3d1e21df3 Fix ci 2026-01-19 17:21:45 +01:00
Laurent Destailleur
8dd729af9a Fix id ci 2026-01-19 17:18:57 +01:00
Laurent Destailleur
9857539204 Fix ci 2026-01-19 17:11:42 +01:00
Laurent Destailleur
abb256212a Ci 2026-01-19 17:05:01 +01:00
Laurent Destailleur
fd1b690813 ci 2026-01-19 16:53:17 +01:00
Laurent Destailleur
05f8d70c39 ci 2026-01-19 16:46:00 +01:00
Laurent Destailleur
e6c735b66e cs 2026-01-19 16:42:25 +01:00
Laurent Destailleur
d4860519a6 ci 2026-01-19 16:36:47 +01:00
Laurent Destailleur
af24facf4a Ci 2026-01-19 16:20:55 +01:00
Laurent Destailleur
2a2bc335c8 Fix ci 2026-01-19 16:14:20 +01:00
Laurent Destailleur
b12b20221b Fix CI 2026-01-19 16:10:30 +01:00
Laurent Destailleur
0fb5a9b3e9 Fix CI 2026-01-19 16:05:31 +01:00
Laurent Destailleur
b46b8b4476 Fix shellcheck 2026-01-19 16:00:11 +01:00
Laurent Destailleur
22283af99c Fix CI 2026-01-19 15:55:51 +01:00
Laurent Destailleur
6a103a9ac9 Fix CI 2026-01-19 15:50:45 +01:00
Laurent Destailleur
3043cf65d1 Fix CI 2026-01-19 15:48:01 +01:00
Laurent Destailleur
5ab2014e09 Try to run phan and phpstan on modified files only 2026-01-19 15:34:28 +01:00
Laurent Destailleur
5c63541097 Fix CI 2026-01-19 15:12:57 +01:00
Laurent Destailleur
99c7effb9b Fix civility_code vs civility_id 2026-01-19 15:04:13 +01:00
Laurent Destailleur
e61c8989f3 Ignore phan false positive 2026-01-19 14:55:37 +01:00
Laurent Destailleur
e52bd93ce0 Fix #36896 2026-01-19 14:46:58 +01:00
Laurent Destailleur
f4693352ca Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-19 14:36:39 +01:00
Laurent Destailleur
a85e25c807 Fix warning 2026-01-19 14:36:29 +01:00
Laurent Destailleur
6ed576bc9f Debug v23 2026-01-19 14:28:33 +01:00
Laurent Destailleur
6a5a8ad951 FIX #36902 2026-01-19 13:36:48 +01:00
Laurent Destailleur
a42ce189ea Trans 2026-01-19 00:22:15 +01:00
Laurent Destailleur
a9abf5c9f2 Trans 2026-01-19 00:21:31 +01:00
Laurent Destailleur
5d18db5aea Disable remote access in test 2026-01-16 18:15:51 +01:00
Laurent Destailleur
f94e1c24fc Fix status of dispute 2026-01-16 16:51:15 +01:00
Laurent Destailleur
062f6d18a4 Fix label in list 2026-01-16 16:43:00 +01:00
Laurent Destailleur
8b79913f6f Fix no translate 2026-01-16 16:36:36 +01:00
Laurent Destailleur
d953f0caf8 Fix color of status 2026-01-16 16:29:26 +01:00
Laurent Destailleur
a7d0206156 Debug v23 - Fix label of dispute status 2026-01-16 16:28:07 +01:00
Laurent Destailleur
5bb00b827a Fix trans 2026-01-16 16:17:14 +01:00
Laurent Destailleur
f240f53e8c Sync transifex 2026-01-16 16:00:55 +01:00
Laurent Destailleur
020895f404 Doc 2026-01-16 15:13:33 +01:00
Laurent Destailleur
d378d1f8cc Debug v23 2026-01-16 14:51:32 +01:00
Laurent Destailleur
79d5c0c418 Debug v23 2026-01-15 16:12:14 +01:00
Laurent Destailleur
8ed279a488 Missing PGK currency 2026-01-15 16:10:15 +01:00
Laurent Destailleur
7abf0cfe68 Add PGK currency 2026-01-15 15:49:38 +01:00
Laurent Destailleur
f8e0ff19da Debug v23 2026-01-15 15:44:03 +01:00
Laurent Destailleur
24d7e4f24d Debug v23 - PDF generation error if additional PDF name not set 2026-01-15 15:37:33 +01:00
Laurent Destailleur
87c01a3371 Debug v23 - migrate_reload_modules was broken 2026-01-15 15:22:33 +01:00
Laurent Destailleur
7f2d0efa22 Debug v23 2026-01-15 11:52:04 +01:00
Laurent Destailleur
bedf25f1f4 Debug v23 2026-01-15 11:19:07 +01:00
Laurent Destailleur
1be0b12b3f Debug v23 2026-01-15 11:00:57 +01:00
Laurent Destailleur
89d380db67 Fix description 2026-01-15 03:12:15 +01:00
Laurent Destailleur
a5dd3cf63b Fix css regression 2026-01-15 02:44:23 +01:00
Lucas Marcouiller
69de2e8cdd Fix agenda search for holiday or birthday (#36878)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 02:05:33 +01:00
Laurent Destailleur
4b9b0877b1 Debug v23 2026-01-15 01:10:28 +01:00
Laurent Destailleur
091b2b3f77 Fix trans 2026-01-15 00:46:33 +01:00
Laurent Destailleur
4126329f3d Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into 23.0 2026-01-15 00:39:06 +01:00
Laurent Destailleur
f17cc801b6 css 2026-01-15 00:38:35 +01:00
Laurent Destailleur
4af57f9f46 CSS 2026-01-14 22:09:56 +01:00
Laurent Destailleur
d4051faf35 Fix CI 2026-01-14 21:38:45 +01:00
Laurent Destailleur
e510043ade css 2026-01-14 19:44:19 +01:00
Laurent Destailleur
9ff559a0ad Fix demo file 2026-01-14 16:07:56 +01:00
Laurent Destailleur
6a80ef4019 Demo template 2026-01-14 16:01:25 +01:00
Laurent Destailleur
0a12caf313 Debug v23 2026-01-14 15:59:58 +01:00
Laurent Destailleur
c940376446 Clean sql 2026-01-14 15:41:44 +01:00
Laurent Destailleur
efdbf9a95c Trans 2026-01-14 14:28:30 +01:00
Laurent Destailleur
b487a95d86 Fix export for quadratus 2026-01-14 14:27:16 +01:00
Laurent Destailleur
053cd4e020 Init var 2026-01-14 14:13:13 +01:00
Laurent Destailleur
3e2598f8ff FIX Debug v23 - Pb in export accountancy. Var not defined. Missing
conditions for dol_dir_list. Pb cache not used when not found. Header
set at end.
2026-01-14 14:04:53 +01:00
Laurent Destailleur
e266a42545 Fix warning 2026-01-14 12:22:11 +01:00
Laurent Destailleur
dec9dfc06b FIX css 2026-01-14 12:01:22 +01:00
Laurent Destailleur
8e4762b2e1 Fix generic password type 2026-01-13 19:00:22 +01:00
Laurent Destailleur
02656bbcb8 Doc 2026-01-13 18:50:10 +01:00
Laurent Destailleur
1eda4e6157 Fix name of Oauth entry must not have special chars 2026-01-13 16:37:18 +01:00
Laurent Destailleur
85c8612c87 Fix warning oauth 2026-01-13 15:57:09 +01:00
Laurent Destailleur
dc5b719065 Fix add missing message once token has been saved 2026-01-13 15:39:04 +01:00
Laurent Destailleur
58d1254212 Fix missing state 2026-01-13 15:38:58 +01:00
Laurent Destailleur
ab9c1a80e6 CSS 2026-01-13 11:20:42 +01:00
Laurent Destailleur
9cd99ba4d2 Fix warning 2026-01-12 16:15:17 +01:00
Laurent Destailleur
e1345e225f Fix css 2026-01-12 15:55:34 +01:00
Laurent Destailleur
fcedaa150e CSS 2026-01-12 14:34:14 +01:00
Laurent Destailleur
9140e0599a Debug v23 2026-01-12 14:32:59 +01:00
Laurent Destailleur
2754b6485d Debug v23 2026-01-12 01:34:27 +01:00
Laurent Destailleur
544f4971bc Debug v23 2026-01-12 01:00:05 +01:00
Laurent Destailleur
a56645784c Prepare 23.0 2026-01-11 18:58:17 +01:00
Laurent Destailleur
b533548caa Prepare 23.0 2026-01-11 18:57:40 +01:00
Laurent Destailleur
aa0563a54a Debug v23 2026-01-11 18:41:11 +01:00
Laurent Destailleur
9c68ba8759 Debug v23 2026-01-11 18:17:21 +01:00
Laurent Destailleur
2759d409e4 Debug v23 2026-01-11 17:57:15 +01:00
Laurent Destailleur
049fcba06a Doc 2026-01-11 17:53:04 +01:00
Laurent Destailleur
342a6f754b Fix CI 2026-01-11 17:51:13 +01:00
Laurent Destailleur
a96bba2199 CSS v23 2026-01-11 17:40:21 +01:00
Laurent Destailleur
6e9225ce8b Debug v23 2026-01-11 16:17:12 +01:00
Laurent Destailleur
a41e9941f9 CSS 2026-01-11 16:00:00 +01:00
Laurent Destailleur
99b88e876f css 2026-01-11 14:26:55 +01:00
Laurent Destailleur
c698f4dc28 Backport some fixes of #36851 2026-01-11 13:12:38 +01:00
Laurent Destailleur
391fd8dab6 FIX icon of mastodon social network 2026-01-11 12:55:58 +01:00
spsolauv
8e37e310e0 CLOSE issue 36744 fix user can delete some actioncomm on which he has not the right (#36747)
* CLOSE issue 36744 fix user can delete some actioncomm on which he has not the right

* Fix whitespace

* Refactor delete confirmation logic for user access

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-11 12:34:47 +01:00
Laurent Destailleur
cc88462e1a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-01-16 12:21:46 +01:00
Laurent Destailleur
22a1340ba9 Debug v23 2025-01-16 12:21:06 +01:00
Mohamed DAOUD
2faa32b9c8 fix iseditable hook (#37269)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 19:42:12 +01:00
Laurent Destailleur
1a3662176b Fix CI 2026-02-17 18:44:03 +01:00
Charlène Benke
177c5eb51f Add $dolibarr_main_restrict_eval_methods to install step1.php (#37268)
Since this variable has a significant impact in future versions of Dolibarr, it is preferable that it be directly included in the conf.php file created during installation.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 18:22:53 +01:00
Laurent Destailleur
dff4b0077b Restore deleted file 2026-02-17 18:10:31 +01:00
Laurent Destailleur
f1c47cf536 CI 2026-02-17 18:06:56 +01:00
Laurent Destailleur
233865da21 NEW Increase satement decription to 12 on card payment, 22 on sepa 2026-02-17 18:05:44 +01:00
Laurent Destailleur
30e1fc6c9f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-17 17:27:34 +01:00
Laurent Destailleur
de0832bcea Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-17 17:23:29 +01:00
Laurent Destailleur
6cf4969100 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-17 17:22:50 +01:00
Laurent Destailleur
bebc6fbb78 FixCI 2026-02-17 17:22:32 +01:00
Frédéric FRANCE
589fe1215a clean code pdf.lib.php (#37265)
* clean code pdf.lib.php

* Update pdf.lib.php

* Update pdf.lib.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 17:00:38 +01:00
Laurent Destailleur
cfedd3b485 Fix CI 2026-02-17 16:15:26 +01:00
Laurent Destailleur
d2a78ce515 CI 2026-02-17 16:02:55 +01:00
Laurent Destailleur
b1aefa13d7 CI 2026-02-17 15:36:58 +01:00
Laurent Destailleur
9d0a2c0978 CI 2026-02-17 15:33:38 +01:00
Laurent Destailleur
2328de8e7c Fix CI 2026-02-17 15:16:31 +01:00
Laurent Destailleur
c205803687 Debug v24 2026-02-17 15:01:38 +01:00
Laurent Destailleur
b595f8468d Fix return 2026-02-17 14:56:03 +01:00
Laurent Destailleur
9c837750a5 Add method to chech if invoice can be replaced 2026-02-17 14:53:26 +01:00
Laurent Destailleur
769b1935e3 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-17 02:51:46 +01:00
Laurent Destailleur
da3edf38ed Debug 2026-02-17 02:51:35 +01:00
Laurent Destailleur
8f0d1d4e25 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 21:57:24 +01:00
Laurent Destailleur
8dbdf910f9 Missing label 2026-02-16 21:54:48 +01:00
Laurent Destailleur
d0c80f3228 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 21:47:14 +01:00
John BOTELLA
22391f32dd UI/UX : Transfert feedback css from experimental to core (#37226)
* Transfert feedback css from experimental to core

* fix php phan

* Fix phan

* Fix phan

* Fix phan
2026-02-16 21:37:57 +01:00
dependabot[bot]
16542692d5 Bump actions/upload-artifact from 4 to 6 (#37250)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-16 21:29:59 +01:00
Alexandre SPANGARO
fbc9934e62 QUAL French comment in English (#37225)
* Edit label of $fields

* QUAL French comment in English
2026-02-16 21:29:33 +01:00
Laurent Destailleur
125d97cf5d Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 21:23:48 +01:00
Delthair
a544af5d02 #37257 FIX for piesemicircle (#37258) 2026-02-16 20:29:44 +01:00
Jyhere
8fde66127c Add 'type' parameter to completeTabsHead hook (#37235) 2026-02-16 20:26:58 +01:00
demiton
45483a6fd9 FIX #37246 Modifying resteapayer calculation for credit note (#37247) 2026-02-16 20:26:20 +01:00
Laurent Destailleur
ecf01bacd7 Fix CI 2026-02-16 20:25:07 +01:00
Laurent Destailleur
d66612eb55 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 20:08:19 +01:00
Laurent Destailleur
cc9f0e5bcf Clean dump file 2026-02-16 20:08:06 +01:00
Charlène Benke
87fc31fa7c add company name on dropdown contract list (#37245) 2026-02-16 20:03:27 +01:00
Frédéric FRANCE
1a2813e13c Update supplier_proposal.lang (#37238) 2026-02-16 19:53:07 +01:00
Laurent Destailleur
904dbef1b2 Debug 2026-02-16 19:51:19 +01:00
Laurent Destailleur
db521258ea Dev control archive integrity 2026-02-16 15:57:00 +01:00
Laurent Destailleur
adc251a053 Responsive 2026-02-16 06:21:12 +01:00
Laurent Destailleur
a8675af65b Debug 2026-02-16 06:06:23 +01:00
Laurent Destailleur
66a9b7b7c3 Debug 2026-02-16 06:03:01 +01:00
Laurent Destailleur
7f06c6b326 Debug 2026-02-16 05:48:39 +01:00
Laurent Destailleur
f9b19c8336 Sync transifex 2026-02-16 05:45:10 +01:00
Laurent Destailleur
549fa27308 Translation 2026-02-16 05:41:19 +01:00
Laurent Destailleur
b31ff84b11 Doc 2026-02-16 05:26:30 +01:00
Laurent Destailleur
1dbf850bf1 Debug v24 2026-02-16 05:22:37 +01:00
Laurent Destailleur
bc9ce0c208 WIP LNE 2026-02-16 05:20:49 +01:00
Laurent Destailleur
4655321e82 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 04:04:45 +01:00
Laurent Destailleur
7328aeacf9 Work on LNE 2026-02-16 04:04:17 +01:00
Laurent Destailleur
1d8e24660c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 03:23:02 +01:00
Laurent Destailleur
252811d116 Debug v24 2026-02-16 03:22:52 +01:00
Laurent Destailleur
dad0061495 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 02:04:12 +01:00
Laurent Destailleur
75a54088fc Debug v23 2026-02-16 02:03:38 +01:00
Laurent Destailleur
160f061326 WIP 2026-02-16 02:03:30 +01:00
Laurent Destailleur
51bd610f0c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 01:21:44 +01:00
Laurent Destailleur
ebe7aacf54 Debug v24 2026-02-16 01:21:20 +01:00
Laurent Destailleur
03c3218a0c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-16 01:06:12 +01:00
Laurent Destailleur
59a51cc3ed Trans 2026-02-16 01:05:45 +01:00
Laurent Destailleur
15b9cab91c Debug v23 2026-02-16 00:57:14 +01:00
Laurent Destailleur
7e8e7a24c3 Debug v23 2026-02-16 00:50:53 +01:00
Laurent Destailleur
414ea91137 Trans 2026-02-16 00:08:14 +01:00
Laurent Destailleur
0a172228f9 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-15 23:13:52 +01:00
Laurent Destailleur
f36f7c62a5 Doc 2026-02-15 23:13:45 +01:00
Laurent Destailleur
b5260fc0cc Trans 2026-02-15 23:13:19 +01:00
Laurent Destailleur
0dda1f9a3e Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-15 22:58:58 +01:00
Laurent Destailleur
055add5503 Sync transifex 2026-02-15 22:19:43 +01:00
Laurent Destailleur
2ec81d9a18 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-15 22:09:49 +01:00
Laurent Destailleur
0152770cfe Fix translation of "various payment" (not english, not pro) with the
term used in english to mean "Opérations diverses (OD)"
2026-02-15 22:09:29 +01:00
Laurent Destailleur
310cad4455 Init demo for v24 2026-02-15 21:25:58 +01:00
Laurent Destailleur
454f381e11 Update initdemo 2026-02-15 19:54:36 +01:00
Laurent Destailleur
717d769009 Debug v23 2026-02-15 19:52:53 +01:00
Laurent Destailleur
77b557e954 Debug initdemo 2026-02-15 17:57:58 +01:00
Laurent Destailleur
dd08c92f2a Debug initdemo 2026-02-15 17:52:26 +01:00
Laurent Destailleur
6bd194b3fa Merge branch 'develop' of github.com:Dolibarr/dolibarr into develop 2026-02-15 17:40:54 +01:00
Laurent Destailleur
061ebaf0b9 Debug initdemo 2026-02-15 17:40:43 +01:00
Laurent Destailleur
9529bd2f3a Debug v23 2026-02-15 17:26:05 +01:00
Laurent Destailleur
f5d90ef9c0 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-15 16:57:58 +01:00
Laurent Destailleur
6a6a24ee3c More complete data on pings. 2026-02-15 16:57:48 +01:00
John BOTELLA
b313d7c0fd Fix in card css modal display (#36569)
* Fix display of cards in a modal

* fix php stan

* fix php stan

* Try a change to force CI

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-14 14:51:33 +01:00
Benjamin Falière
793bfde2a6 FIX phpdoc on createFixedAmountDiscount() (#37212)
* FIX phpdoc on createFixedAmountDiscount

* FIX phpdoc

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-13 15:10:58 +01:00
Laurent Destailleur
4d319bc2e1 Fix include 2026-02-13 02:01:19 +01:00
Laurent Destailleur
8978367505 Debug 2026-02-13 01:22:06 +01:00
Laurent Destailleur
b416748451 Compatibility with multicompany 2026-02-13 01:05:25 +01:00
Laurent Destailleur
961989d149 Fix CSP for ping 2026-02-13 00:20:53 +01:00
Laurent Destailleur
0463e210d8 FIX Bad header name 2026-02-13 00:18:01 +01:00
Laurent Destailleur
e9b064b7f0 WIP LNE 2026-02-12 22:55:44 +01:00
Laurent Destailleur
efd79201dc Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-12 21:45:49 +01:00
Laurent Destailleur
3bc7eb5c59 Debug v23 2026-02-12 21:45:22 +01:00
Laurent Destailleur
f022de3ff2 WIP LNE 2026-02-12 21:43:54 +01:00
MDW
c47998522a Qual: Ignore exit code from grep -v in phan flow (#37213)
# Qual: Ignore exit code from `grep -v` in phan flow

`grep -v` returns 1 when the resulting filtered list is empty and would stop the execution.
This is fixed with `|| true` to have a final exit code that is 0.
2026-02-12 19:53:03 +01:00
Laurent Destailleur
56618e0c59 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-12 19:51:13 +01:00
Laurent Destailleur
e1c499bbe7 Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION
2026-02-12 19:22:58 +01:00
Laurent Destailleur
0fdb91548f Setup easier to understand between INVOICE_CHECK_POSTERIOR_DATE and
FAC_FORCE_DATE_VALIDATION
2026-02-12 19:18:51 +01:00
Laurent Destailleur
c0911e55c8 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-12 18:57:51 +01:00
Laurent Destailleur
2f584530ce Doc 2026-02-12 18:04:16 +01:00
Eric - CAP-REL
7f38769d62 NEW Can request and force user to change its password (#37196)
* force user to change password : redirect to user card on login

* force user to change password : redirect to user card on login

* redirect to a dedicated page

* bad old idea : self change passwd on user card + edit mode and rights: it makes a hole on security check

* only apply on dolibarr auth mode context

* only on dolibarr auth mode context

* Fix force_pass_change SQL assignment logic

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-12 17:35:03 +01:00
hansemschnokeloch
6a9d4c5ca9 Error handling methods for commonobject (#37201) 2026-02-12 16:42:55 +01:00
MDW
f8e609b3b3 Qual: Update spelling (#37199)
* Qual: Update spelling for pre-select variants

# Qual: Update spelling for pre-select variants

In English, preselect is without the hyphen.  Update text and made some translations
related to preselect.

* Qual: Update composant to component and/or adequate translation.

# Qual: Update composant to component and/or adequate translation.

"Composant(s)" was mostly referenced in french file/class comments.
Updated

* Qual: Fix misspellings related to "criteria"

# Qual: Fix misspellings related to "criteria"

* Qual: Fix produt misspellings

# Qual: Fix produt misspellings

Change 'produt' to 'product'.

* Qual: Update French comments with "composants"

#Qual: Update French comments with "composants"

- Translating French comments to English (avoid codespell notice)

* Qual: Fixed typo 'bad practive' to 'bad practice'

# Qual: Fixed typo 'bad practive' to 'bad practice'

* Qual: Update phan.yml to exclude specific files from analysis

- Added file exclusion pattern to match phan configuration
- Added check for empty file list to avoid unnecessary phan execution

* Qual: Update file filtering in phan.yml workflow

The change updates the file filtering process in the phan.yml workflow to correctly redirect the output of the grep command to a temporary file.

* Qual: Ignore $systemfunction always exists

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-12 16:29:11 +01:00
intelliking
d5cc1d7754 fix: Remove HTML from accounting menu tooltips in eldy theme (#37203)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-12 16:28:05 +01:00
Joris Le Blansch
b1d60ec82b CLOSE #37190 ODT Templates for thirdparties - Birthday is returned in epoch format (#37198)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-12 16:27:30 +01:00
Laurent Destailleur
bada2c29df Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-12 15:19:27 +01:00
Laurent Destailleur
7b453994d8 Fix CI 2026-02-12 15:18:31 +01:00
MDW
8436004ce6 qual: Update PHPStan workflow to run on all files in integration (#37207)
The PHPStan workflow has been updated to run on all files in integration branches.
2026-02-12 15:14:03 +01:00
Laurent Destailleur
ed0b3a6f4d css 2026-02-12 01:40:00 +01:00
Laurent Destailleur
d092852768 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-12 00:39:28 +01:00
Laurent Destailleur
de948fad37 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-11 21:17:35 +01:00
Laurent Destailleur
b6f9a62a65 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-11 21:17:28 +01:00
hansemschnokeloch
09b69a178b Typo fix (#37195) 2026-02-11 21:15:41 +01:00
github-actions[bot]
e199ef7cae PHPStan > Update baseline (#37197)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
2026-02-11 21:15:15 +01:00
MDW
358a4883c6 Qual: Fix ambigious redirect error on Phan workflow (#37200)
# Qual: Fix ambigious redirect error on Phan workflow

Rewrote the shell command that is supposed to suppress a file contents
but is flagged by the environment.
2026-02-11 21:13:08 +01:00
Laurent Destailleur
ff63da5fac Fix phan 2026-02-11 15:08:13 +01:00
Laurent Destailleur
bd65974d56 Fix phan 2026-02-11 15:07:19 +01:00
MDW
411a18ec9f Qual: Partial phan run on PR's, complete run on integration branches (#37186)
* Qual: Partial phan run on PR's, complete on main

# Qual: Partial phan run on PR's, complete on main

The selection is based on the branch name.
To run a complete phan run in a PR, the branch name of the PR must include phan_full.
This can help to fix remaining phan issue before re-integrating to the develop branch.

* qual: Update workflow and pre-commit configurations

- Enable phan workflow by uncommenting the relevant lines
- Update actionlint version to v1.7.10
- Add manual stage to actionlint hook in pre-commit-config.yaml

* qual: Update Phan analysis conditions

The conditions for running Phan analysis have been updated to include an additional check for branches containing 'phan_full'.

* qual: Update Phan workflow

- Replace github.event.ref with github.ref_name
- Add FILE_CHANGE_LIST environment variable for better file handling
- Update file list creation and usage in the workflow

* qual: Update Phan workflow conditions

Fix the branch reference (head_ref in PR, ref_name otherwise)

* Add step for debug information

* Remove debug step

* Fix: Missing initialisations members/new.php

Following a suppression of assignments, the variables disabledphy and disabledmor were undefined.

* fix: Update budget selection dropdown arguments in member creation form

Correct the arguments in the member creation form.

* qual: Add cs2pr to phan workflow

- Add cs2pr to the tools list in the phan workflow
- Change the output mode of phan to checkstyle
- Add a step to add results to PR as Github notices
- Add a step to provide phan log as artifact

* qual: Update Phan workflow to use environment variable for file list

The change fixes the Phan workflow to use the environment variable `$FILE_CHANGED_LIST` to clear the file

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 12:58:04 +01:00
Laurent Destailleur
00136cf9e3 Another step for #37171 2026-02-11 03:27:42 +01:00
Laurent Destailleur
67c9853cd2 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-11 03:24:06 +01:00
Eric - CAP-REL
4bf8b3097f Develop force user change pass userclass (#37174)
* datamodel for user change password next time

* add force_pass_change in user object

* Initialize force_pass_change to 0

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 03:20:54 +01:00
Laurent Destailleur
ca854a434e Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-11 03:18:04 +01:00
Vincent Penel
8a8a7f4e95 NEW #25829 Automatically send the invoice generated from a template (#36967)
* Update DB

* ADD email template

* Ajout d'une clé de trad

* Ajout des traductions

* Suppression des traductions, sauf en_US

* Add flag auto send

* Modif form + cron auto send

* Suppression auto_send

* correction loopError

* ajout du selected au model de mail

* Prise en compte default model

* Fix pre-commit

* ménage

* precommit

* Correction Phan

* Correction Phan

* Correction, double cal du trigger

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 03:14:18 +01:00
Vincent Maury
3623872851 Fix #33521 VAT total false (#36990)
* - Fix #33521 VAT total false
- Fix some warnings
- Fix : delete $this->vat_rate

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* - Fix #33521 VAT total false
- Fix some warnings
- Fix  :delete $this->tva array (replaced by $this->tva_array)

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

* Update pdf_octopus.modules.php

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 03:07:58 +01:00
Laurent Destailleur
55c33edeec Check if upload_max_filesize is not empty 2026-02-11 02:16:24 +01:00
Laurent Destailleur
602bcc5361 CI 2026-02-11 02:03:45 +01:00
Laurent Destailleur
b699b3f9b9 Fix CI 2026-02-11 01:55:09 +01:00
minimexat
92562150ec QUAL Replace var_export() with json_encode() in dol_syslog() calls (#37138)
var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch, Graylog) as each line becomes a separate
log entry.

json_encode() produces single-line structured output that works correctly
with all log aggregation tools. This pattern is already used elsewhere
in Dolibarr (accountancy, install modules).

Files changed:
- core/class/commoninvoice.class.php (payment intent logging)
- core/class/commonobject.class.php (payment terms logging)
- core/modules/mailings/advthirdparties.modules.php (mailing targets)
- core/modules/oauth/google_oauthcallback.php (userinfo logging)
- core/modules/oauth/generic_oauthcallback.php (userinfo logging)
- public/payment/newpayment.php (GET/POST debug logging)
- public/payment/paymentok.php (payment tag logging)
- public/stripe/ipn.php (Stripe event data logging)
- paypal/lib/paypal.lib.php (PayPal response logging)
- api/index.php (API debug logging)
- stripe/class/stripe.class.php (payment/setup intent logging)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 01:44:21 +01:00
Frédéric FRANCE
9ac93e1e98 fix phpstan errors blocking action baseline (#37189)
* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* fix phpstan errors blocking action baseline

* refresh baseline
2026-02-11 00:52:15 +01:00
jeremydassaud
8a52b78f3d Issue 36923 Fix session title handling in survey creation (#37105)
* Issue 36923 Fix session title handling in survey creation

* Change input field to use id attribute for title

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-11 00:51:17 +01:00
Laurent Destailleur
89698730d0 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 20:37:09 +01:00
Laurent Destailleur
9f9ca3faf7 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 20:36:42 +01:00
hansemschnokeloch
019e17c040 Replace var_export by formatLogObject (continued) (#37188)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 16:54:51 +01:00
Laurent Destailleur
448bd21195 Fix phpstan 2026-02-10 16:09:20 +01:00
Laurent Destailleur
9d14dd25c4 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 16:00:31 +01:00
Laurent Destailleur
b6f714fe44 CI 2026-02-10 15:59:57 +01:00
Frédéric FRANCE
89d15ac306 fix phpdoc comment (#37184)
* fix phpdoc comment

* fix phpdoc comment

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:50:34 +01:00
Laurent Destailleur
52de478d6a Add template in migration 2026-02-10 15:49:23 +01:00
Laurent Destailleur
7601198799 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 15:46:40 +01:00
Laurent Destailleur
830fdbdaca Fix CI 2026-02-10 15:46:28 +01:00
hansemschnokeloch
23780ad765 Fix file path comment in supplier invoice module (#37133)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:31:51 +01:00
Vanyo
72a2510b46 Update default time handling in index.php (#37150)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-10 15:31:24 +01:00
Laurent Destailleur
1774bca857 Look and feel v24 2026-02-10 15:26:36 +01:00
Laurent Destailleur
8150d06abe Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 15:10:25 +01:00
Laurent Destailleur
7715579d71 ci 2026-02-10 15:10:11 +01:00
Laurent Destailleur
db7a02f33d ci 2026-02-10 15:09:12 +01:00
hansemschnokeloch
16cec77d5b Replace var_export with new function formatLogObject (#37178) 2026-02-10 15:01:34 +01:00
evarisk-kilyan
0341d1b961 #37166 [SQL] add: email template for ticket admin creation (#37182) 2026-02-10 15:00:50 +01:00
Laurent Destailleur
0cda79c2d9 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 14:42:14 +01:00
Laurent Destailleur
8f32564580 Avoid error if include fails 2026-02-10 13:56:04 +01:00
Laurent Destailleur
249feb265f CI 2026-02-10 01:32:04 +01:00
Laurent Destailleur
9b7fb5e28f CI 2026-02-10 01:26:08 +01:00
Laurent Destailleur
6d26cec36c CI 2026-02-10 00:50:53 +01:00
Laurent Destailleur
fb39d0973d Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-10 00:45:31 +01:00
Laurent Destailleur
36108255e3 Complete call to setStatus so we have a trigy as 4th parameter (help to
fix the #37129)
2026-02-10 00:44:46 +01:00
hansemschnokeloch
acb45dd61c Fix typo in file path (#37160)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 23:50:17 +01:00
MDW
2353b94eb7 Qual: Update phan baseline (#37172) 2026-02-09 23:49:44 +01:00
Eric - CAP-REL
1090494e90 datamodel for user change password next time (#37155) 2026-02-09 23:48:20 +01:00
Laurent Destailleur
fd0b21a5a6 Doc 2026-02-09 23:37:00 +01:00
hansemschnokeloch
f7db0d6cb7 Populate syslog with placeholder (#37163)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 23:18:36 +01:00
minimexat
b6980ebb8f FIX #37134 Use json_encode for IMAP search logging in EmailCollector (#37135)
var_export() produces multiline output that breaks log aggregators
(Loki, Splunk, Elasticsearch) as each line becomes a separate log entry.

Using json_encode() produces single-line structured output that works
correctly with all log aggregation tools.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 23:12:39 +01:00
Frédéric FRANCE
3429546116 fix ternary always true (#37161)
* fix ternary always true

* Update requests.php

* Update registration.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 22:48:16 +01:00
Laurent Destailleur
14180b3a40 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-09 22:44:17 +01:00
Laurent Destailleur
6251540dc9 Debug CI 2026-02-09 22:43:56 +01:00
Noé Cendrier
a7f13f59c1 FIX: missing include for blockedlog lib (#37165) 2026-02-09 20:37:19 +01:00
Laurent Destailleur
4075db8df5 CI 2026-02-09 20:31:21 +01:00
Laurent Destailleur
7221f0a8ef CI 2026-02-09 20:00:35 +01:00
Laurent Destailleur
fd9f4484fa Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-09 20:00:02 +01:00
Laurent Destailleur
34f1ec1f94 CI 2026-02-09 19:55:56 +01:00
Laurent Destailleur
853f09ccef CI 2026-02-09 19:50:05 +01:00
Laurent Destailleur
1c59868e79 CI 2026-02-09 19:43:22 +01:00
Laurent Destailleur
45abf7643c CI 2026-02-09 19:29:17 +01:00
Laurent Destailleur
cec0c2086c Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-09 19:22:44 +01:00
Laurent Destailleur
332fb8c3ef Factorize code 2026-02-09 19:11:37 +01:00
Laurent Destailleur
233a70b5e2 Debug setup navigation 2026-02-09 18:28:53 +01:00
Laurent Destailleur
4c4a3d23eb Debug registration process 2026-02-09 18:04:59 +01:00
Laurent Destailleur
414337e358 Fix navigation 2026-02-09 16:17:01 +01:00
Laurent Destailleur
a2822764e5 WIP LNE 2026-02-09 07:11:20 +01:00
Laurent Destailleur
426f13d495 CSS 2026-02-09 04:35:40 +01:00
Laurent Destailleur
22c824642a Add currency 2026-02-09 04:31:22 +01:00
Laurent Destailleur
616ba86bb8 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-09 04:25:03 +01:00
Laurent Destailleur
5321c29a00 Protect module 2026-02-09 04:24:41 +01:00
Yamil Esteban Garcia
eaa146293e Fix: IRPF tax not applied when creating invoice from project times (#37077)
* Remove 'supplier_invoice' from old path array

* Update module path in arrayforoldpath

Sorry Eldy, I was confused. You are absolutely right, it is already corrected.

* Replace localtax2 assignment with get_localtax function


Error when creating an invoice with personal income tax from project times. The rate does not apply

* Refactor localtax1 calculation using get_localtax

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-09 03:55:34 +01:00
Laurent Destailleur
9da14a6eb2 Fix CI 2026-02-09 03:54:32 +01:00
Laurent Destailleur
71e4553504 CI 2026-02-09 03:23:06 +01:00
Laurent Destailleur
a84271f339 More legal info 2026-02-09 03:21:18 +01:00
Laurent Destailleur
776fed3834 Fix phpunit 2026-02-09 03:18:00 +01:00
Laurent Destailleur
ed03a6f1f8 CSS 2026-02-09 01:06:34 +01:00
Laurent Destailleur
f921204bd4 Clean code. File not used. 2026-02-09 00:05:00 +01:00
Laurent Destailleur
8eda44e96a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 23:59:27 +01:00
Laurent Destailleur
822bc7ffef CI 2026-02-08 23:59:18 +01:00
Laurent Destailleur
a25d4e0e22 CI 2026-02-08 23:42:45 +01:00
Laurent Destailleur
8eb76e4da8 CI 2026-02-08 23:25:11 +01:00
Laurent Destailleur
900b28b97a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 23:21:38 +01:00
Laurent Destailleur
9ab084cee2 CI 2026-02-08 23:21:27 +01:00
Lucas Marcouiller
0e27ee5643 New LNE Collect of buisness informations (#37084)
* Working LNE ping

* remove GPDA

* Add of other informations

* remove testing var

* fix Ci

* fix Ci

* fix ci

* fix CI

* Fix Ci

* fix Ci

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-02-08 23:14:07 +01:00
Laurent Destailleur
7e1fb745b5 NEW Use the js lib into htdocs/public/includes instead of htdocs/includes 2026-02-08 23:11:40 +01:00
Laurent Destailleur
1025c6798a Clean code 2026-02-08 22:38:26 +01:00
Jarvis
9d52c129e4 Update modProduct.class.php (#37087)
Fix: allow import of sell_or_eat_by_mandatory for products

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 22:26:21 +01:00
adamhocini
138c571c75 TakePOS hook “AddAction” jamais exécuté (#35961) (#37113)
@defrance 
Adam Hocini
2026-02-08 22:25:08 +01:00
Laurent Destailleur
67a598d0be Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 21:58:41 +01:00
Laurent Destailleur
1c435e2a67 Clean sql 2026-02-08 21:17:56 +01:00
Laurent Destailleur
102b65364c Avoid ( in sql 2026-02-08 20:57:11 +01:00
Laurent Destailleur
fe3314d07a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 20:40:42 +01:00
minimexat
b74c6d3ee0 FIX PHP 8.1 undefined array key warnings in ProductCombination multiprices loop (#37142)
When PRODUIT_MULTIPRICES is enabled and a product variant's parent has
multiprices configured, the updateChildPrice() method iterates through
all price levels up to PRODUIT_MULTIPRICES_LIMIT. For price levels that
don't have prices defined, accessing $parent->multiprices[$i] and
related arrays directly causes 'undefined array key' warnings on
PHP 8.1+.

Changes:
- Add isset() check before comparing $parent->multiprices[$i]
- Use isset() ternary for $parent->multiprices_min[$i] (default: 0)
- Use !empty() for $parent->prices_by_qty_list[$i] check
- Use isset() ternary for $parent->multiprices_ttc[$i] (default: 0)
- Use isset() ternary for second $parent->multiprices[$i] (default: 0)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 20:02:02 +01:00
Eric - CAP-REL
b560a05e68 add fk_parent on group group for permission inheritance (#37152) 2026-02-08 20:01:25 +01:00
Laurent Destailleur
938f8b2d46 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 19:52:49 +01:00
Laurent Destailleur
8c5fe25137 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 19:04:03 +01:00
Laurent Destailleur
48254ef6d0 Comment 2026-02-08 17:51:20 +01:00
Laurent Destailleur
f4dc5dfee9 Fix CI 2026-02-08 17:51:08 +01:00
David Beniamine
de71085394 Ensure that if $object->members is not loaded either we do not send m… (#37126)
* Ensure that if $object->members is not loaded either we do not send members to LDAP or we explicitly loads them before according to LDAP configuration

* Fix typo
2026-02-08 15:39:27 +01:00
MDW
1166dd305b Qual: Update comments from French to English (#37097)
* Qual: Update comments from French to English

# Qual: Update comments from French to English

* Qual: Fix missing initialisations

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 15:29:53 +01:00
Laurent Destailleur
2b1d0e1012 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 15:28:31 +01:00
Laurent Destailleur
8a8ba06698 Fix CI 2026-02-08 15:28:19 +01:00
minimexat
f70eaae6f5 FIX #34342 PHP 8.1 undefined array key warnings in Product::getSellPrice() multiprices (#37144)
When using multiprices (PRODUIT_MULTIPRICES or
PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES), getSellPrice() accesses
$this->multiprices[$level], multiprices_ttc, multiprices_min,
multiprices_min_ttc, and multiprices_base_type arrays using the
buyer's price_level as key without checking if the key exists.

This causes 'undefined array key' warnings on PHP 8.1+ when a
third party has a price_level set but the product doesn't have
prices defined for that specific level.

Similarly, prices_by_qty array accesses for PRODUIT_CUSTOMER_PRICES_BY_QTY
and PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES modes could trigger
warnings when the array index doesn't exist.

Changes:
- Add isset() checks with safe defaults for all multiprices array
  accesses (0 for prices, 'HT' for price_base_type)
- Replace direct prices_by_qty access with !empty() checks

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 15:08:58 +01:00
Laurent Destailleur
28a7c69f11 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 14:56:01 +01:00
Laurent Destailleur
d15f196249 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 14:51:29 +01:00
Laurent Destailleur
f6ec5b44fe CI 2026-02-08 14:51:11 +01:00
minimexat
7496ec701c FIX #36923 Fix undefined array key warnings in opensurvey create_survey.php (#37140)
The session variable initialization logic was inverted: it set variables
to null only when they already existed, instead of initializing them
when they were missing. This caused 'undefined array key' warnings on
PHP 8.1+ when accessing the poll creation form for the first time.

Changes:
- Inverted isset() condition to !isset() to properly initialize missing
  session variables
- Initialize to empty string instead of null
- Added missing session variables (allow_comments, allow_spy, champdatefin)
  to the initialization array
- Added dol_escape_htmltag() for title output (XSS hardening)

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 14:46:02 +01:00
Vanyo
1cd73239fc Initialize arrayforbutaction before hook (#37149) 2026-02-08 14:44:15 +01:00
Laurent Destailleur
aa36309755 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 14:40:13 +01:00
Laurent Destailleur
c939f56b56 NEW Add method formatLogObject to allow logs in 1 line #37135 2026-02-08 14:39:46 +01:00
Mathieu G.
3f412cf745 fix avoids undefined array key (#37103) 2026-02-08 14:28:09 +01:00
Laurent Destailleur
ce50e32a71 Fix regression 2026-02-08 14:25:27 +01:00
Laurent Destailleur
5e960ae089 FIX Show total on multicurrency only if currency are the same on all
lines
2026-02-08 13:57:11 +01:00
Laurent Destailleur
04c72eea0f Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-08 13:15:16 +01:00
Laurent Destailleur
eeae12ed63 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 13:05:32 +01:00
Laurent Destailleur
9fa2fd0b92 Debug v23 2026-02-08 13:04:23 +01:00
Laurent Destailleur
5c6bc657f4 CI 2026-02-08 12:58:22 +01:00
minimexat
02d0b6524c FIX Add missing isset() check for $_GET['file'] in viewimage.php (#37141)
On line 65, $_GET['file'] is accessed without isset() check inside
the modulepart=='mycompany' condition. This causes an 'undefined array
key' warning on PHP 8.1+ when modulepart is 'mycompany' but no file
parameter is provided.

Note: GETPOST() is intentionally not used here as it is not available
before main.inc.php is loaded (see existing code comment).

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
2026-02-08 03:06:36 +01:00
minimexat
61ece3d5c5 FIX Replace direct $_POST access with GETPOST() in origin/originid recovery paths (#37143)
When a create action fails and rolls back, several list/card pages
restore origin parameters by assigning $_POST values directly to
$_GET. This causes 'undefined array key' warnings on PHP 8.1+ if
the POST data is missing or malformed.

Replace raw $_POST['origin'] with GETPOST('origin', 'alpha') and
raw $_POST['originid'] with GETPOSTINT('originid') which safely
handle missing parameters.

Files fixed:
- htdocs/expedition/list.php
- htdocs/fourn/commande/list.php
- htdocs/commande/list.php
- htdocs/compta/facture/card.php
- htdocs/reception/list.php

These files had TODO-style comments ('Keep this ?', 'Keep GET and
POST here ?') indicating the pattern was already questionable.

Co-authored-by: f-hoedl <hoefla14@htl-kaindorf.ac.at>
2026-02-08 03:05:47 +01:00
Laurent Destailleur
9369f4aea3 Fix CI 2026-02-08 00:19:03 +01:00
Laurent Destailleur
192e181d8a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-08 00:11:09 +01:00
Laurent Destailleur
b82f488c54 Fix CI 2026-02-08 00:11:01 +01:00
DarmonNoah
7cd3abb9f8 Fixed Bug : email sending test #36741 (#37107)
Fixed Bug : email sending test #36741
@defrance 
-->
Issue fixed
The problem was caused by initializing $result = 0 in core/actions_sendmails.inc.php.
When sending a test email from Setup → Emails, there is no $object to fetch. As a result, $result remained 0 and the code incorrectly triggered ErrorFailedToReadObject.

The fix consists in explicitly setting $result = 1 when no $object is provided (test email / generic email context). This correctly treats the absence of an object as a valid case and restores the ability to send test emails, while keeping $result properly initialized.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-08 00:00:12 +01:00
adamhocini
ebce799bdb Correct linked_objects assignment for 'propal' #Wrong sourcetype 'commande' instead of 'propal' when creating recurring invoice template from invoice linked to proposal #37099 @defrance (#37112)
* Correct linked_objects assignment for 'propal'

@defrance Adam Hocini

* Refactor linked objects assignment for proposals

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-07 23:58:14 +01:00
Laurent Destailleur
f20eb01d0e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-07 23:57:50 +01:00
Laurent Destailleur
fd6ecb3901 Fix CI 2026-02-07 23:57:41 +01:00
Laurent Destailleur
43034bfc30 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-07 23:56:27 +01:00
Laurent Destailleur
ee0df74f83 Fix CI 2026-02-07 23:54:21 +01:00
Laurent Destailleur
e364607856 Fix CI 2026-02-07 23:53:07 +01:00
AnthoXic
5078e42330 Update card.php (#37108)
@defrance https://github.com/Dolibarr/dolibarr/issues/36767
2026-02-07 23:41:13 +01:00
Charlène Benke
712b4ce5c4 Increase editor height for note input fields (#37128) 2026-02-07 23:23:56 +01:00
Laurent Destailleur
a781d91469 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-07 22:04:13 +01:00
Laurent Destailleur
e5b2243565 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-07 17:13:24 +01:00
Laurent Destailleur
1ec65e0589 Debug extrafields chckbxlist v23 2026-02-07 14:55:51 +01:00
Laurent Destailleur
d03e1bd940 Debug v23 2026-02-07 12:05:53 +01:00
Laurent Destailleur
a1bc833c3f Fix link 2026-02-07 11:54:54 +01:00
Laurent Destailleur
5b0b22fe28 NEW Add direct debit to close on home thumbs 2026-02-07 11:24:26 +01:00
Laurent Destailleur
0ee93311e9 Fix status code 2026-02-06 22:14:38 +01:00
Laurent Destailleur
8ba58b33ae Fix list of status 2026-02-06 22:11:17 +01:00
Laurent Destailleur
2f023619e9 Fix link 2026-02-06 21:57:46 +01:00
Laurent Destailleur
eaab8a8242 Fix link 2026-02-06 21:53:20 +01:00
Laurent Destailleur
fbd92432b1 Debug v24 2026-02-06 21:50:44 +01:00
Laurent Destailleur
bbba60fa3f Link are clicable on page 2026-02-06 21:47:11 +01:00
Laurent Destailleur
e907abd201 NEW Add status canceled on direct debit payment 2026-02-06 21:27:31 +01:00
Laurent Destailleur
5bde9c7b56 Add tab on sepa direct debit 2026-02-06 20:22:21 +01:00
Laurent Destailleur
38690cd872 Clean code 2026-02-06 19:41:16 +01:00
Laurent Destailleur
92e05a521d Debug filter on status 2026-02-06 19:04:15 +01:00
Laurent Destailleur
d909b6cb75 NEW Filter on status of direct debit 2026-02-06 18:58:34 +01:00
Laurent Destailleur
53045c7377 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-06 18:08:06 +01:00
Laurent Destailleur
4721d852bf Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-06 18:07:54 +01:00
Jarvis
954233c67d Fix extrafields visibility formulas using $objectoffield without computed fields (#37116)
Initialize $objectoffield before evaluating extrafield visibility/perms so formulas work even when no computed field exists.
Affects create/edit/view visibility logic for extrafields.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-06 12:57:19 +01:00
Laurent Destailleur
f4b7ce7f20 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-06 12:46:04 +01:00
Laurent Destailleur
5728e44c3d NEW Introduce THIRDPARTY_LIMIT_SIZE for a limit on thirdpaty in select
list
2026-02-06 12:45:40 +01:00
Christophe Battarel
7c20573ef2 FIX : permission on pmp (#37119)
* fix pmp auth on stock at date screen

* fix pmp auth on warehouse list

* fix pmp auth on warehouse card

* FIX: bad argument for print_liste_field_titre

---------

Co-authored-by: Christophe Battarel <christophe@altairis.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Noé Cendrier <81741011+altairis-noe@users.noreply.github.com>
Co-authored-by: Noé Cendrier <noe.cendrier@altairis.fr>
2026-02-06 12:13:21 +01:00
Laurent Destailleur
22e7100281 Trans 2026-02-06 03:17:44 +01:00
Laurent Destailleur
5e206952f4 FIX Error on large product database 2026-02-06 03:10:25 +01:00
Laurent Destailleur
920627e75f Fix var 2026-02-06 02:41:02 +01:00
Laurent Destailleur
2dada142ba Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-06 02:38:10 +01:00
Florian Hödl
26aabf9e2d fix(emailcollector): prevent PHPIMAP body carryover between emails (#37121)
Reset global variables $htmlmsg, $plainmsg, and $attachments before
processing each email in PHPIMAP mode to prevent email body content
from previous email carrying over into the next one.

This issue only affected Microsoft OAuth (PHPIMAP) mode. When an email
had no plain-text body but the previous email did, the previous email's
plain-text would incorrectly be used for the current email.

The $charset variable is intentionally not reset as PHPIMAP handles
charset internally, unlike native IMAP mode.

Also standardized array syntax to use array() consistently per Dolibarr
coding conventions.

Co-authored-by: Florian Hödl <florian@hoedl.co>
2026-02-06 02:37:37 +01:00
Laurent Destailleur
9d68bebac4 NEW Can set position of search object in combo search 2026-02-06 01:29:53 +01:00
Laurent Destailleur
4112213431 Trans 2026-02-06 01:08:29 +01:00
Laurent Destailleur
7bc2523f57 Fix phan 2026-02-05 19:31:41 +01:00
Laurent Destailleur
7773c2504f Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-05 13:55:24 +01:00
Laurent Destailleur
b74e50d7e6 NEW Add method calculateVATNumberFromProperties() 2026-02-05 13:54:13 +01:00
Laurent Destailleur
c9b270b035 Code comment 2026-02-05 13:30:59 +01:00
William Mead
efb61ca449 NEW product barcode label print options (#36656)
* Added product reference and product label options to barcode label. Updated EN localization. Updated contributor details.

* Added reference and label input placeholder

* Updated logic and localizations

* Updated styling

* Updated localization

* Cleaned code
2026-02-05 12:44:00 +01:00
Anthony Berton
86a913d5b1 FIX - Standardization with other Dolibarr objects (#36725)
* FIX - Standardization with other Dolibarr objects

* Solve CI error

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-05 12:42:15 +01:00
William Mead
feca86b812 FIX supplier order delivery date from order (#36860)
* Fixed delivery date from order

* Updated comment

* Fixed delivery date from order

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-05 12:35:53 +01:00
Laurent Destailleur
16fe32f908 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-05 03:57:09 +01:00
Laurent Destailleur
a798501af3 Fix CI 2026-02-05 03:56:54 +01:00
atm-GregM
77a033999d Add new multiselect OF status search on list (#37069)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-05 03:28:37 +01:00
Anthony Berton
7b33e1c752 UIUX - Look and feel for knowledge (#37096)
* FIX

* FIX

* NEW - Look and feel for knowledge

---------

Co-authored-by: Anthony Berton <anthony.berton@bb2a.fr>
2026-02-05 01:08:00 +01:00
Frédéric FRANCE
ccdcee471b fix french doc (#37095) 2026-02-05 01:06:46 +01:00
Laurent Destailleur
e79416c801 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-04 21:33:26 +01:00
Laurent Destailleur
15658c56d5 CI 2026-02-04 21:33:07 +01:00
Laurent Destailleur
c681071c65 Fix phan 2026-02-04 21:30:16 +01:00
Benjamin Falière
5ed012c6e5 NEW(API): create fixed amount discount (#37091)
* NEW(API): create fixed amount discount

* FIX CI

* FIX CI

---------

Co-authored-by: Benjamin Falière <benjamin.faliere@altairis.fr>
2026-02-04 21:23:46 +01:00
ThomasNgr-OpenDSI
d75499d076 NEW : hide remise_except unit price on invoice lines (#37066)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-04 21:19:06 +01:00
Laurent Destailleur
2905b6096e Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-04 19:49:49 +01:00
Laurent Destailleur
5453a7a79b Close #36975 2026-02-04 18:05:10 +01:00
Charlène Benke
af7f01750b family assignment logic on user perms of external modules (#36456)
* family assignment logic on user perms of external modules

Updated family assignment logic to default to 'other' if family does not exist in $familyinfo.

* Update copyright year for Charlene Benke
2026-02-04 17:19:23 +01:00
Laurent Destailleur
7b96c31789 Fix CI 2026-02-04 17:13:38 +01:00
Laurent Destailleur
5b20b70b66 Doc 2026-02-04 16:56:20 +01:00
Laurent Destailleur
3399db3471 Fix CI 2026-02-04 16:33:50 +01:00
Laurent Destailleur
0ca6f7366b Clean code 2026-02-04 16:21:51 +01:00
AWeerWolf
09a840b6c3 #36843 Update card-rec.php (#37062)
The item desc is already added into the line when selecting the Item. No Need to concat it again when clicking the "add" button.
2026-02-04 16:21:11 +01:00
Laurent Destailleur
f3aa82e4ba Restrict to modiied files 2026-02-04 16:16:51 +01:00
Laurent Destailleur
d6bff9f364 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-04 16:16:10 +01:00
Laurent Destailleur
e3b3a8bbec Fix CI 2026-02-04 16:15:26 +01:00
LePat
8bca07597d fix: add missing geturl lib (#37088) 2026-02-04 16:11:55 +01:00
Laurent Destailleur
5fa75e981b CLOSE #37085 - Popup notif is just under the menu bar 2026-02-04 16:00:16 +01:00
Laurent Destailleur
e22ba4a3d2 Fix CI 2026-02-04 15:20:36 +01:00
Lenin Rivas
624407afcc NEW Show total multicurrency on payment (#37070)
* Total multicurrency

* Total multicurrency paiment

* total result multicurrency

* show total multicurrency
2026-02-04 15:19:48 +01:00
Vanyo
34f7bf1e68 Change translation function to transnoentities (#37065)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-04 15:08:56 +01:00
Laurent Destailleur
96a9d1f4e5 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-04 15:08:02 +01:00
Laurent Destailleur
89c40d9be6 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-04 15:05:56 +01:00
Laurent Destailleur
1a26f9a42e Trans 2026-02-04 15:05:35 +01:00
Frédéric FRANCE
80f9839253 translate french doc to english (#37064)
* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix

* fix

* fix

* fix
2026-02-04 14:49:13 +01:00
Laurent Destailleur
82d4bb9df6 fix: dev/examples/zapier/package.json to reduce vulnerabilities (#37071)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-LODASH-15053838

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2026-02-04 14:48:57 +01:00
Braito
d45ed9d78e EmailCollector: exclude sender emails/domains (#37075)
# Conflicts:
#	htdocs/langs/en_US/admin.lang

Co-authored-by: braito4 <braito4@users.noreply.github.com>
2026-02-04 14:46:14 +01:00
Charlène Benke
00b04e9691 Adjust signature appearance position in PDF generation (#37076) 2026-02-04 14:45:07 +01:00
Laurent Destailleur
1cfb3dfaa3 Fix new path of dolreceiptprinter.class.php 2026-02-04 14:36:45 +01:00
Laurent Destailleur
85687d5d88 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-04 14:27:02 +01:00
Laurent Destailleur
8b920938de Clean code for Takepos 2026-02-04 14:21:47 +01:00
LePat
70d522a6d4 FIX: TakePOS, webapp-hardware-bridge and TakePOS-Connector for modern weighing scales (#37078)
* feat: CustomerDisplay through Webapp-Hardware-Bridge

* feat: WeighingScale through Webapp-Hardware-Bridge

* feat: WeighingScale through Webapp-Hardware-Bridge

* fix: looks like a typo

* feat: for small screens

* fix: attribut contenant le prix du produit ajouté

* feat: ajout d'un callback de gestion d'erreur
2026-02-04 14:20:59 +01:00
Charlène Benke
11241cd8da bad link on sql in fichinter list (#37081) 2026-02-04 14:19:46 +01:00
Laurent Destailleur
4b3a8ff24f Debug v23 2026-02-03 19:05:22 +01:00
Laurent Destailleur
fdce9453bc Make array of dispute status a shared constant 2026-02-03 18:40:36 +01:00
Laurent Destailleur
ca7e4346f0 More complete message 2026-02-03 18:16:05 +01:00
Laurent Destailleur
3a6bd97fc8 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-03 14:08:20 +01:00
Laurent Destailleur
9d8314a65a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-03 11:23:24 +01:00
Laurent Destailleur
2faa3a0ae2 Link and filter on ountry for holiday types 2026-02-03 11:22:23 +01:00
Laurent Destailleur
62384bedb4 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-02 20:56:47 +01:00
Laurent Destailleur
fd41237049 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-02 20:03:05 +01:00
Laurent Destailleur
faa60854f9 Fix situation invoice 2026-02-02 20:02:28 +01:00
Charlène Benke
0a247c57ca load tables in init for create categorie table associated (#37059) 2026-02-02 19:24:31 +01:00
Frédéric FRANCE
95da49edf3 fix french doc (#37056)
* fix french doc

* fix french doc

* fix french doc

* doc translation

* doc translation

* doc translation

* doc translation

* doc translation
2026-02-02 19:22:04 +01:00
hansemschnokeloch
3ff9722903 Add optionnal img to openid login (#37060) 2026-02-02 19:09:57 +01:00
Laurent Destailleur
b5d5087550 Fix sql syntax error 2026-02-02 16:18:43 +01:00
Laurent Destailleur
84592e1f5d Fix CSS 2026-02-02 16:11:46 +01:00
Laurent Destailleur
f8d8abd70b Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-02 15:59:37 +01:00
Frédéric FRANCE
d02b05f1a7 remove french doc and fix travis migration missing (#37053)
* fix french doc

* fix french doc

* fix french doc

* fix french doc

* Clean up comments in card.php

Removed unnecessary comments from card.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-02 00:43:28 +01:00
Pierre Ardoin
73273a48da Fix Signature position (#37048)
Move up the position of the signature to fix its explosion on 3 pages
2026-02-02 00:38:06 +01:00
ThomasNgr-OpenDSI
079f0565d7 NEW : Manage discount for all lines for supplier elements. (#36954)
* NEW : Manage remise for all lines for supplier elements.

* Cast remise_percent to float in updateline call

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-02 00:23:40 +01:00
Laurent Destailleur
5b8eeba33d Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-01 19:22:03 +01:00
Laurent Destailleur
e2206a5849 FIX #36892 2026-02-01 19:20:52 +01:00
Frédéric FRANCE
d3dbfd8c6e Add thumbnails for avif (#37045)
* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* vignette for avif

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 19:07:15 +01:00
Laurent Destailleur
1395b5f66c CI 2026-02-01 19:04:53 +01:00
Lenin Rivas
429aff6991 FIX divisa rate indirect to direct because Dolibarr use indirect for default (#37046)
* FIX rate_indirect to rate_direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect	: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* FIX divisa rate indirect to direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* FIX divisa rate indirect to direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* FIX divisa rate indirect to direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* FIX divisa rate indirect to direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* Divisa rate direct

Direct	: 	1 Divisa Currency = X Currency Main.
Indirect: 	1 Currency Main = X Divisa Currency.
Then for Dolibarr use is Indirect for default

* Add col rate_direct because Dolibarr use for.default rate indirect

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 18:13:09 +01:00
MDW
4e8b6dc21d Qual: Translate french 'avec' comments to English (#37049)
# Qual: Translate french 'avec' comments to English
2026-02-01 18:09:39 +01:00
MDW
c5582f5085 Qual: Translate French 'valeur' in comments to English (#37051) 2026-02-01 18:05:15 +01:00
Alexandre SPANGARO
a84b9cf89d Qual: Translate French comments to English (#37052) 2026-02-01 18:04:58 +01:00
Laurent Destailleur
d02dfe0966 Fix ci 2026-02-01 02:56:16 +01:00
Laurent Destailleur
3ac710d260 Fix CI 2026-02-01 02:48:21 +01:00
Laurent Destailleur
20186dd991 Fix CI 2026-02-01 02:30:28 +01:00
Jyhere
9bb2ae7772 FIX: Add htmlname and selectedrate to parameters array for hook (#36998)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 02:08:03 +01:00
Vincent Maury
892f49ffb2 Fix #35394 Display public note on first page (#36993)
* Display public note (an incoterms and sales rep signat) only on real first page

* Display public note (an incoterms and sales rep signat) only on real first page

---------

Co-authored-by: vmaury <vmaury@vmaury-Lafite-Pro-16-AMD>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 02:05:08 +01:00
Thatoo
296372cf5f Minimum amount and subscription's amount formula description (#37006)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-01 01:19:29 +01:00
Laurent Destailleur
1e5a12708d CI 2026-02-01 00:44:24 +01:00
Laurent Destailleur
09ded05029 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-01 00:40:38 +01:00
Laurent Destailleur
47089ec3e1 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-01 00:14:21 +01:00
Laurent Destailleur
93c1013eff Fix CI 2026-02-01 00:13:37 +01:00
Frédéric FRANCE
d74cbcb26d fix french doc (#37047)
* fix french doc

* Update index.php

* Update index.php
2026-02-01 00:00:49 +01:00
Frédéric FRANCE
2e21b1d596 fix french doc (#37037)
* fix french doc

* Update dispatch.php

* Update dispatch.php

* Update graph.php
2026-01-31 20:29:59 +01:00
Charlène Benke
d4f68f8986 warning error if no societe->id defined (#37039) 2026-01-31 20:29:22 +01:00
Frédéric FRANCE
84774abc2c fix french doc (#37040) 2026-01-31 20:28:43 +01:00
MDW
e444abc3d1 Qual: Translate French comments to English ("niveau") (#37041)
Translate French comments to English (comments with "niveau")
2026-01-31 20:28:26 +01:00
Alexandre SPANGARO
1ac1cbf8de Qual: Translate French comments to English (#37044)
* Qual: Translate French comments to English

* Qual: Translate French comments to English
2026-01-31 20:28:09 +01:00
Frédéric FRANCE
73ec501b20 fix french doc (#36897)
* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix

* fix

* fix

* fix

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* fix french doc

* Update html.form.class.php

* Update html.form.class.php

* Update index.php

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Update modules_facture.php

* Update phpstan.neon.dist

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-30 14:22:56 +01:00
Laurent Destailleur
f64c0136d7 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-30 13:33:44 +01:00
Laurent Destailleur
66746b7e18 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-30 13:26:28 +01:00
Laurent Destailleur
4ec7c5c3f6 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-30 13:26:10 +01:00
Frédéric FRANCE
003c22e772 fix CI (#37033) 2026-01-30 13:08:48 +01:00
Laurent Destailleur
5ae622fb28 Clean code 2026-01-30 05:40:34 +01:00
Laurent Destailleur
611188e32c Log 2026-01-30 05:40:27 +01:00
Laurent Destailleur
08b55f54c5 Fix IPN 2026-01-30 05:31:16 +01:00
Laurent Destailleur
a02afa7641 Fix IPN payment 2026-01-30 05:11:17 +01:00
Laurent Destailleur
2f76d0bc5a More Log 2026-01-30 04:46:32 +01:00
Laurent Destailleur
51c6165983 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-30 04:12:15 +01:00
Laurent Destailleur
1f77162fef More log 2026-01-30 04:11:42 +01:00
Laurent Destailleur
764f23c1b8 More log 2026-01-30 03:57:07 +01:00
Laurent Destailleur
a8cbcd7150 More log 2026-01-30 03:54:23 +01:00
Laurent Destailleur
dd7906a1d9 FIX Division by zero 2026-01-30 03:20:08 +01:00
Laurent Destailleur
fd71ba3fec Debug v24 2026-01-30 02:56:17 +01:00
Laurent Destailleur
adec349442 Fix when there is more than 99 direct debit in same month 2026-01-30 02:54:03 +01:00
Laurent Destailleur
842b09b2f5 FIX When bank direct debit SEPA ref is > 99 2026-01-30 02:52:34 +01:00
Laurent Destailleur
8882c5e79a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-30 02:10:43 +01:00
Laurent Destailleur
c9dee9bcd1 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-30 02:10:31 +01:00
Laurent Destailleur
965fa8da72 Doc comment 2026-01-30 02:10:21 +01:00
Laurent Destailleur
22ef8998fb Doc 2026-01-30 00:56:32 +01:00
Frédéric FRANCE
b5d1f8d569 fix phan (#37030)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-30 00:52:36 +01:00
Frédéric FRANCE
001755285b fix phan (#37029)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-30 00:47:45 +01:00
MDW
3fef69e9bf Qual: Update french comments with 'nombre' (#37032)
Update french comments with 'nombre' in their phrasing

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-30 00:37:23 +01:00
Laurent Destailleur
ab0395e8c9 Fix LDAP 2026-01-29 23:52:43 +01:00
Laurent Destailleur
bb5a37e0ef Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 23:46:17 +01:00
Laurent Destailleur
63e4f2305f Clean code 2026-01-29 23:33:04 +01:00
Laurent Destailleur
8befaf1ae6 Clean code 2026-01-29 23:30:39 +01:00
Laurent Destailleur
736c269790 Fix phan 2026-01-29 23:19:36 +01:00
Laurent Destailleur
9140024505 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 23:17:02 +01:00
Laurent Destailleur
01d715053a try to fix phan 2026-01-29 23:16:51 +01:00
Alexandre SPANGARO
2af5a71c91 NEW Invoice - List - use select2 multiselect for status (#36834)
* NEW Invoice - List - use select2 multiselect for status

* Optimize

* CI

* CI

* Review

* Duplicate line and last problem

* CI

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-29 23:01:26 +01:00
Charlène Benke
a1662ed122 Add api document management for holiday (#36915)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-29 22:55:38 +01:00
Laurent Destailleur
be86aa3c37 CI 2026-01-29 19:21:34 +01:00
Laurent Destailleur
16bdaa5b50 Test without file list 2026-01-29 19:09:57 +01:00
Laurent Destailleur
f30acef13a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 16:48:26 +01:00
Laurent Destailleur
bb833f7641 CI 2026-01-29 15:33:02 +01:00
Laurent Destailleur
225eda7d18 CI 2026-01-29 15:30:30 +01:00
Laurent Destailleur
07a2920ef6 css 2026-01-29 15:08:54 +01:00
Zakaria Boushaba
252ac1e008 NEW: Display thirdparty name with ref in supplier orders linked objects (#36952)
Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa>
2026-01-29 14:55:44 +01:00
Thatoo
eed9d743c1 [database] Minimum amount and subscription's amount formula description (#37021)
* Remove jstz.min.js from JavaScript array (#37017)

jstz.min.js was deleted in 5599ac733b

* prevent ST_AsWKT() (#37013)

* prevent ST_AsWKT()

* Update commonobject.class.php

---------

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

* css

* Update llx_adherent_type.sql

add minimumamount and amountformuladescription rows

* Update 22.0.0-23.0.0.sql

add minimumamount and amountformuladescription column

---------

Co-authored-by: hansemschnokeloch <hansemschnokeloch@users.noreply.github.com>
Co-authored-by: atm-jonathan <146709163+atm-jonathan@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-29 14:46:57 +01:00
Charlène Benke
d9910be2ea NEW allow to disable freezone product on takepos (#37004)
* allow to disable freezone product on takepos

* Conditionally add FreeZone product to menus

* Add NoFreeZoneProduct language entry

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-29 13:33:16 +01:00
Laurent Destailleur
8abe26fde8 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 13:32:01 +01:00
Laurent Destailleur
2b1a2e1357 Debug v24 2026-01-29 13:18:03 +01:00
Laurent Destailleur
a746d9b122 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 13:14:33 +01:00
Laurent Destailleur
c1456e9db9 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 13:14:14 +01:00
sonikf
48791de235 MCP server sql part (#37025)
* Create llx_ai_request_log.sql

* Create llx_ai_request_log.key.sql

* Update 23.0.0-24.0.0.sql

* Update llx_ai_request_log.sql

* Update 23.0.0-24.0.0.sql

* Remove foreign key constraint from llx_ai_request_log

Removed foreign key constraint for fk_user in llx_ai_request_log.

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-29 13:13:52 +01:00
Laurent Destailleur
ac8c35fa9d Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 12:32:03 +01:00
Laurent Destailleur
cde20fd1b9 CI 2026-01-29 12:31:55 +01:00
hansemschnokeloch
0e86d0c33a Populate openid data from wellknow url (#37023)
* Delete inexistant file

File jstz.min.js was deleted in
5599ac733b

* Populate openid parameters from wellknow url
2026-01-29 12:09:53 +01:00
Laurent Destailleur
758ee4bef7 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-29 11:28:53 +01:00
Laurent Destailleur
5cf7b54c41 More robust phpunit 2026-01-29 11:25:33 +01:00
Laurent Destailleur
234607a3dd Log 2026-01-29 11:00:43 +01:00
Laurent Destailleur
c23b58d416 Merge manually changes from #37012 that seems good. 2026-01-29 10:56:26 +01:00
Laurent Destailleur
c07ac38ddb Fix test 2026-01-29 10:31:49 +01:00
Laurent Destailleur
183451c607 Clean code 2026-01-29 09:56:10 +01:00
Laurent Destailleur
aa451769ce Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 19:47:35 +01:00
Laurent Destailleur
ffc5ee41f9 ci 2026-01-28 19:47:23 +01:00
MDW
ec69a624e0 qual: Update french texts (comments) to english (#37009)
* qual: Update french texts (comments) to english

* Qual: Update comment to english in card-rec.php and card.php

Translation of comments in the files card-rec.php and card.php.

* Qual: Translate comments to English

* Qual: Translate comments to English

* Fix space into tab

* Fix spelling

* Qual: Translate comments to English

* Update website.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-28 19:34:12 +01:00
Laurent Destailleur
42751b532e ci 2026-01-28 19:06:13 +01:00
Laurent Destailleur
3a80f4296f ci 2026-01-28 19:00:46 +01:00
Laurent Destailleur
863b5e4303 CI 2026-01-28 18:55:29 +01:00
Laurent Destailleur
de7190eb24 CI 2026-01-28 18:41:58 +01:00
Laurent Destailleur
72a13b8586 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 18:37:02 +01:00
Laurent Destailleur
2ed9107dc0 Try to fix phan 2026-01-28 18:32:27 +01:00
atm-jonathan
d9ee7a6b5e prevent ST_AsWKT() (#37013)
* prevent ST_AsWKT()

* Update commonobject.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-28 18:21:32 +01:00
hansemschnokeloch
4682a9bbfa Remove jstz.min.js from JavaScript array (#37017)
jstz.min.js was deleted in 5599ac733b
2026-01-28 18:01:17 +01:00
hansemschnokeloch
4f2d91d30b Fix typo in phpstan.neon.dist for isset() rule (#37018)
See https://github.com/Dolibarr/dolibarr/actions/runs/21444577128/job/61756970301?pr=37017
2026-01-28 18:00:32 +01:00
Laurent Destailleur
6323e09ba9 CI 2026-01-28 17:59:21 +01:00
Laurent Destailleur
0ccb67c2ef CI 2026-01-28 17:35:00 +01:00
Laurent Destailleur
fdaff88ff7 CI 2026-01-28 17:13:30 +01:00
Laurent Destailleur
49589ab9b1 Trans 2026-01-28 17:11:30 +01:00
Laurent Destailleur
568e69d537 CI 2026-01-28 17:03:52 +01:00
Laurent Destailleur
2890d4a196 CI 2026-01-28 16:55:01 +01:00
Laurent Destailleur
35305eb56e CI 2026-01-28 16:52:52 +01:00
Laurent Destailleur
0ccc9c2802 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-28 16:23:07 +01:00
Laurent Destailleur
71cb371a1a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 16:21:37 +01:00
Laurent Destailleur
9c832c58ad Exclude non interesting warning 2026-01-28 16:21:24 +01:00
Frédéric FRANCE
11c2feb486 NEW add image format avif (#37014)
* add format avif

* Update functions.lib.php
2026-01-28 16:19:01 +01:00
Lucas Marcouiller
27db2c8169 NEW add import of leave balance (Implementation) (#37011)
* New add import Leave Balance

* add eof

* Update modHoliday.class.php

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-28 16:16:20 +01:00
Braito
d3bb30c1d5 Improve OAuth HTTP error details (#36951)
Keep throwing TokenResponseException on HTTP 4xx/5xx while also capturing the response body (ignore_errors) to include a short snippet for admins.

Co-authored-by: caminotravelcenter <caminotravelcenter@localhost>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-28 15:56:01 +01:00
Laurent Destailleur
882200d897 Fix CI 2026-01-28 15:24:31 +01:00
Laurent Destailleur
fa800c532a ci 2026-01-28 15:23:06 +01:00
Laurent Destailleur
2977297582 Doc 2026-01-28 15:21:46 +01:00
Alexandre SPANGARO
58709579cc NEW Add new EUID number (#36997) 2026-01-28 15:18:43 +01:00
Laurent Destailleur
f403a0c705 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 15:07:27 +01:00
Laurent Destailleur
06e328eb0b Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 15:06:59 +01:00
Laurent Destailleur
afc22d2ba0 CI 2026-01-28 15:06:40 +01:00
Frédéric FRANCE
1819296689 fix phan (#37008)
PhanTypeMismatchArgumentNullable Argument 3 ($txt) is $productlot->batch of type ?string but \TCPDF::MultiCell() takes string defined at htdocs/includes/tecnickcom/tcpdf/tcpdf.php:5871 (expected type to be non-nullable)
2026-01-28 15:04:49 +01:00
Laurent Destailleur
8710651e45 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 15:04:14 +01:00
Laurent Destailleur
1bcc8e7fbd CI 2026-01-28 15:04:03 +01:00
Frédéric FRANCE
35b74ef7d6 fix phan (#37007) 2026-01-28 14:58:32 +01:00
Laurent Destailleur
3646b8cbe7 Try to fix CI 2026-01-28 14:58:18 +01:00
Laurent Destailleur
f23394dd53 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-28 14:57:28 +01:00
Laurent Destailleur
18e7d44790 CI 2026-01-28 14:54:40 +01:00
MDW
58ee81186f Qual: Update Phan baseline.txt with reduced issue counts (#36996)
This commit updates the Phan baseline.txt file.
2026-01-27 17:56:36 +01:00
Lucas Marcouiller
8d6e02c373 New import Leave Balance (Datastructure) (#37001)
* New import Leave Balance (Datastructure)

* fix

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-27 17:55:23 +01:00
Laurent Destailleur
0a98a5ca44 Doc 2026-01-27 17:39:02 +01:00
Laurent Destailleur
3ff33915c0 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-27 01:15:58 +01:00
Laurent Destailleur
6808e132f3 WIP LNE 2026-01-27 01:15:30 +01:00
Laurent Destailleur
1212f640c0 Trans 2026-01-26 21:41:02 +01:00
Laurent Destailleur
8fbb1afae9 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-26 20:36:29 +01:00
Laurent Destailleur
5efcd7652f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-26 19:35:29 +01:00
Braito
9ab11b497e FIX|Fix supplier payment presend mail/PDF (#36939)
- Keep the presend form open after applying an email template.

- Use getDolGlobalString('SUPPLIER_PAYMENT_ADDON_PDF') (no direct ->global access).

- Ensure a PDF model is selected (fallback to first available or standard_supplierpayment) so receipt generation/attachment works.

Signed-off-by: Camino Travel Center <noreply@caminotravelcenter.com>
Co-authored-by: Camino Travel Center <noreply@caminotravelcenter.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-26 18:23:01 +01:00
Laurent Destailleur
c1cb839d7d ci 2026-01-26 18:21:49 +01:00
Laurent Destailleur
801fcfbf34 CI 2026-01-26 18:07:51 +01:00
Laurent Destailleur
375fb90bed ci 2026-01-26 18:00:00 +01:00
Laurent Destailleur
45b15db4c6 ci 2026-01-26 17:37:31 +01:00
Laurent Destailleur
d3a1bd58eb Code comment 2026-01-26 16:19:45 +01:00
Laurent Destailleur
00e19d474e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-26 16:11:36 +01:00
Laurent Destailleur
fab5a769e4 Fix CI 2026-01-26 16:11:21 +01:00
Vincent Penel
ba3df067f3 Automatically send the invoice generated from a template DB (#36947)
* Update DB

* Add flag auto send

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-26 15:53:45 +01:00
Laurent Destailleur
22ffe7f645 Fix ci 2026-01-26 15:47:04 +01:00
Laurent Destailleur
0b7dfad2cf Code comment 2026-01-26 15:21:50 +01:00
Laurent Destailleur
28ce9c657c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-26 11:58:08 +01:00
Laurent Destailleur
a3c8a832a2 ci 2026-01-26 11:57:58 +01:00
Frédéric FRANCE
8ef582eaf5 display color selected in dict (#36500)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-25 16:16:47 +01:00
noec764
4b2ca3bd28 FIX: Add missing event counter on Agenda tab (#36972)
Co-authored-by: Noé <noe@scopen.fr>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-25 15:55:05 +01:00
Laurent Destailleur
619fb3a590 Debug v23 2026-01-25 15:49:44 +01:00
Laurent Destailleur
156828ac1f Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-25 15:35:34 +01:00
Laurent Destailleur
57950b25fd Trans 2026-01-25 15:33:54 +01:00
Laurent Destailleur
6318b1a836 Clean code 2026-01-25 14:54:56 +01:00
Laurent Destailleur
e79c8d0b87 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-25 14:20:52 +01:00
Laurent Destailleur
1da17070f5 Code comment 2026-01-25 14:19:59 +01:00
Alexandre SPANGARO
82cf80cbc3 Move module asset to stable (#36983) 2026-01-25 14:13:09 +01:00
Laurent Destailleur
57be3472a2 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-24 20:13:16 +01:00
Braito
3a61d3f2c9 Fix SMTP OAuth refresh scopes (#36950)
Recreate the OAuth service with its configured scopes when refreshing an access token (required by some providers like Microsoft v2).

Also keep the previous refresh token when the refreshed token does not include one (e.g. Google returns it only once).

Co-authored-by: caminotravelcenter <caminotravelcenter@localhost>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 20:13:06 +01:00
Laurent Destailleur
7f13a3035c Lazy load of substitution array can accept arrays. 2026-01-24 19:43:12 +01:00
Laurent Destailleur
06e2e60364 Fix ci 2026-01-24 19:24:19 +01:00
Laurent Destailleur
6b8214ea6a Fix ci 2026-01-24 18:07:53 +01:00
Laurent Destailleur
27026eced9 Fix ci 2026-01-24 18:00:45 +01:00
Laurent Destailleur
c8e755e5a8 ci 2026-01-24 17:53:57 +01:00
Laurent Destailleur
101b0d7e12 FIX substitution of vars in donation templates 2026-01-24 17:40:22 +01:00
Laurent Destailleur
bb28eed850 Fix ci 2026-01-24 16:15:31 +01:00
Laurent Destailleur
88a1b168ad Fix ci 2026-01-24 16:13:00 +01:00
Laurent Destailleur
7b17ceeefa Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-24 13:54:37 +01:00
Laurent Destailleur
e18220e8eb Fix code action 2026-01-24 13:54:10 +01:00
Charlène Benke
0e51a7a529 Add source parameter to getContacts on api interventional (#36931)
Added a new parameter 'source' to the getContacts method to filter contacts based on their source (internal or external). Updated the method to handle the new parameter appropriately.

propose to add this feature on all getContacts method.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-24 13:42:54 +01:00
Laurent Destailleur
0029d891a6 Fix ci 2026-01-24 12:46:32 +01:00
Laurent Destailleur
b6c9c42144 Fix ci 2026-01-24 12:43:14 +01:00
Laurent Destailleur
237d623d31 Try fix ci 2026-01-23 22:53:22 +01:00
Laurent Destailleur
639e75b8ae Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-23 22:44:55 +01:00
Laurent Destailleur
455f91c215 Debug v23 2026-01-23 22:44:34 +01:00
Laurent Destailleur
eed0f219a1 Fix ci 2026-01-23 22:43:56 +01:00
Laurent Destailleur
de877188c1 ci 2026-01-23 18:48:57 +01:00
Laurent Destailleur
818dea526b ci 2026-01-23 18:46:38 +01:00
Laurent Destailleur
4c07ef386e Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-23 18:44:37 +01:00
Laurent Destailleur
61c913dff0 Fix ci 2026-01-23 18:43:54 +01:00
Laurent Destailleur
bf9f0e6eb8 Fix ci 2026-01-23 18:40:36 +01:00
Laurent Destailleur
e1b48219df Fix ci 2026-01-23 18:37:58 +01:00
Laurent Destailleur
b75383670c Fix select resource 2026-01-23 18:33:45 +01:00
Charlène Benke
4f15a2e408 Change resource selection index from 1 to 2 (#36955)
fix warning causing by returning array (1 to 2) and suppress search button (0 to 2)
2026-01-23 18:32:34 +01:00
Laurent Destailleur
037ba0212a Fix label of vdp report 2026-01-23 18:28:13 +01:00
Laurent Destailleur
a92cd402d6 Fix ci 2026-01-23 18:21:10 +01:00
Laurent Destailleur
21102855a7 Fix french comment 2026-01-23 18:16:53 +01:00
Laurent Destailleur
6d03ec417a Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-23 18:08:12 +01:00
Laurent Destailleur
237d8d5b90 ci 2026-01-23 18:07:16 +01:00
Alexandre SPANGARO
fd44a5f0e8 NEW - VAT Report - Add button to collapse / expand all rates (#36946)
* NEW - VAT Report - Add button to collapse / expand all rates

* Fix CI

* CI

* Update disposition

* Escape HTML tags in URL parameter handling

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-23 17:55:24 +01:00
Laurent Destailleur
ec04a1bbbd Fix ci 2026-01-23 17:52:27 +01:00
Laurent Destailleur
35f3c56b96 Fix ci 2026-01-23 17:49:37 +01:00
Zakaria Boushaba
ca56cbdaf7 fix: exclude special lines from supplier order dispatch count (#36964)
Co-authored-by: Zakaria Boushaba <z.boushaba@vold.africa>
2026-01-23 16:57:11 +01:00
Lucas Marcouiller
cc222b3ca7 Fix bad trans for member subscription on import (#36969)
* Fix bad trans for member subscription on import

* fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-23 16:51:57 +01:00
Lucas Marcouiller
1fd2674795 Fix email collector ticket fetch (#36968)
* Fix email collector ticket fetch

* fix CI

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
2026-01-23 16:51:13 +01:00
Laurent Destailleur
f848220c59 Clean code 2026-01-23 13:29:28 +01:00
Laurent Destailleur
0ae23ec0d1 Fix log 2026-01-21 19:19:36 +01:00
Laurent Destailleur
7ad0874162 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-21 18:23:15 +01:00
Laurent Destailleur
3cbe24ad8c Doc 2026-01-21 18:23:03 +01:00
Laurent Destailleur
a3e6bbb862 Code comment 2026-01-21 17:43:10 +01:00
Laurent Destailleur
1edf2a6ae1 ci 2026-01-21 14:30:04 +01:00
splohmer
508cf6fba9 FIX missmatch of permission check of button and action of cancel delivery note (expedition) (#36943)
In expedition/card.php there is the action "confirm_cancel" which checks for the right supprimer of expedition. The corresponding UI Button checks for creer of expedition. This means some people can see the button, but nothing happens when clicking on it (also no error message).
2026-01-21 14:25:24 +01:00
John BOTELLA
3a3a20e537 QUAL : remove PHP in JS CODE (#36473)
* New hooks and data for ajax getSupplier price

* Fix header

* Quality of code : remove PHP from js code part 02

* Quality of code : remove PHP from js code part 02

* Quality of code : remove PHP from js code part 02

* remove last php

* import last develop changes

* Update objectline_create.tpl.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-21 14:24:30 +01:00
Laurent Destailleur
e72345334a Fix ci 2026-01-21 13:40:25 +01:00
Laurent Destailleur
7f3a6a5a40 ci 2026-01-21 13:35:29 +01:00
Laurent Destailleur
b14bae17ae Fix ci 2026-01-21 13:22:02 +01:00
Laurent Destailleur
c89d710fdd Fix ci 2026-01-21 12:47:45 +01:00
Laurent Destailleur
a79d80e11a Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-21 12:45:03 +01:00
Laurent Destailleur
ad092a37f3 Fix ci 2026-01-21 12:44:12 +01:00
Laurent Destailleur
d4030302c9 Comment 2026-01-21 12:29:49 +01:00
Laurent Destailleur
fba2a97ab6 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-21 12:16:44 +01:00
Laurent Destailleur
a2555bab6b Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-21 12:14:46 +01:00
Laurent Destailleur
eff943bbcf Fix false positive 2026-01-21 12:14:27 +01:00
Charlène Benke
47ae685061 NEW Update holiday class to handle date_create field (#36918)
* Update holiday class to handle date_create field

Add conditional logic to include date_create in SQL update.

* Update holiday.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-21 01:41:03 +01:00
Charlène Benke
9a75f66e29 NEW Can add date_create on expense report update (#36936)
* Add date_create on expense report update

* Update expensereport.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-21 01:39:46 +01:00
John BOTELLA
5672008258 FIX WebPortal responsive menu dropdown (#36937)
* Fix responsive menu dropdown

* Change comment from French to English

Updated comment to English for better clarity.

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-21 01:39:23 +01:00
Frédéric FRANCE
5ecc8fe61e add filter on product list (#36926)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-21 01:36:58 +01:00
Laurent Destailleur
01c2c563fb Fix css 2026-01-21 00:47:06 +01:00
Laurent Destailleur
c570b91c96 Debug 2026-01-21 00:36:37 +01:00
Laurent Destailleur
fb7232dc82 Doc 2026-01-21 00:33:24 +01:00
Laurent Destailleur
60dcff1475 Clean code 2026-01-21 00:31:08 +01:00
Laurent Destailleur
0698c3316b Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-21 00:10:40 +01:00
Laurent Destailleur
db49600983 Fix ci 2026-01-21 00:10:30 +01:00
Charlène Benke
33c51e3704 add holiday reference on user hr bank tabs (#36933) 2026-01-21 00:08:29 +01:00
Braito
8d388632cf fix(cron): clamp lastoutput and harden run_jobs (#36938)
* FIX|Fix Cron job lastoutput overflow

Clamp cronjob.lastoutput to MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD in create/update to avoid SQL errors when output exceeds DB TEXT size.

Also harden run_jobs():
- jobtype=function: report lib/lang load failures into lastoutput/lastresult and parse params more reliably (comma + trim, supports "0").
- jobtype=command: mark run as failed when CLI is disabled, fall back to sys_get_temp_dir(), and report an explicit error if no temp dir can be resolved.

Signed-off-by: Camino Travel Center <noreply@caminotravelcenter.com>

* Update cronjob.class.php

---------

Signed-off-by: Camino Travel Center <noreply@caminotravelcenter.com>
Co-authored-by: Camino Travel Center <noreply@caminotravelcenter.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-20 23:53:29 +01:00
Laurent Destailleur
106ffcfbd6 Fix legacy code 2026-01-20 23:35:41 +01:00
Laurent Destailleur
38f6c4bce1 Remove a TODO 2026-01-20 23:25:27 +01:00
Laurent Destailleur
53231470fc Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-20 23:16:38 +01:00
Laurent Destailleur
715aeb91d9 Fix CI 2026-01-20 23:16:24 +01:00
Frédéric FRANCE
d77fe3afe8 fix ci (#36942)
* fix ci

* Update contact.php
2026-01-20 23:07:24 +01:00
Laurent Destailleur
b93aacbba2 Fix CI 2026-01-20 17:39:40 +01:00
Laurent Destailleur
618ef9925b Fix CI 2026-01-20 17:36:38 +01:00
Laurent Destailleur
6549f135d1 FIX CI 2026-01-20 17:12:25 +01:00
Laurent Destailleur
8da132d4ce Fix CI 2026-01-20 17:04:07 +01:00
Laurent Destailleur
d8a146d6f3 Fix CI 2026-01-20 16:48:27 +01:00
Laurent Destailleur
a6c11e27b1 Fix CI 2026-01-20 16:46:14 +01:00
Laurent Destailleur
275b82e51e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-20 14:57:32 +01:00
Laurent Destailleur
6f8a8834b8 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-20 14:57:22 +01:00
lvessiller-opendsi
d51a5a9068 FIX color of ajax on/off button on setup page (#36917)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-20 14:51:43 +01:00
Laurent Destailleur
4ee6eb2e2d Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-20 14:04:47 +01:00
Laurent Destailleur
7d13c12252 Fix CI 2026-01-20 14:01:09 +01:00
Alexandre SPANGARO
3913f4418e Asset - Simplify menu (#36911)
* Asset - Simplify menu

* Asset - Simplify menu

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-20 13:57:33 +01:00
Laurent Destailleur
ff4b7c54d8 Fix CI 2026-01-20 13:56:52 +01:00
Laurent Destailleur
1e8fdd41c9 Fix CI 2026-01-20 13:35:31 +01:00
Laurent Destailleur
7b9a485f17 Fix CI 2026-01-20 13:22:48 +01:00
Laurent Destailleur
8af405a3e8 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-20 12:36:29 +01:00
Laurent Destailleur
ae52d75335 NEW Can add more tags to default tags in dolPrintHTML 2026-01-20 12:30:08 +01:00
Vincent Penel
20dfc743e0 Update DB (#36925) 2026-01-20 11:36:00 +01:00
Laurent Destailleur
6571096107 Merge 2026-01-20 02:37:16 +01:00
Laurent Destailleur
6e6779f401 Merge branch 'develop' of github.com:Dolibarr/dolibarr into develop 2026-01-20 00:30:09 +01:00
Laurent Destailleur
b79ade4c1f Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-19 21:18:00 +01:00
Laurent Destailleur
61f90ab20c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 21:16:07 +01:00
Laurent Destailleur
9c899899f3 Fix CI 2026-01-19 21:15:46 +01:00
Frédéric FRANCE
3401bd6249 fetchAll ecm_files load extrafields (#36894) 2026-01-19 20:53:30 +01:00
Laurent Destailleur
92048de0f5 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 20:52:09 +01:00
Laurent Destailleur
01e37657a6 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 19:48:50 +01:00
Laurent Destailleur
f7e688f580 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 19:48:43 +01:00
William Mead
566aec36c6 Added since tags to orders api PHPDoc (#36919) 2026-01-19 19:10:44 +01:00
Charlène Benke
eeaa02390e Rename expense report to holiday in API class (#36920) 2026-01-19 19:10:20 +01:00
Laurent Destailleur
2893311770 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 19:08:15 +01:00
Laurent Destailleur
9790bf61c6 Fix CI 2026-01-19 19:08:02 +01:00
Laurent Destailleur
13d872a265 Fix warning 2026-01-19 18:39:34 +01:00
Laurent Destailleur
94217e800d Fix CI 2026-01-19 18:28:06 +01:00
Laurent Destailleur
3b23e76237 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 18:18:27 +01:00
Laurent Destailleur
7b12b10f9b Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 17:31:48 +01:00
Laurent Destailleur
68d92e59d2 Fix CI 2026-01-19 17:29:02 +01:00
Laurent Destailleur
76a2945d88 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 17:06:06 +01:00
Laurent Destailleur
99f5ede0ec Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 15:39:48 +01:00
Laurent Destailleur
3a01cd9002 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 14:48:21 +01:00
Laurent Destailleur
60fbdb1bc9 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 14:48:06 +01:00
Charlène Benke
76399298dc fix field name for create update payement (#36903) 2026-01-19 13:27:50 +01:00
Charlène Benke
b79aaf99d7 Add setpaid call on api expensereport (#36904) 2026-01-19 13:27:22 +01:00
Laurent Destailleur
27aa36b537 Fix div balance 2026-01-19 03:50:15 +01:00
Laurent Destailleur
a7e54c5e36 Better title for stipe pages 2026-01-19 01:17:36 +01:00
Laurent Destailleur
f2455704d2 NEW Button to close/reopen bank account status 2026-01-19 01:07:33 +01:00
Laurent Destailleur
354559aa19 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 00:27:30 +01:00
Laurent Destailleur
820f3f44c7 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-19 00:26:48 +01:00
Laurent Destailleur
47c4ebeb14 WIP Upload file with AI parsing 2026-01-18 21:29:19 +01:00
Laurent Destailleur
e26c965b7c Doc 2026-01-18 14:23:52 +01:00
Laurent Destailleur
3ba8daab0c Work on AI doc parsing protopype 2026-01-18 14:21:09 +01:00
Laurent Destailleur
f99df3ddc8 Fix position of html components 2026-01-17 18:32:25 +01:00
Laurent Destailleur
2e3d1b0ccd CSS 2026-01-17 16:03:14 +01:00
Laurent Destailleur
ec27124e24 Log message 2026-01-16 18:08:48 +01:00
Laurent Destailleur
c3e043d656 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-16 16:51:37 +01:00
Laurent Destailleur
06a5ea19c4 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-16 16:43:45 +01:00
Laurent Destailleur
3cc2f1b146 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-16 16:37:56 +01:00
Laurent Destailleur
7dee283762 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-01-16 16:34:32 +01:00
Laurent Destailleur
949c111f68 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-16 16:32:40 +01:00
Frédéric FRANCE
d07ce2bd08 enhance actioncomm reminder (#36316)
* enhance actioncomm reminder

* fix
2026-01-16 11:32:43 +01:00
Alexandre SPANGARO
8838ad7636 UX Accountancy - Card - Add link to element (#36452)
* UX Accountancy - Card - Add link to element

* CI
2026-01-16 11:31:20 +01:00
Francis
5180d59fc3 Update visibility logic for individual and professional lines (#36449)
Hi
It is a long time that I modify my Dolibarr to erase some items which are not interesting for individual customer...
I decided to post my solution !!!
A css class call professionalline to allow to erase some items !
A simple switch show/hide...
Francis
2026-01-16 11:29:41 +01:00
Frédéric FRANCE
723df03c0d clean printipp (#36472)
* clean printipp

* clean printipp

* clean printipp

* clean printipp

* clean printipp

* clean printipp

* Update functions.lib.php
2026-01-16 11:28:47 +01:00
Frédéric FRANCE
b5394f763a time to init modules (#36526)
* time to init modules

* time to init modules

* Update modules.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-16 11:14:27 +01:00
atm-corentin
9c04379799 NEW : add support for label field in addline method In supplier order (#36544)
* add support for label field in addline method to set description when empty

* update
2026-01-16 11:12:47 +01:00
Eric - CAP-REL
7f6966ee06 add hooks on extrafields (#36536) 2026-01-16 11:12:22 +01:00
Lucas Marcouiller
0aa629cfe0 fix change some conf->global to getdolglobal (#36874)
* fix change some conf->global to getdolglobal

* revert some changes

---------

Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-16 02:55:21 +01:00
Alexandre SPANGARO
bd4b90eadf NEW Supplier invoice - List - use select2 multiselect for status (#36887) 2026-01-16 02:51:21 +01:00
Frédéric FRANCE
b6a49cb4bd fix french doc (#36895)
* fix french doc

* fix french

* Update sync_members_types_dolibarr2ldap.php

* fix french doc

* Update translate.class.php

* Update export-bank-receipts.php

* Update product.class.php

* Update product.class.php
2026-01-16 02:32:37 +01:00
Frédéric FRANCE
d770d37e29 add phpcs rule extension (#36561)
* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* add phpcs rule extension

* test

* test

* test

* test

* test

* test

* fix

* fix

* fix

* fix

* fix

* fix

* fix translations

* fix translations

* translate

* translate

* translate

* translate

* translate

* translate

* translate

* Update propal.class.php
2026-01-15 16:05:06 +01:00
Charlène Benke
2c5be593c4 Add includepermissions parameter to infoGroups api method (#36856)
Added parameter to include permissions in infoGroups method.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 03:19:59 +01:00
Laurent Destailleur
5929de443e Debug v24 2026-01-15 03:18:50 +01:00
William Mead
7b9a878af2 NEW IP restriction to CIDR range (#36855)
* Added IP in CIDR range check

* Cleaned code

* Cleaned code

* Updated conf example

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 03:16:10 +01:00
Charlène Benke
d37d84b66e add user table on api holiday index (#36862)
added a join to the user table in the SQL query.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 03:14:24 +01:00
Charlène Benke
a994dbf674 NEW : Fichinter model on stable version (#36873)
* fichinter model on stable version

* Simplify menu addition for ListOfTemplates

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 03:04:27 +01:00
Lucas Marcouiller
f1b4379a0e Fix agenda search for holiday or birthday (#36878)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 02:04:57 +01:00
tcesar
200c88a55b New Add day selection for payment reports (#36799)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 02:04:41 +01:00
Charlène Benke
417bdc88ce Fix warning : add test on $key_fields['default'] is set (#36870)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 01:57:41 +01:00
github-actions[bot]
35602c6ff4 PHPStan > Update baseline (#36876)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-15 01:28:31 +01:00
Laurent Destailleur
4255228273 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-14 21:39:25 +01:00
Laurent Destailleur
c39939fb21 Log travis 2026-01-14 17:48:49 +01:00
Laurent Destailleur
263cba5c0e Fix CI 2026-01-14 17:40:43 +01:00
Laurent Destailleur
4cffb37310 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-14 16:23:52 +01:00
Laurent Destailleur
e2cd37a178 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-14 15:42:21 +01:00
Laurent Destailleur
4d65ce61d6 Clean code 2026-01-13 23:25:12 +01:00
Laurent Destailleur
e9ac39c031 Fix CI 2026-01-13 23:06:07 +01:00
Laurent Destailleur
cb99921d7c Fix include 2026-01-13 21:51:01 +01:00
Laurent Destailleur
b02d1e0ada Fix error code 2026-01-13 21:48:45 +01:00
Laurent Destailleur
7a93278cb7 Fix generic password type 2026-01-13 19:00:00 +01:00
Laurent Destailleur
750e1ccc90 NEW Global option do diable email is on each email setup page 2026-01-13 16:10:34 +01:00
Laurent Destailleur
72b746ddd3 Fix CI 2026-01-13 15:56:03 +01:00
Laurent Destailleur
4abad0b347 Fix warning oauth 2026-01-13 15:55:56 +01:00
Laurent Destailleur
f1e45a3f69 Fix add missing message once token has been saved 2026-01-13 15:24:26 +01:00
Laurent Destailleur
f373c65b08 Fix missing state 2026-01-13 14:53:31 +01:00
Laurent Destailleur
5c43f8a2cf Fix CI 2026-01-13 11:34:25 +01:00
Laurent Destailleur
8531f6a2aa Fix CI 2026-01-13 11:33:09 +01:00
Laurent Destailleur
509e93e425 Fix CI 2026-01-13 11:31:48 +01:00
Laurent Destailleur
6ca16f700d Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-13 11:21:00 +01:00
Laurent Destailleur
8ed5f73a71 Add registration number into file 2026-01-12 19:44:43 +01:00
Laurent Destailleur
98a179f638 Fix filter 2026-01-12 19:18:52 +01:00
Laurent Destailleur
9464f88162 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-12 16:14:28 +01:00
Laurent Destailleur
1d37667947 Fix warning 2026-01-12 16:14:19 +01:00
github-actions[bot]
84ac2a32ee PHPStan > Update baseline (#36852)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
2026-01-12 16:05:40 +01:00
Laurent Destailleur
9f151233be Clean code 2026-01-12 14:14:19 +01:00
Laurent Destailleur
c92b7874a3 Enhance modify control of invoices 2026-01-12 14:13:37 +01:00
Laurent Destailleur
91c35d4e40 NEW Add a protection against total change on a validated invoice. 2026-01-12 13:44:30 +01:00
Laurent Destailleur
15054810ba Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop
Debug v23
2026-01-12 13:42:02 +01:00
Laurent Destailleur
8dd0aeb1c8 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-12 01:36:19 +01:00
Laurent Destailleur
041f50a438 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-12 01:00:32 +01:00
Laurent Destailleur
fb99d6e736 Debug v23 2026-01-12 00:59:17 +01:00
Laurent Destailleur
8d1cb356c3 Link to societe_rib into llx_facture 2026-01-11 19:16:22 +01:00
Laurent Destailleur
9403eb5aab Copy some field of customer invoices into supplier invoices 2026-01-11 19:12:19 +01:00
Laurent Destailleur
94c75d399d Add field thirdparty_payment_id 2026-01-11 19:08:28 +01:00
Laurent Destailleur
d280468216 Debug v23 2026-01-11 18:12:45 +01:00
Laurent Destailleur
c019159f05 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-11 17:57:29 +01:00
Laurent Destailleur
a303b97330 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-11 17:53:32 +01:00
Laurent Destailleur
382a211962 Try to fix warning 2026-01-11 16:25:10 +01:00
Laurent Destailleur
a4852508e3 Clean code 2026-01-11 16:19:47 +01:00
Laurent Destailleur
d803fc5f28 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-11 16:18:52 +01:00
Laurent Destailleur
4d23bfbffa Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-11 13:13:14 +01:00
Laurent Destailleur
3fbee82d99 Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-01-11 13:13:06 +01:00
spsolauv
ca52029551 CLOSE issue 36744 fix user can delete some actioncomm on which he has not the right (#36747)
* CLOSE issue 36744 fix user can delete some actioncomm on which he has not the right

* Fix whitespace

* Refactor delete confirmation logic for user access

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-11 12:33:17 +01:00
Expresion
9fa9d395dc Fix numeric input parsing to support comma as decimal separator (#36845)
* Fix numeric input parsing to support comma as decimal separator

GETPOSTINT()  only handles integer values and fails when input uses a comma as decimal

* Update dispatch.php

* Change GETPOST to GETPOSTFLOAT for price input

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-01-10 18:24:19 +01:00
Laurent Destailleur
cf621642fb Revert "NEW : allow to save stocks as 0 on a stock movement. (#36812)" (#36848)
This reverts commit 5662bfad31.
2026-01-10 18:21:41 +01:00
Laurent Destailleur
61188c10c0 Debug v24 2025-01-16 10:54:15 +01:00
Laurent Destailleur
219cd50c17 CI with beautify sh generates more trouble and time than it saves.
Removed.
2025-01-16 10:05:52 +01:00
Alexandre SPANGARO
de83d6b1c8 NEW Add EUID number (#37222)
* NEW Add EUID number

* Update example

* CI - Problem on formaccounting

* Fix merge

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 22:06:31 +01:00
MDW
7d89635c5b Qual: Update pre-commit for shell script formatting (#37221)
* Qual: Upgrade pre-commit/beautysh, .editorconfig for sh

# Qual: Upgrade pre-commit/beautysh, .editorconfig for sh

- Upgrade beautysh pre-commit hook (trixie/python 3.13 compatibility);
- Indicate tab indent for shell scripts in .editorconfig.

* Qual: Update pre-commit hooks configuration

- Exclude `dev/initdemo/initdemo.sh` from beautysh hook
- Enable shellcheck hook manually
- Fix indentation in `initdemo.sh`

* Qual: Update pre-commit hook configuration

- Update .pre-commit-config.yaml to exclude dolibarr.postrm from beautysh formatting

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 22:05:03 +01:00
Laurent Destailleur
bd2ff84a95 Debug v24 2026-02-17 22:00:22 +01:00
Laurent Destailleur
af872c27f7 Debug v24 2026-02-17 21:21:48 +01:00
Laurent Destailleur
753fbda91e Trans 2026-02-17 21:10:07 +01:00
Laurent Destailleur
48391fdbfa Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-17 21:01:39 +01:00
Laurent Destailleur
d213cc82f0 Sync transifex 2026-02-17 21:01:08 +01:00
Eric - CAP-REL
043e1520a6 remove id= from redirect : we use current logged user (#37217) 2026-02-17 20:46:15 +01:00
Francis
2aa45a3897 Comment out additional case for ORDER_SUPPLIER_SUBMIT (#37230)
Trigger ORDER_SUPPLIER_SUBMIT is not présent in module builder
See /fourn/commande/card.php line 2125
2026-02-17 20:37:10 +01:00
Laurent Destailleur
8558744df1 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2026-02-17 20:36:32 +01:00
Laurent Destailleur
60ed6ed3ca CI 2026-02-17 20:36:22 +01:00
evarisk-kilyan
da1ea959cb #37167 [TicketAdmin] add: notification ticket_create email template config (#37229)
* #37167 [TicketAdmin] add: notification ticket_create email template config

* #37167 [Lang] add: langs trans
2026-02-17 20:31:53 +01:00
Anthony Damhet
7786bfcd0a Added intuitive selection of table rows for missing objects (#37231)
Add the row-with-select class to list tables

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 20:29:00 +01:00
Laurent Destailleur
aef5a5ee91 CI 2026-02-17 20:28:28 +01:00
Erwan-Wiwit
0f397ece1c Add hook beforeCreateStripePaymentIntent in getPaymentIntent() (#37261)
Add a hook point in Stripe::getPaymentIntent() to allow external modules
to modify the $dataforintent array before the Stripe PaymentIntent::create()
API call.

This enables modules to customize:
- statement_descriptor (e.g. structured communication for SEPA DD)
- metadata
- description
- payment_method_types
- and other PaymentIntent parameters

The $arrayofoptions (containing stripe_account and idempotency_key) is
intentionally NOT exposed for security reasons.

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2026-02-17 20:21:35 +01:00
Laurent Destailleur
26aefd139e Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2026-02-17 19:55:06 +01:00
Laurent Destailleur
26a78801d5 Debug v23 Fix creation of thirdparty from member and fix deletion 2025-01-16 10:02:33 +01:00
Laurent Destailleur
37a67f6fa6 Debug v24 2025-01-15 10:25:47 +01:00
1646 changed files with 82359 additions and 23056 deletions

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ on:
workflow_dispatch:
concurrency:
group: phan-${{ github.workflow }}-${{ github.ref }}
group: phan-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
@@ -34,13 +34,65 @@ jobs:
|| github.event.schedule == false
steps:
- uses: actions/checkout@v6
# Another method to get the list of changed files
# It sets the variable steps.changed-php.outputs.all_changed_files for other steps
- name: Get all changed php files (if PR)
id: changed-php
if: env.gh_event == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./.github/scripts/get_changed_php.sh
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
coverage: none # disable xdebug, pcov
tools: phan
tools: cs2pr,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') }}
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
phan $PHAN_QUICK -k "$PHAN_CONFIG" -B "$PHAN_BASELINE" --analyze-twice --minimum-target-php-version "$PHAN_MIN_PHP" --output-mode=github
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

View File

@@ -62,14 +62,55 @@ jobs:
phpstan-cache-${{ matrix.php-version }}-${{ github.head_ref }}-
phpstan-cache-${{ matrix.php-version }}-${{ github.base_ref }}-
phpstan-cache-${{ matrix.php-version }}-
- name: Show debug into
run: cd ./.github/tmp && ls -al
# Another method to get the list of changed files
# It sets the variable steps.changed-php.outputs.all_changed_files for other steps
- name: Get all changed php files (if PR)
id: changed-php
if: env.gh_event == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./.github/scripts/get_changed_php.sh
#- name: Get changed PHP files
# id: files
# run: |
# git fetch origin ${{ github.base_ref }}
# FILES=$(git diff --name-only "origin/${{ github.base_ref }}...HEAD" | grep '\.php$' || true)
# {
# echo "files<<EOF"
# echo "$FILES"
# echo "EOF"
# } > "$GITHUB_OUTPUT"
# 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') }}
env:
ALL_CHANGED_FILES: ${{ steps.changed-php.outputs.all_changed_files }}
# shellcheck disable=2086
run: |
phpstan -vvv analyse --error-format=checkstyle --memory-limit 7G -a dev/build/phpstan/bootstrap_action.php | tee _stan.xml | cs2pr --graceful-warnings
# 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
# continue-on-error: true
# Save cache
@@ -87,6 +128,7 @@ jobs:
name: phpstan-srcrt
path: ${{ github.workspace }}/_stan.xml
retention-days: 2
# Run PHPStan generate baseline
# - name: Run PHPStan generate baseline
# id: phpstan-baseline

View File

@@ -12,8 +12,7 @@ on:
workflow_dispatch:
concurrency:
group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref
}}
group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
gh_event: ${{ inputs.gh_event || github.event_name }}
@@ -110,15 +109,15 @@ jobs:
tools: phpcs
# Install perltidy and perlcritic
- name: Install perltidy and perlcritic
run: sudo apt-get update && sudo apt-get install -y perltidy libperl-critic-perl
#- name: Install perltidy and perlcritic
# run: sudo apt-get update && sudo apt-get install -y perltidy libperl-critic-perl
# Run all the precommit tools (defined into pre-commit-config.yaml).
# We can force exclusion of some of them here.
- name: Run pre-commit hooks
env:
# SKIP is used by pre-commit to not execute certain hooks
SKIP: no-commit-to-branch,php-cs,php-cbf,trailing-whitespace,end-of-file-fixer
SKIP: no-commit-to-branch,php-cs,php-cbf,trailing-whitespace,end-of-file-fixer,shellcheck
run: |
set -o pipefail
pre-commit gc

View File

@@ -1,5 +1,5 @@
---
exclude: (?x)^( htdocs/includes/ckeditor/.*|htdocs/public/includes/ckeditor/.*|(\.(?!github/workflows)[^/]*/.*))$
exclude: (?x)^( htdocs/includes/ckeditor/.*|htdocs/public/includes/ckeditor/.*|htdocs/public/includes/jquery/.*|(\.(?!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,25 +60,28 @@ 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.29.0
rev: v8.30.0
hooks:
- id: gitleaks
# Check github actions
- repo: https://github.com/rhysd/actionlint
rev: v1.7.8
rev: v1.7.11
hooks:
- id: actionlint
stages: [manual] # To run: pre-commit run -a --hook-stage=manual actionlint
# Beautify shell scripts
- repo: https://github.com/lovesegfault/beautysh.git
rev: v6.2.1
hooks:
- id: beautysh
exclude: |
(?x)^(dev/setup/git/hooks/pre-commit
)$
args: [--tab]
#- repo: https://github.com/lovesegfault/beautysh.git
# rev: v6.4.2
# 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]
# Run local script
#
@@ -193,7 +196,7 @@ repos:
# Check format of yaml files
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
rev: v1.38.0
hooks:
- id: yamllint
args:
@@ -249,11 +252,12 @@ repos:
rev: v0.11.0.1
hooks:
- id: shellcheck
stages: [manual] # To run: `pre-commit run -a --hook-stage=manual shellcheck`
args: [-W, "100"]
# Check sql file syntax
- repo: https://github.com/sqlfluff/sqlfluff
rev: 3.3.1
rev: 4.0.4
hooks:
- id: sqlfluff-lint
stages: [pre-commit, manual] # manual needed for ci
@@ -275,15 +279,15 @@ repos:
|htdocs/modulebuilder/template/sql/.*\.sql
)$
- repo: https://github.com/perltidy/perltidy
rev: '20250105.03'
hooks:
- id: perltidy
# virtualmin excuded - reason https://github.com/Dolibarr/dolibarr/pull/36370#issuecomment-3565101823
exclude: (?x)^
(dev/build/perl/virtualmin/dolibarr.pl
)$
args: [ --tabs, --nola ]
#- repo: https://github.com/perltidy/perltidy
# rev: '20250105.03'
# hooks:
# - id: perltidy
# # virtualmin excuded - reason https://github.com/Dolibarr/dolibarr/pull/36370#issuecomment-3565101823
# exclude: (?x)^
# (dev/build/perl/virtualmin/dolibarr.pl
# )$
# args: [ --tabs, --nola ]
#- repo: https://github.com/henryykt/pre-commit-perl
# rev: v0.0.5
@@ -292,4 +296,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,6 +531,9 @@ 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
@@ -571,6 +574,8 @@ 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

@@ -189,6 +189,8 @@ NEW: action to clone ticket
WARNING:
--------
The following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* If you were using the website module with PHP page, you must add the following parameter $dolibarr_website_allow_custom_php=2; into your conf.php to continue to be
allowed to edit PHP content into the website module.
* The deprecated column "egroupware_id" has been dropped from table llx_user.
* The property $sumpayed (duplicated of $totalpaid), $sumdeposit (duplicate of $totaldeposits) and $sumcreditnote (duplicate of $totalcreditnotes) has
been removed (there are replaced with the property that was a duplication of (same for $sumpayed_multicurrency, $sumdeposit_multicurrency, $sumcreditnote_multicurrency).

View File

@@ -7,4 +7,4 @@
/dolibarr-*.zip
/*.exe
/html
/makepack-dolibarr.pl.bak
/*.bak

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/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/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/jszip
- htdocs/includes/mike42
- htdocs/includes/phpoffice

View File

@@ -61,7 +61,7 @@ License: GPL-3+
------------------------------------------------------------
Files: htdocs/includes/ckeditor/*
Files: htdocs/public/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/includes/jquery/*
Files: htdocs/public/includes/jquery/*
Copyright: JQuery team
https://www.jquery.com
License: GPL-2+ or MIT

View File

@@ -97,10 +97,9 @@ 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/includes/ckeditor
# rm -fr htdocs/includes/jquery/js
# rm -fr htdocs/includes/jquery/css
# rm -fr htdocs/includes/jquery/plugins/flot
# rm -fr htdocs/public/includes/ckeditor
# rm -fr htdocs/public/includes/jquery/js
# rm -fr htdocs/public/includes/jquery/css
# clean from all embedded fonts (we use package dependencies instead)
# rm -fr htdocs/includes/fonts

View File

@@ -1,15 +1,15 @@
# 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
source-is-missing htdocs/public/includes/ckeditor/ckeditor/plugins/*/dialogs/*.js
source-is-missing htdocs/public/includes/ckeditor/ckeditor/plugins/*/filter/*.js
source-is-missing htdocs/public/includes/ckeditor/ckeditor/plugins/templates/templates/default.js
source-is-missing htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/*.js
# Those are false positives, the files are their own sources since
# they are data files

View File

@@ -40,9 +40,11 @@ if (substr($sapi_type, 0, 3) == 'cgi') {
define('DOL_DOCUMENT_ROOT', dirname(dirname($path)).'/htdocs');
//$algo = 'md5'; // Old algorithm
$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";
@@ -127,7 +129,10 @@ if ($tmpver[0] == 'auto') {
$release .= '-'.$tmpver[1];
}
}
// If release is auto, we take current version
$releaseblockedlog = DOLCERT_VERSION;
// If release is auto, we take current version to read checklock file
$tmpver = explode('-', $checklock, 2);
if ($tmpver[0] == 'auto') {
$checklock = DOL_VERSION;
@@ -182,6 +187,8 @@ 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' : '');
foreach ($includeconstants as $countrycode => $tmp) {
@@ -190,6 +197,7 @@ if ($release) {
}
}
print "\n";
print "\n";
}
if ($checklock) {
print "Working on files into : ".DOL_DOCUMENT_ROOT."\n";
@@ -335,13 +343,13 @@ if ($release) {
$checksumconcat = array();
if ($release) {
fputs($fp, '<dolibarr_unalterable_files version="'.$release.'">'."\n");
if ($release && $releaseblockedlog) {
fputs($fp, '<dolibarr_unalterable_files version="'.$releaseblockedlog.'">'."\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'),
@@ -425,6 +433,7 @@ foreach ($arrayofunalterablefiles as $entry) {
}
asort($checksumconcat); // Sort list of checksum
$hashunalterable_files = hash($algo, join(',', $checksumconcat));
if ($release) {

View File

@@ -20,27 +20,28 @@ use Cwd;
use Term::ANSIColor;
# Change this to defined target for option 98 and 99
$PROJECT = "dolibarr";
my $PROJECT = "dolibarr";
$PUBLISHBETARC =
my $PUBLISHBETARC =
"$ENV{'DESTIASSOLOGIN'}\@vmprod1.dolibarr.org:/home/dolibarr/asso.dolibarr.org/dolibarr_documents/website/www.dolibarr.org/files";
$PUBLISHSTABLE =
my $PUBLISHSTABLE =
"$ENV{'DESTISFLOGIN'}\@frs.sourceforge.net:/home/frs/project/dolibarr";
# due to implicit origin on git commands, example: implicit origin, lionel upstream, eric dolibarr
$GITREMOTENAME = "$ENV{'GITREMOTENAME'}";
my $GITREMOTENAME = "$ENV{'GITREMOTENAME'}";
#@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","EXEDOLIWAMP","SNAPSHOT"); # Possible packages
@LISTETARGET = (
my @LISTETARGET = (
"TGZ", "ZIP", "RPM_GENERIC", "RPM_FEDORA",
"RPM_MANDRIVA", "RPM_OPENSUSE", "DEB", "EXEDOLIWAMP",
"SNAPSHOT"
); # Possible packages
%REQUIREMENTPUBLISH = (
my %REQUIREMENTPUBLISH = (
"SF" => "git ssh rsync",
"ASSO" => "git ssh rsync"
);
%REQUIREMENTTARGET = ( # Tool requirement for each package
my %REQUIREMENTTARGET = ( # Tool requirement for each package
"-CHKSUM" => "",
"TGZ" => "tar",
"ZIP" => "7z",
"XZ" => "xz",
@@ -53,18 +54,18 @@ $GITREMOTENAME = "$ENV{'GITREMOTENAME'}";
"EXEDOLIWAMP" => "ISCC.exe",
"SNAPSHOT" => "tar"
);
%ALTERNATEPATH = (
my %ALTERNATEPATH = (
"7z" => "7-ZIP",
"makensis.exe" => "NSIS"
);
$RPMSUBVERSION = "auto"; # auto use value found into BUILD
my $RPMSUBVERSION = "auto"; # auto use value found into BUILD
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
use vars qw/ $REVISION $VERSION /;
$VERSION = "4.0";
my $VERSION = "4.0";
#------------------------------------------------------------------------------
# MAIN
@@ -198,7 +199,7 @@ open( my $IN, "<", $SOURCE . "/htdocs/version.inc.php" )
while (<$IN>) {
if ( $_ =~ /define\('DOL_MAJOR_VERSION',\s*'([\d\.a-z\-]+)'\)/ ) {
$MAJORVERSION = $1;
break;
last;
}
}
close $IN;
@@ -209,7 +210,7 @@ open( my $IN2, "<", $SOURCE . "/htdocs/filefunc.inc.php" )
while (<$IN2>) {
if ( $_ =~ /define\('DOL_MINOR_VERSION',\s*'([\d\.a-z\-]+)'\)/ ) {
$MINORVERSION = $1;
break;
last;
}
}
close $IN2;
@@ -395,6 +396,7 @@ foreach my $target ( sort keys %CHOOSEDTARGET ) {
}
$atleastonerpm = 1;
}
foreach my $req ( split( /[,\s]/, $REQUIREMENTTARGET{$target} ) ) {
# Test
@@ -814,19 +816,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/includes/ckeditor/ckeditor/adapters`
`rm -fr $BUILDROOT/$PROJECT/htdocs/public/includes/ckeditor/ckeditor/adapters`
; # Keep this removal in case we embed libraries
$ret =
`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/ckeditor/samples`
`rm -fr $BUILDROOT/$PROJECT/htdocs/public/includes/ckeditor/ckeditor/samples`
; # Keep this removal in case we embed libraries
$ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/_source`
$ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/public/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/includes/jquery/plugins/multiselect/MIT-LICENSE.txt`;
`rm -f $BUILDROOT/$PROJECT/htdocs/public/includes/jquery/plugins/multiselect/MIT-LICENSE.txt`;
$ret =
`rm -f $BUILDROOT/$PROJECT/htdocs/includes/jquery/plugins/select2/release.sh`;
`rm -f $BUILDROOT/$PROJECT/htdocs/public/includes/jquery/plugins/select2/release.sh`;
$ret =
`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/doc`;
$ret =
@@ -932,7 +934,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMETGZ/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMETGZ/htdocs/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMETGZ/htdocs/public/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";
@@ -969,7 +971,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMEXZ/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMEXZ/htdocs/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMEXZ/htdocs/public/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";
@@ -1008,7 +1010,7 @@ if ($nboftargetok) {
$ret = `rm -fr $BUILDROOT/$FILENAMEZIP/dev/build/exe`;
$ret =
`rm -fr $BUILDROOT/$FILENAMEZIP/htdocs/includes/ckeditor/_source`
`rm -fr $BUILDROOT/$FILENAMEZIP/htdocs/public/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";
@@ -1060,7 +1062,7 @@ if ($nboftargetok) {
$ret = `$cmd`;
# Removed files we don't need (already removed before)
#$ret=`rm -fr $BUILDROOT/$FILENAMETGZ2/htdocs/includes/ckeditor/_source`;
#$ret=`rm -fr $BUILDROOT/$FILENAMETGZ2/htdocs/public/includes/ckeditor/_source`;
print "Set permissions on files/dir\n";
$ret = `chmod -R 755 $BUILDROOT/$FILENAMETGZ2`;
@@ -1259,17 +1261,17 @@ if ($nboftargetok) {
# Removed duplicate license files
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/plugins/scayt/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/plugins/scayt/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/_source/plugins/wsc/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/_source/plugins/wsc/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/plugins/scayt/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/plugins/scayt/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/ckeditor/ckeditor/plugins/wsc/LICENSE.md`;
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/includes/ckeditor/ckeditor/plugins/wsc/LICENSE.md`;
$ret =
`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/includes/php-iban/LICENSE`;
$ret =
@@ -1292,7 +1294,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/includes/ckeditor/ckeditor/_source`;
#$ret=`rm -fr $BUILDROOT/$PROJECT.tmp/htdocs/public/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`;
@@ -1376,61 +1378,41 @@ 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`;
@@ -1447,10 +1429,8 @@ 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";
@@ -1458,7 +1438,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;
@@ -1480,17 +1460,15 @@ 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 $!;
@@ -1504,40 +1482,35 @@ 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");
@@ -1556,7 +1529,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" =>
@@ -1587,8 +1560,7 @@ 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" =>
@@ -1650,8 +1622,7 @@ 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;
@@ -1695,13 +1666,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 . "\"";

View File

@@ -7,24 +7,24 @@
#----------------------------------------------------------------------------
## no critic (InputOutput::ProhibitExplicitStdin,InputOutput::RequireBriefOpen)
use strict;
#use strict;
use warnings;
use Cwd;
use Term::ANSIColor;
$OWNER = "ldestailleur";
$GROUP = "ldestailleur";
my $OWNER = "ldestailleur";
my $GROUP = "ldestailleur";
@LISTETARGET = ("ZIP"); # Possible packages
%REQUIREMENTTARGET = ( # Tool requirement for each package
my @LISTETARGET = ("ZIP"); # Possible packages
my %REQUIREMENTTARGET = ( # Tool requirement for each package
"TGZ" => "tar",
"ZIP" => "7z"
);
%ALTERNATEPATH = ();
my %ALTERNATEPATH = ();
use vars qw/ $REVISION $VERSION /;
$REVISION = '1.0';
$VERSION = "3.5 (build $REVISION)";
my $REVISION = '1.0';
my $VERSION = "3.5 (build $REVISION)";
#------------------------------------------------------------------------------
# MAIN
@@ -184,7 +184,7 @@ foreach my $PROJECT (@PROJECTLIST) {
while (<$IN>) {
if ( $_ =~ /this->version\s*=\s*'([\d\.]+)'/ ) {
$PROJVERSION = $1;
break;
last;
}
}
close $IN;

File diff suppressed because it is too large Load Diff

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/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/nusoap
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts

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/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/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

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/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
# Lang

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/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/public/includes/ckeditor/_source
%{__rm} -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/htdocs/includes/fonts
# Lang

View File

@@ -263,7 +263,19 @@ with
PHP JQUERYFILETREE:
-------------------
* Remove directory htdocs/includes/jquery/plugins/jqueryFileTree/connectors
* Remove directory htdocs/public/includes/jquery/plugins/jqueryFileTree/connectors
PHP Mobile_DETECT:
------------------
Remplacer:
array $headers = null,
par
$headers = null,

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
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,5 +1,6 @@
#!/bin/bash
# Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
# Copyright (C) 2010-2026 Laurent Destailleur <eldy@users.sourceforge.net>
# Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
#------------------------------------------------------
# Script to purge and initialize a database with demo values.
@@ -11,8 +12,8 @@
# Regis Houssin - regis.houssin@inodbox.com
# Laurent Destailleur - eldy@users.sourceforge.net
#------------------------------------------------------
# Usage: initdemo.sh confirm
# usage: initdemo.sh confirm mysqldump_dolibarr_x.x.x.sql database port login pass
# Usage: initdemo.sh confirm|confirmresetblockedlog
# usage: initdemo.sh confirm|confirmresetblockedlog mysqldump_dolibarr_x.x.x.sql database port login pass
#------------------------------------------------------
@@ -37,18 +38,18 @@ fi
# ----------------------------- command line params
confirm=$1
dumpfile=$2
base=$3
port=$4
base="${3:-dolibarrdemo}"
port="${4:-3306}"
admin=$5
passwd=$6
# ----------------------------- check params
if [ "$confirm" != "confirm" ]
if [ "$confirm" != "confirm" ] && [ "$confirm" != "confirmresetblockedlog" ]
then
echo "----- $0 -----"
echo "Usage: initdemo.sh confirm "
echo "Usage: initdemo.sh confirm|confirmresetblockedlog "
echo " or"
echo "Usage: initdemo.sh confirm [mysqldump_dolibarr_x.x.x.sql database port login pass]"
echo "Usage: initdemo.sh confirm|confirmresetblockedlog [mysqldump_dolibarr_x.x.x.sql database port login pass]"
exit
fi
@@ -91,7 +92,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 dolibarrdemo 2> "$fichtemp"
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql database name :" 16 55 "$base" 2> "$fichtemp"
valret=$?
case $valret in
0)
@@ -107,7 +108,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 3306 2> "$fichtemp"
$DIALOG --title "Init Dolibarr with demo values" --clear --inputbox "Mysql port (ex: 3306):" 16 55 "$port" 2> "$fichtemp"
valret=$?
case $valret in
@@ -161,7 +162,7 @@ then
# ---------------------------- confirmation
$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
$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
case $? in
0) echo "Ok, start process..." ;;
@@ -172,7 +173,7 @@ then
fi
# ---------------------------- run sql file
# ---------------------------- Run sql file
if [ "$passwd" != "" ]
then
export passwd="-p$passwd"
@@ -181,8 +182,11 @@ 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"
echo "drop table if exists llx_accounting_account;"
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=$?
@@ -192,10 +196,24 @@ 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=$?
# ---------------------------- copy demo files
# ---------------------------- 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
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')
@@ -246,8 +264,8 @@ fi
if [ "$res" = "0" ]
then
echo "Success, file successfully loaded."
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."
else
echo "Error, load failed."
echo "Error, 1 step of script has failed."
fi
echo

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,6 @@
#!/bin/sh
#!/bin/bash
# Copyright (C) 2010-2026 Laurent Destailleur <eldy@users.sourceforge.net>
#------------------------------------------------------
# Script to extract a database with demo values.
# Note: "dialog" tool need to be available if no parameter provided.
@@ -11,26 +13,28 @@
#------------------------------------------------------
# shellcheck disable=2012,2006,2034,2046,2064,2086,2155,2166,2186,2172,2268
export mydir=`echo "$0" | sed -e 's/savedemo.sh//'`;
if [ "x$mydir" = "x" ]
export mydir
mydir=${0//savedemo.sh/}
if [ "$mydir" = "" ] || [ "$mydir" = "./" ]
then
export mydir="."
fi
export id=`id -u`;
export id
id=$(id -u)
# ----------------------------- check if root
if [ "x$id" != "x0" -a "x$id" != "x1001" ]
if [ "$id" != "0" ] && [ "$id" != "1001" ]
then
echo "Script must be ran as root"
echo "Script must be executed as root"
exit
fi
# ----------------------------- command line params
dumpfile=$1;
base=$2;
port=$3;
base="${2:-dolibarrdemo}"
port="${3:-3306}"
admin=$4;
passwd=$5;
@@ -54,7 +58,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)
@@ -71,7 +75,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 dolibarrdemo 2> $fichtemp
--inputbox "Mysql database name :" 16 55 "$base" 2> $fichtemp
valret=$?
case $valret in
0)
@@ -87,7 +91,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 3306 2> $fichtemp
--inputbox "Mysql port (ex: 3306):" 16 55 "$port" 2> $fichtemp
valret=$?
@@ -172,6 +176,7 @@ fi
if [ "x$passwd" != "x" ]
then
export passwd="-p$passwd"
export passwdshown="-p*****"
fi
export list="
--ignore-table=$base.llx_abonne
@@ -256,6 +261,7 @@ export list="
--ignore-table=$base.llx_c_ticketsup_type
--ignore-table=$base.llx_cabinetmed_c_banques
--ignore-table=$base.llx_cabinetmed_c_examconclusion
--ignore-table=$base.llx_cabinetmed_cons
--ignore-table=$base.llx_cabinetmed_cons_extrafields
--ignore-table=$base.llx_cabinetmed_diaglec
--ignore-table=$base.llx_cabinetmed_examaut
@@ -269,6 +275,7 @@ export list="
--ignore-table=$base.llx_congespayes_events
--ignore-table=$base.llx_congespayes_logs
--ignore-table=$base.llx_congespayes_users
--ignore-table=$base.llx_deplacement
--ignore-table=$base.llx_dolicloud_customers
--ignore-table=$base.llx_dolicloud_stats
--ignore-table=$base.llx_dolicloud_emailstemplates
@@ -345,20 +352,24 @@ 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 -p***** $list $base > $mydir/$dumpfile"
echo "mysqldump -P$port -u$admin $passwdshown $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 loaded."
echo "Success, file successfully dumped."
else
echo "Error, load failed."
echo "Error, dump failed."
fi
echo

View File

@@ -36,6 +36,7 @@ $confirm = isset($argv[1]) ? $argv[1] : '';
// Include Dolibarr environment
$res = 0;
$reg = array();
if (!$res && file_exists($path."../../master.inc.php")) {
$res = @include $path."../../master.inc.php";
}
@@ -60,24 +61,32 @@ if (!$res && preg_match('/\/nltechno([^\/]*)\//', $_SERVER["PHP_SELF"], $reg)) {
if (!$res) {
die("Failed to include master.inc.php file\n");
}
/**
* @var DoliDB $db
*/
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
include_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
/*
* Main
*/
print "***** ".$script_file." *****\n";
print "Update dates to current year for database name = ".$db->database_name."\n";
print "***** ".$script_file." ".$confirm." *****\n";
if (empty($confirm)) {
print "Usage: $script_file confirm\n";
print "Usage: $script_file confirm|confirmresetblockedlog\n";
print "Return code: 0 if success, <>0 if error\n";
exit(1);
}
$tmp = dol_getdate(dol_now());
$dolnow = dol_now();
// Current year
$tmp = dol_getdate($dolnow);
$year = 2010; // Old year in demo
$lastyear = $tmp['year'] - 2; // New year in demo
$tables = array(
'propal' => array(0 => 'datep', 1 => 'fin_validite', 2 => 'date_valid', 3 => 'date_cloture'),
@@ -92,55 +101,312 @@ $tables = array(
'ticket' => array(0 => 'datec', 1 => 'date_read', 2 => 'date_close')
);
$year = 2010;
$currentyear = $tmp['year'];
while ($year <= $currentyear) {
//$year=2021;
$delta1 = ($currentyear - $year);
$delta2 = ($currentyear - $year - 1);
//$delta=-1;
if ($delta1) {
foreach ($tables as $tablekey => $tableval) {
print "Correct ".$tablekey." for year ".$year." and move them to current year ".$currentyear." ";
$sql = "select rowid from ".MAIN_DB_PREFIX.$tablekey." where ".$tableval[0]." between '".$year."-01-01' and '".$year."-12-31' and ".$tableval[0]." < DATE_ADD(NOW(), INTERVAL -1 YEAR)";
//$sql="select rowid from ".MAIN_DB_PREFIX.$tablekey." where ".$tableval[0]." between '".$year."-01-01' and '".$year."-12-31' and ".$tableval[0]." > NOW()";
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
if ($obj) {
print ".";
$sql2 = "UPDATE ".MAIN_DB_PREFIX.$tablekey." set ";
$j = 0;
foreach ($tableval as $field) {
if ($j) {
$sql2 .= ", ";
}
$sql2 .= $field." = ".$db->ifsql("DATE_ADD(".$field.", INTERVAL ".$delta1." YEAR) > NOW()", "DATE_ADD(".$field.", INTERVAL ".$delta2." YEAR)", "DATE_ADD(".$field.", INTERVAL ".$delta1." YEAR)");
$j++;
}
$sql2 .= " WHERE rowid = ".$obj->rowid;
//print $sql2."\n";
$resql2 = $db->query($sql2);
if (!$resql2) {
dol_print_error($db);
}
}
$i++;
}
} else {
dol_print_error($db);
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'];
}
print "\n";
$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');
}
$year++;
$db->commit();
}
if ($confirm == 'confirm') {
print "Update dates to current year for database name = ".$db->database_name."\n";
// Upgrade dates from 2010 to current year - 2.
while ($year <= $lastyear) {
//$year=2021;
$delta1 = ($lastyear - $year);
$delta2 = ($lastyear - $year - 1);
//$delta=-1;
if ($delta1) {
foreach ($tables as $tablekey => $tableval) {
print "Correct ".$tablekey." for year ".$year." and move them to current year ".$lastyear." ";
$sql = "select rowid from ".MAIN_DB_PREFIX.$tablekey." where ".$tableval[0]." between '".$year."-01-01' and '".$year."-12-31' and ".$tableval[0]." < DATE_ADD(NOW(), INTERVAL -1 YEAR)";
//$sql="select rowid from ".MAIN_DB_PREFIX.$tablekey." where ".$tableval[0]." between '".$year."-01-01' and '".$year."-12-31' and ".$tableval[0]." > NOW()";
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
if ($obj) {
print ".";
$sql2 = "UPDATE ".MAIN_DB_PREFIX.$tablekey." set ";
$j = 0;
foreach ($tableval as $field) {
if ($j) {
$sql2 .= ", ";
}
$sql2 .= $field." = ".$db->ifsql("DATE_ADD(".$field.", INTERVAL ".$delta1." YEAR) > NOW()", "DATE_ADD(".$field.", INTERVAL ".$delta2." YEAR)", "DATE_ADD(".$field.", INTERVAL ".$delta1." YEAR)");
$j++;
}
$sql2 .= " WHERE rowid = ".$obj->rowid;
//print $sql2."\n";
$resql2 = $db->query($sql2);
if (!$resql2) {
dol_print_error($db);
}
}
$i++;
}
} else {
dol_print_error($db);
}
print "\n";
}
}
$year++;
}
}
if ($confirm == 'confirmresetblockedlog') {
$year = $tmp['year']; // Old year in demo
$lastyear = $tmp['year'] - 2; // New year in demo
// Upgrade dates from current year to current year - 2.
while ($year >= $lastyear) {
//$year=2021;
$delta1 = ($lastyear - $year); // negative value
$delta2 = ($lastyear - $year - 1); // negative value
//$delta=-1;
if ($delta1) {
foreach ($tables as $tablekey => $tableval) {
print "Correct ".$tablekey." for year ".$year." and move them to current year ".$lastyear." ";
$sql = "select rowid from ".MAIN_DB_PREFIX.$tablekey." where ".$tableval[0]." between '".$year."-01-01' and '".$year."-12-31'";
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
if ($obj) {
print ".";
$sql2 = "UPDATE ".MAIN_DB_PREFIX.$tablekey." set ";
$j = 0;
foreach ($tableval as $field) {
if ($j) {
$sql2 .= ", ";
}
$sql2 .= $field." = DATE_ADD(".$field.", INTERVAL ".$delta1." YEAR)";
$j++;
}
$sql2 .= " WHERE rowid = ".$obj->rowid;
//print $sql2."\n";
$resql2 = $db->query($sql2);
if (!$resql2) {
dol_print_error($db);
}
}
$i++;
}
} else {
dol_print_error($db);
}
print "\n";
}
}
$year--;
}
$sql = "CREATE TABLE tmp_delete (SELECT pf.fk_paiement FROM llx_paiement_facture as pf WHERE pf.fk_facture IN (SELECT f.rowid FROM llx_facture as f WHERE f.datef < '2024-12-31'))";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."paiement_facture WHERE fk_paiement IN (SELECT fk_paiement FROM tmp_delete)";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."paiement WHERE rowid IN (SELECT fk_paiement FROM tmp_delete)";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."facturedet as fd WHERE fd.fk_facture IN (SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE datef < '".$lastyear."-12-31')";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."facture WHERE datef < '".$lastyear."-12-31'";
print $sql;
print "\n";
$db->query($sql);
$sql = "DROP TABLE tmp_delete";
print $sql;
print "\n";
$db->query($sql);
$sql = "UPDATE ".MAIN_DB_PREFIX."facture SET datef = datec";
print $sql;
print "\n";
$db->query($sql);
$sql = "UPDATE ".MAIN_DB_PREFIX."paiement as p SET datep = (SELECT datef FROM ".MAIN_DB_PREFIX."facture as f WHERE f.rowid = (SELECT fk_facture FROM ".MAIN_DB_PREFIX."paiement_facture as pf WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = f.rowid) LIMIT 1)";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog";
print $sql;
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_%'";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog WHERE rowid < 199";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog WHERE action LIKE 'MODULE_RESET'";
print $sql;
print "\n";
$db->query($sql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog";
print $sql;
print "\n";
$db->query($sql);
$sql = "UPDATE ".MAIN_DB_PREFIX."blockedlog SET date_creation = tms WHERE date_creation <> tms";
print $sql;
print "\n";
$sql = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog WHERE date_creation > '".dol_print_date($dolnow, 'day')."'";
print $sql;
print "\n";
$db->query($sql);
$sql = "UPDATE ".MAIN_DB_PREFIX."blockedlog SET debuginfo = NULL WHERE debuginfo IS NOT NULL";
print $sql;
print "\n";
$db->query($sql);
*/
}
print "\n";
exit(0);

View File

@@ -60,7 +60,7 @@
Require all granted
</Directory>
# You may also want to allow access to everyone to wrappers for api, document, viewimage, manifest and public json/img
# You may also want to allow access to everyone to wrappers for api, document, viewimage, manifest and public json/img files
# but if you can avoid it, it is better.
<Files /home/admin/wwwroot/dolibarr/htdocs/api/index.php>
AuthType None

View File

@@ -0,0 +1,103 @@
<?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

@@ -0,0 +1,112 @@
<?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,6 +21,11 @@
<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 -->
@@ -31,12 +36,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">
@@ -76,16 +81,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 IP making too much tries.
# Regexp to detect try to check a couple login/password so we can add mitigation on IPs 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-dol-bruteforce
# fail2ban-client status web-dolibarr-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,6 +7,7 @@
# 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
@@ -14,5 +15,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,7 +6,8 @@
[Definition]
# To test, you can inject this example into 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
# 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
#
# then
# fail2ban-client status web-dolibarr-limitpublic
@@ -14,5 +15,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,7 +6,8 @@
[Definition]
# To test, you can inject this example into 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
# 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
#
# then
# fail2ban-client status web-dolibarr-passf
@@ -14,5 +15,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

@@ -883,7 +883,7 @@ foreach ($arrayofalerts as $key => $alert) {
// VDP ID
$html .= '<td style="white-space: nowrap">';
if (!empty($alert['issueidvdp'])) {
$html .= '#vdp'.$alert['issueidvdp'];
$html .= '#'.$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'] = $reg[1];
if (preg_match('/#(yogosha\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];
if (preg_match('/#(ghsa[a-z\-\d]+)/i', $tmpval['title'], $reg)) {
$tmpval['issueidvdp'] = strtolower($reg[1]);
}
return $tmpval;

View File

@@ -9,19 +9,18 @@
*/
return [
// # Issue statistics:
// PhanUndeclaredProperty : 410+ occurrences
// PhanTypeMismatchArgument : 65+ occurrences
// PhanUndeclaredGlobalVariable : 60+ occurrences
// PhanTypeMismatchArgumentNullable : 20+ occurrences
// PhanUndeclaredProperty : 400+ occurrences
// PhanTypeMismatchArgument : 60+ occurrences
// PhanUndeclaredGlobalVariable : 50+ occurrences
// PhanTypeMismatchProperty : 20+ occurrences
// PhanTypeInvalidDimOffset : 15+ occurrences
// PhanTypeInvalidDimOffset : 10+ 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
@@ -30,7 +29,6 @@ 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'],
@@ -41,16 +39,12 @@ 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'],
@@ -59,7 +53,6 @@ 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'],
@@ -76,7 +69,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' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonobject.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'],
'htdocs/core/class/commonpeople.class.php' => ['PhanUndeclaredProperty'],
'htdocs/core/class/conf.class.php' => ['PhanTypeMismatchProperty'],
'htdocs/core/class/ctyperesource.class.php' => ['PhanUndeclaredProperty'],
@@ -101,38 +94,32 @@ 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' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'],
'htdocs/core/modules/commande/doc/pdf_einstein.modules.php' => ['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', 'PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/delivery/doc/pdf_storm.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/delivery/doc/pdf_typhon.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/contract/doc/pdf_strato.modules.php' => ['PhanTypeMismatchArgument'],
'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', 'PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expedition/doc/pdf_merou.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expedition/doc/pdf_rouget.modules.php' => ['PhanTypeMismatchArgumentNullable'],
'htdocs/core/modules/expedition/doc/pdf_espadon.modules.php' => ['PhanTypeMismatchArgument'],
'htdocs/core/modules/expensereport/doc/pdf_standard_expensereport.modules.php' => ['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/facture/doc/pdf_octopus.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'],
'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' => ['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/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/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' => ['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/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/syslog/mod_syslog_file.php' => ['PhanPluginDuplicateArrayKey'],
'htdocs/core/modules/workstation/mod_workstation_advanced.php' => ['PhanUndeclaredProperty'],
'htdocs/core/multicompany_page.php' => ['PhanTypeMismatchArgument'],
@@ -146,7 +133,6 @@ 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'],
@@ -235,16 +221,15 @@ return [
'htdocs/salaries/virement_request.php' => ['PhanUndeclaredProperty'],
'htdocs/societe/ajax/company.php' => ['PhanUndeclaredProperty'],
'htdocs/societe/class/societe.class.php' => ['PhanTypeMismatchProperty'],
'htdocs/societe/paymentmodes.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgument'],
'htdocs/societe/paymentmodes.php' => ['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' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'],
'htdocs/takepos/invoice.php' => ['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'],
@@ -253,7 +238,6 @@ 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,6 +227,24 @@ 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',
@@ -439,6 +457,7 @@ 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,6 +74,7 @@ $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,6 +76,8 @@ 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

@@ -939,7 +939,6 @@ Don
ECM
EmptyMessageNotAllowedError
ErrorInputRequired
ErrorLDAPFunctionsAreDisabledOnThisPHP
ErrorUpdating
Extra
FailedToConnectToSFTPAfterSSHAuthentication
@@ -1014,7 +1013,6 @@ TicketMessageMailSignatureText
TicketSetupPage
Timeline
Transfer
TryAnotherConnectionMode
UndefinedKey
UnknownType
UpdateMember

View File

@@ -23,7 +23,7 @@
# - Some side effects from translations on variables.
# - Some other minors side effects to be examined (#, %).
#
# Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
# Copyright (C) 2024-2026 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

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2016-2018 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
@@ -27,11 +27,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -39,6 +34,10 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
// Load translation files required by the page
$langs->loadLangs(array('accountancy', 'admin', 'bills', 'compta', 'salaries'));
@@ -260,6 +259,9 @@ 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";
@@ -440,7 +442,9 @@ if ($resql) {
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="page_y" value="">';
// @phan-suppress-next-line PhanPluginSuspiciousParamOrder
print_barre_liste($langs->trans('ListAccounts'), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'accounting_account', 0, $newcardbutton, '', $limit, 0, 0, 1);
@@ -467,7 +471,7 @@ if ($resql) {
$obj = $db->fetch_object($resqlchart);
if ($obj) {
$labeltoshow = $obj->country_code.' - '.$obj->pcg_version.' - '.$obj->label;
$htmltoshow = picto_from_langcode($obj->country_code).' '.$obj->country_code.' - '.$obj->pcg_version.' - '.$obj->label;
$htmltoshow = picto_from_langcode($obj->country_code).' '.$obj->country_code.' - '.$obj->pcg_version.' <span class="opacitymedium">- '.$obj->label.'</span>';
print '<option value="'.$obj->rowid.'" data-html="'.dolPrintHTMLForAttribute($htmltoshow).'"';
print ($pcgver == $obj->rowid) ? ' selected' : '';
print '>'.$labeltoshow.'</option>';
@@ -760,9 +764,31 @@ if ($resql) {
}
// Custom accounts
if (!empty($arrayfields['categories']['checked'])) {
print '<td class="right">';
// TODO Get all custom groups labels the account is in
print dol_escape_htmltag($obj->fk_accounting_category);
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>\n";
if (!$i) {
$totalarray['nbfield']++;
@@ -842,11 +868,11 @@ if ($resql) {
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="center nowraponall">';
// if ($permissiontoadd) { // test is always true
print '<a class="editfielda" href="./card.php?action=update&token='.newToken().'&id='.$obj->rowid.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?'.$param).'">';
print '<a class="editfielda" href="./card.php?action=update&token='.newToken().'&id='.$obj->rowid.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?'.$param.'&page='.$page).'">';
print img_edit();
print '</a>';
print '&nbsp;';
print '<a class="marginleftonly" href="./card.php?action=delete&token='.newToken().'&id='.$obj->rowid.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?'.$param).'">';
print '<a class="marginleftonly" href="./card.php?action=delete&token='.newToken().'&id='.$obj->rowid.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?'.$param.'&page='.$page).'">';
print img_delete();
print '</a>';
print '&nbsp;';

View File

@@ -8,11 +8,11 @@
* Copyright (C) 2011 Remy Younes <ryounes@gmail.com>
* Copyright (C) 2012-2015 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@ltairis.fr>
* Copyright (C) 2011-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* 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 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -196,7 +196,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("Country")), null, 'errors');
}
// Si verif ok et action add, on ajoute la ligne
// In case of 'actionadd' and with valid parameters, add the line
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -241,11 +241,11 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// Si verif ok et action modify, on modifie la ligne
// In case of 'actionmodify' and with valid parameters, modify the line
if ($ok && GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modifie valeur des champs
// Change field's value
$i = 0;
foreach ($listfieldmodify as $field) {
@@ -268,7 +268,6 @@ 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');
@@ -327,13 +326,13 @@ $linkback = '';
print load_fiche_titre($titre, $linkback, 'title_accountancy');
// Confirmation de la suppression de la ligne
// Confirmation of line deletion
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 requete recherche valeurs avec critere de tri
// Complete the values search query with the sort order
$sql = $tabsql[$id];
if ($search_country_id > 0) {
@@ -351,7 +350,6 @@ if ($sortfield == 'country') {
}
$sql .= $db->order($sortfield, $sortorder);
$sql .= $db->plimit($listlimit + 1, $offset);
//print $sql;
$fieldlist = explode(',', $tabfield[$id]);
@@ -368,8 +366,8 @@ $fieldlist = explode(',', $tabfield[$id]);
// Line for title
print '<tr class="liste_titre">';
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
// Determine the field name based on the possible names
// in the data dictionaries
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$class = "left";
@@ -393,7 +391,6 @@ 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.'">';
@@ -588,8 +585,7 @@ if ($resql) {
'page' => $page,
'sortfield' => $sortfield,
'sortorder' => $sortorder,
'rowid' => (!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')),
'code' => $obj->code,
'rowid' => (!empty($obj->rowid) ? $obj->rowid : '')
]);
// Active

View File

@@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
@@ -72,7 +72,7 @@ $object = new AccountingAccount($db);
*/
if (GETPOST('cancel', 'alpha')) {
$urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
$urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
header("Location: ".$urltogo);
exit;
}
@@ -126,7 +126,7 @@ if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // al
}
if (!$error) {
setEventMessages("RecordCreatedSuccessfully", null, 'mesgs');
$urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
$urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
header("Location: " . $urltogo);
exit;
}
@@ -169,7 +169,7 @@ if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // al
$result = $object->update($user);
if ($result > 0) {
$urltogo = $backtopage ? $backtopage : ($_SERVER["PHP_SELF"] . "?id=" . $id);
$urltogo = (!empty($backtopage) ? $backtopage : ($_SERVER["PHP_SELF"] . "?id=" . $id));
header("Location: " . $urltogo);
exit();
} elseif ($result == -2) {
@@ -179,7 +179,7 @@ if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // al
}
}
} else {
$urltogo = $backtopage ? $backtopage : ($_SERVER["PHP_SELF"]."?id=".$id);
$urltogo = (!empty($backtopage) ? $backtopage : ($_SERVER["PHP_SELF"]."?id=".$id));
header("Location: ".$urltogo);
exit();
}
@@ -190,7 +190,8 @@ if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // al
$result = $object->delete($user);
if ($result > 0) {
header("Location: account.php");
$urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
header("Location: ".$urltogo);
exit;
}
}

View File

@@ -1,9 +1,9 @@
<?php
/* 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>
/* 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>
*
* 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,9 +27,6 @@
// 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
@@ -39,187 +36,399 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.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("bills", "accountancy", "compta"));
$langs->loadLangs(array("accountancy", "admin", "bills", "compta"));
$id = GETPOSTINT('id');
$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';
$confirm = GETPOST('confirm', 'alpha');
$id = GETPOSTINT('id');
$catid = GETPOSTINT('catid'); // Alternative parameter name for consistency
if (empty($id) && !empty($catid)) {
$id = $catid;
}
$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 we add account
if (!empty($selectcpt)) {
$cpts = array();
foreach ($selectcpt as $selectedoption) {
if (!array_key_exists($selectedoption, $cpts)) {
$cpts[$selectedoption] = "'".$selectedoption."'";
}
if ($useNewSystem) {
// Remove filter
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
$search_account = '';
$search_label = '';
}
$return = $accountingcategory->updateAccAcc((int) $cat_id, $cpts);
// Add account to category
if ($action == 'add_account' && !empty($account_id)) {
$result = $accountingcategory->addAccountToCategory($account_id);
if ($return < 0) {
setEventMessages($langs->trans('errors'), $accountingcategory->errors, 'errors');
} else {
setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
}
}
if ($action == 'delete') {
if ($cpt_id) {
if ($accountingcategory->deleteCptCat($cpt_id)) {
setEventMessages($langs->trans('AccountRemovedFromGroup'), null, 'mesgs');
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($langs->trans('errors'), null, 'errors');
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
}
}
// Remove account from category
if ($action == 'confirm_delete' && $confirm == 'yes' && !empty($account_id)) {
$result = $accountingcategory->deleteAccountFromCategory($account_id);
if ($result > 0) {
setEventMessages($langs->trans("AccountRemovedFromCategory"), null, 'mesgs');
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit;
} else {
setEventMessages($accountingcategory->error, $accountingcategory->errors, 'errors');
}
}
// 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');
} 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');
}
}
}
/*
* View
*/
$form = new Form($db);
$formaccounting = new FormAccounting($db);
$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');
$title = $langs->trans('AccountingCategory');
$help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilit&eacute;_en_Partie_Double#Configuration';
if ($useNewSystem) {
// ============================================================================
// NEW SYSTEM VIEW
// ============================================================================
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin_categories');
$linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories_list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$titlepicto = 'setup';
print load_fiche_titre($langs->trans('AccountingCategory'), $linkback, $titlepicto);
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 dol_get_fiche_head();
print '<table class="border centpercent">';
// 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 {
print $s;
print '<input type="submit" class="button small" value="'.$langs->trans("Select").'">';
}
print '</td></tr>';
print '</table>';
print dol_get_fiche_end();
// Select the accounts
if (!empty($cat_id)) {
$return = $accountingcategory->getAccountsWithNoCategory($cat_id);
if ($return < 0) {
setEventMessages(null, $accountingcategory->errors, 'errors');
}
print '<br>';
$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 : '');
// 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
);
}
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").'"> ';
if ($action == 'remove_all') {
print $form->formconfirm(
$_SERVER["PHP_SELF"].'?id='.$id,
$langs->trans('RemoveAllAccountsFromCategory'),
$langs->trans('ConfirmRemoveAllAccountsFromCategory'),
'confirm_remove_all',
'',
0,
1
);
}
}
print '</form>';
// Page title
$title = $langs->trans("AccountingCategory").': '.$accountingcategory->label;
print load_fiche_titre($title, '', 'title_accountancy');
// Category information card
print dol_get_fiche_head();
if ((empty($action) || $action == 'display' || $action == 'delete') && $cat_id > 0) {
$param = 'account_category='.((int) $cat_id);
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 '<br>';
print '<table class="noborder centpercent">'."\n";
print dol_get_fiche_end();
// 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 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";
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>';
if (!empty($cat_id)) {
$return = $accountingcategory->display($cat_id); // This load ->lines_display
if ($return < 0) {
setEventMessages(null, $accountingcategory->errors, 'errors');
}
// 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>';
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);
// Data rows
$i = 0;
while ($i < min($num, $limit)) {
$obj = $db->fetch_object($resql);
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 '<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++;
}
print "</table>";
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>';
}
} else {
// ============================================================================
// OLD SYSTEM VIEW (compatibility)
// ============================================================================
$listcpt = $accountingcategory->display($id);
$listcptNotIn = $accountingcategory->getAccountsWithNoCategory($id);
print load_fiche_titre($langs->trans('AccountingCategory')." : ".$accountingcategory->label);
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";
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>';
}
print '</table>';
print '</form>';
}
// End of page

View File

@@ -1,8 +1,8 @@
<?php
/* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* 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>
* 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>
*
* 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,14 +26,6 @@
// 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
@@ -43,6 +35,16 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.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"));
@@ -70,7 +72,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_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
if (empty($page) || $page < 0 || GETPOST('button_refresh', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
// If $page is not defined, or '' or -1 or if we click on clear filters
$page = 0;
}
@@ -80,6 +82,22 @@ $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'));
@@ -99,7 +117,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_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_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').")";
// Criteria to sort dictionaries
$tabsqlsort = array();
@@ -147,6 +165,12 @@ $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
@@ -209,7 +233,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors');
}
// Si verif ok et action add, on ajoute la ligne
// In case of 'actionadd' and with valid parameters, add the line
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -280,7 +304,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modifie valeur des champs
// Modify field values
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
@@ -426,6 +450,71 @@ 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);
@@ -443,6 +532,15 @@ 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';
@@ -461,6 +559,9 @@ $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);
@@ -493,8 +594,8 @@ if ($tabname[$id]) {
print '<td></td>';
}
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
// Determine the field name based on the possible names
// in the data dictionaries.
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$class = "left";
@@ -889,11 +990,18 @@ if ($resql) {
print '<td>';
if (empty($obj->formula)) {
// Count number of accounts into group
$nbofaccountintogroup = 0;
$listofaccountintogroup = $accountingcategory->getCptsCat($obj->rowid);
$nbofaccountintogroup = count($listofaccountintogroup);
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);
}
print '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories.php?action=display&save_lastsearch_values=1&account_category='.$obj->rowid.'">';
print '<a href="'.DOL_URL_ROOT.'/accountancy/admin/categories.php?id='.$obj->rowid.'">';
print $langs->trans("NAccounts", $nbofaccountintogroup);
print '</a>';
} else {
@@ -902,7 +1010,7 @@ if ($resql) {
print '</td>';
// Active
print '<td class="center" class="nowrap">';
print '<td class="center nowrap">';
if ($canbedisabled) {
print '<a class="reposition" href="'.$url.'action='.urlencode($acts[$obj->active]).'&token='.newToken().'">'.$actl[$obj->active].'</a>';
} else {

View File

@@ -24,11 +24,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -36,6 +31,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
$action = GETPOST('action', 'aZ09');
@@ -123,7 +121,8 @@ llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-adm
$sql = "SELECT f.rowid, f.label, f.date_start, f.date_end, f.statut as status, f.entity";
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_fiscalyear as f";
$sql .= " WHERE f.entity = ".$conf->entity;
$sql .= " WHERE f.entity = ".((int) $conf->entity);
$sql .= $db->order($sortfield, $sortorder);
// Count total nb of records

View File

@@ -25,10 +25,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/fiscalyear.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -36,13 +32,15 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/fiscalyear.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "compta"));
// Get parameters
$id = GETPOSTINT('id');
$ref = GETPOST('ref', 'alpha');
$ref = GETPOST('ref', 'alpha') ? GETPOST('ref', 'alpha') : GETPOST('label', 'alpha');
$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
@@ -62,17 +60,16 @@ $extrafields = new ExtraFields($db);
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
// List of status
/*
static $tmpstatus2label = array(
'0' => 'OpenFiscalYear',
'1' => 'CloseFiscalYear'
);
$status2label = array(
'' => ''
'0' => 'OpenFiscalYear',
'1' => 'CloseFiscalYear'
);
$status2label = array('' => '');
foreach ($tmpstatus2label as $key => $val) {
$status2label[$key] = $langs->trans($val);
}
*/
$date_start = dol_mktime(0, 0, 0, GETPOSTINT('fiscalyearmonth'), GETPOSTINT('fiscalyearday'), GETPOSTINT('fiscalyearyear'));
$date_end = dol_mktime(0, 0, 0, GETPOSTINT('fiscalyearendmonth'), GETPOSTINT('fiscalyearendday'), GETPOSTINT('fiscalyearendyear'));
@@ -128,16 +125,19 @@ if ($action == 'confirm_delete' && $confirm == "yes" /* && $permissiontoadd // a
$db->begin();
$id = $object->create($user);
if ($id > 0) {
$db->commit();
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit();
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
exit;
} else {
$db->rollback();
setEventMessages($object->error, $object->errors, 'errors');
// Handle overlap error
if ($id == -5 && !empty($object->errors[0])) {
setEventMessages($langs->trans($object->error, $object->errors[0]), null, 'errors');
} else {
setEventMessages($object->error, $object->errors, 'errors');
}
$action = 'create';
}
} else {
@@ -145,7 +145,7 @@ if ($action == 'confirm_delete' && $confirm == "yes" /* && $permissiontoadd // a
}
} else {
header("Location: ./fiscalyear.php");
exit();
exit;
}
} elseif ($action == 'update' /* && $permissiontoadd // always true */) {
// Update record
@@ -158,16 +158,20 @@ if ($action == 'confirm_delete' && $confirm == "yes" /* && $permissiontoadd // a
$object->status = GETPOSTINT('status');
$result = $object->update($user);
if ($result > 0) {
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit();
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
exit;
} else {
setEventMessages($object->error, $object->errors, 'errors');
// Handle overlap error
if ($result == -5 && !empty($object->errors[0])) {
setEventMessages($langs->trans($object->error, $object->errors[0]), null, 'errors');
} else {
setEventMessages($object->error, $object->errors, 'errors');
}
}
} else {
header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
exit();
header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
exit;
}
} elseif ($action == 'reopen' /* && $permissiontoadd // always true */ && getDolGlobalString('ACCOUNTING_CAN_REOPEN_CLOSED_PERIOD')) {
$result = $object->fetch($id);
@@ -343,6 +347,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '<div class="fichecenter">';
print '<div class="fichehalfleft">';
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">'."\n";
// Id
@@ -373,6 +378,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '</td></tr>';
print '</table>';
print '</div>';
print '</div>';

View File

@@ -24,10 +24,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/fiscalyear.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -35,10 +31,21 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/fiscalyear.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "compta"));
$id = GETPOSTINT('id');
$ref = GETPOST('ref', 'alpha') ? GETPOST('ref', 'alpha') : GETPOST('label', 'alpha');
$object = new Fiscalyear($db);
// Load object
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
// Security check
if ($user->socid > 0) {
accessforbidden();
@@ -47,10 +54,17 @@ if (!$user->hasRight('accounting', 'fiscalyear', 'write')) {
accessforbidden();
}
$id = GETPOSTINT('id');
/*
* Actions
*/
// None
// View
/*
* View
*/
$title = $langs->trans("Fiscalyear")." - ".$langs->trans("Info");
@@ -59,19 +73,18 @@ $help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilit&eacut
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin_fiscalyear_info');
if ($id) {
$object = new Fiscalyear($db);
$object->fetch($id);
$object->info($id);
$head = fiscalyear_prepare_head($object);
print dol_get_fiche_head($head, 'info', $langs->trans("Fiscalyear"), -1, $object->picto);
print dol_get_fiche_head($head, 'info', $langs->trans("Fiscalyear"), -1, $object->picto, 0, '', '', 0, '', 1);
$linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/fiscalyear.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
$morehtmlref = '';
dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
dol_banner_tab($object, 'label', $linkback, 1, 'label', 'label', $morehtmlref);
print '<div class="fichecenter">';
print '<div class="underbanner clearboth"></div>';

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2014-2015 Ari Elbaz (elarifr) <github@accedinfo.com>
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
@@ -32,13 +32,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -47,6 +40,12 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
// Load translation files required by the page
$langs->loadLangs(array("compta", "bills", "admin", "accountancy", "other"));
@@ -482,33 +481,28 @@ print '<br>';
// Case of the parameter ACCOUNTING_MODE
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="updatemode">';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 1) {
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="updatemode">';
print '<table class="noborder centpercent">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans('OptionMode').'</td>';
print "</tr>\n";
print '<tr class="oddeven"><td class="nowraponall"><input type="radio" id="accounting_mode_1" name="accounting_mode" value="CREANCES-DETTES"'.($accounting_mode != 'RECETTES-DEPENSES' ? ' checked' : '').'><label for="accounting_mode_1"> '.$langs->trans('OptionModeVirtual').'</label> ('.$langs->trans('Default').')</td>';
print '<td><span class="opacitymedium">'.nl2br($langs->trans('ACCOUNTING_USE_NON_TREASURY_Desc')).'</span>';
print "</td></tr>\n";
print '<tr class="oddeven"><td class="nowraponall"><input type="radio" id="accounting_mode_2" name="accounting_mode" value="RECETTES-DEPENSES"'.($accounting_mode == 'RECETTES-DEPENSES' ? ' checked' : '').'><label for="accounting_mode_2"> '.$langs->trans('OptionModeTrue').'</label></td>';
print '<td><span class="opacitymedium">'.nl2br($langs->trans('ACCOUNTING_USE_TREASURY_Desc'))."</span>";
print "</td></tr>\n";
print '<tr class="liste_titre">';
print '<td colspan="2">'.$langs->trans('OptionMode').'</td>';
print "</tr>\n";
print '<tr class="oddeven"><td class="nowraponall"><input type="radio" id="accounting_mode_1" name="accounting_mode" value="CREANCES-DETTES"'.($accounting_mode != 'RECETTES-DEPENSES' ? ' checked' : '').'><label for="accounting_mode_1"> '.$langs->trans('OptionModeVirtual').'</label> ('.$langs->trans('Default').')</td>';
print '<td><span class="opacitymedium">'.nl2br($langs->trans('ACCOUNTING_USE_NON_TREASURY_Desc')).'</span>';
print "</td></tr>\n";
print '<tr class="oddeven"><td class="nowraponall"><input type="radio" id="accounting_mode_2" name="accounting_mode" value="RECETTES-DEPENSES"'.($accounting_mode == 'RECETTES-DEPENSES' ? ' checked' : '').'><label for="accounting_mode_2"> '.$langs->trans('OptionModeTrue').'</label></td>';
print '<td><span class="opacitymedium">'.nl2br($langs->trans('ACCOUNTING_USE_TREASURY_Desc'))."</span>";
print "</td></tr>\n";
print "</table>\n";
print "</table>\n";
print '<div class="center"><input type="submit" class="button button-edit" name="button" value="'.$langs->trans('Save').'"></div>';
print '</form>';
print '<br><br>';
}
print '<div class="center"><input type="submit" class="button button-edit" name="button" value="'.$langs->trans('Save').'"></div>';
print '</form>';
print '<br><br>';
// Show form main options
print $formSetup->generateOutput(true);
@@ -660,7 +654,7 @@ print '</form>';
print '<br><br>';
// Accountancy Numbering model
$dirmodels = array_merge(array('/'), $conf->modules_parts['models']);
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2017-2024 Alexandre Spangaro <aspangaro@easya.solutions>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -194,7 +194,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
$ok = 0;
}
// Si verif ok et action add, on ajoute la ligne
// In case of 'actionadd' and with valid parameters, add the line
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')) {
}
}
// Si verif ok et action modify, on modifie la ligne
// If check ok and action modify, we modify the line
if ($ok && GETPOST('actionmodify', 'alpha')) {
if ($tabrowid[$id]) {
$rowidcol = $tabrowid[$id];
@@ -261,7 +261,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modifie valeur des champs
// Modify the field values
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);
// Confirmation de la suppression de la ligne
// Generate a form to confirm the deletion of the row
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 requete recherche valeurs avec critere de tri
// Complete the search query with sort criteria
$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 le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
// Determine the field name based on the possible names
// in the data dictionaries.
$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 le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
// Determine the field name based on the possible names
// in the data dictionaries.
$class = "left";
$sortable = 1;
$valuetoshow = '';

View File

@@ -552,10 +552,12 @@ 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);
}
@@ -563,7 +565,7 @@ if ($resql) {
$moreforfilter = '';
if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
$formcategory = new FormCategory($db);
$moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PRODUCT, $searchCategoryProductList, 'minwidth300', $searchCategoryProductList ? $searchCategoryProductList : 0);
$moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PRODUCT, $searchCategoryProductList, 'minwidth300', $searchCategoryProductList ? $searchCategoryProductOperator : 0);
}
// Show/hide child products. Hidden by default
@@ -662,7 +664,7 @@ if ($resql) {
while ($i < min($num, $limit)) {
$obj = $db->fetch_object($resql);
// Ref produit as link
// Product ref as link
$product_static->ref = $obj->ref;
$product_static->id = $obj->rowid;
$product_static->type = $obj->product_type;
@@ -907,49 +909,48 @@ 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")
print '<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++;
});
atleastoneselected=0;
jQuery(".checkforselect").each(function( index ) {
/* console.log( index + ": " + $( this ).text() ); */
if ($(this).is(\':checked\')) atleastoneselected++;
});
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');
}
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());
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>';
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
print '</form>';

View File

@@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -183,7 +184,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
}
}
// Si verif ok et action add, on ajoute la ligne
// In case of 'actionadd' and with valid parameters, add the line
if ($ok && GETPOST('actionadd', 'alpha')) {
$newid = 0;
@@ -254,7 +255,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
// Modify entry
$sql = "UPDATE ".$db->sanitize($tabname[$id])." SET ";
// Modifie valeur des champs
// Modify field values
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $db->sanitize($tabrowid[$id])." = ";
$sql .= "'".$db->escape($rowid)."', ";
@@ -427,8 +428,8 @@ if ($tabname[$id]) {
print '<td></td>';
}
foreach ($fieldlist as $field => $value) {
// Determine le nom du champ par rapport aux noms possibles
// dans les dictionnaires de donnees
// Determine the field name based on the possible names
// in the data dictionaries.
$valuetoshow = ucfirst($fieldlist[$field]); // By default
$valuetoshow = $langs->trans($valuetoshow); // try to translate
$class = "left";

View File

@@ -0,0 +1,651 @@
<?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

@@ -0,0 +1,701 @@
<?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

@@ -235,8 +235,8 @@ if ($action == 'export' && $user->hasRight('accounting', 'mouvements', 'lire'))
if ($exportType === 'csv') {
$sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
$filename = 'balance';
$type_export = 'balance';
$filename = 'balance'; // Used by the tpl
$type_export = 'balance'; // Used by the tpl
include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
foreach ($object->lines as $line) {

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-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2026 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,9 +34,12 @@ 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
@@ -312,14 +315,79 @@ if (empty($reshook)) {
$action = 'create';
} else {
$reshook = $hookmanager->executeHooks('afterCreateBookkeeping', $parameters, $object, $action);
// Transaction created successfully
$piece_num = $object->piece_num;
if ($mode != '_tmp') {
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
// 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();
}
}
}
$action = '';
$id = $object->id;
$piece_num = (int) $object->piece_num;
// Redirect to the transaction
header("Location: ".$_SERVER["PHP_SELF"]."?piece_num=".$piece_num."&mode=_tmp");
exit;
}
}
}
@@ -569,15 +637,47 @@ 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>';
@@ -738,7 +838,38 @@ if ($action == 'create') {
print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
print '</form>';
} else {
print $object->doc_ref;
// 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 '</td>';
print '</tr>';
@@ -804,7 +935,13 @@ if ($action == 'create') {
print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
print '</form>';
} else {
print $object->code_journal;
// 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 '</td>';
print '</tr>';

View File

@@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2022 Lionel Vessiller <lvessiller@open-dsi.fr>
* Copyright (C) 2016-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
@@ -30,6 +30,13 @@
// 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.'/accountancy/class/accountancyexport.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php';
@@ -41,14 +48,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "compta"));
@@ -851,15 +850,26 @@ if ($action == 'export_file') {
|| 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');
}
$form_question['notifiedexportfull'] = array(
'name' => 'notifiedexportfull',
'type' => 'checkbox',
'label' => $langs->trans('NotifiedExportFull'),
'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, 390, 700);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").'...', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 500, 700);
}
// Print form confirm

View File

@@ -31,6 +31,13 @@
// 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.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfiscalyear.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
@@ -42,14 +49,6 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "categories", "compta", "other"));
@@ -489,6 +488,7 @@ if (empty($reshook)) {
$uploaddir = $conf->societe->dir_output;
global $error;
/** @var int $error */
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
if (!$error && $action == 'deletebookkeepingwriting' && $confirm == "yes" && $user->hasRight('accounting', 'mouvements', 'supprimer')) {
@@ -1272,17 +1272,19 @@ while ($i < min($num, $limit)) {
// Piece number
if (!empty($arrayfields['t.piece_num']['checked'])) {
print '<td>';
print '<td class="nowraponall">';
$object->id = $line->id;
$object->piece_num = $line->piece_num;
$object->ref = $line->ref;
print $object->getNomUrl(1, '', 0, '', 1);
print '<span class="hideonsmartphone">';
if (!empty($line->date_export)) {
print img_picto($langs->trans("DateExport").": ".dol_print_date($line->date_export, 'dayhour')." (".$langs->trans("TransactionExportDesc").")", 'fa-file-export', 'class="paddingleft pictofixedwidth opacitymedium"');
}
if (!empty($line->date_validation)) {
print img_picto($langs->trans("DateValidation").": ".dol_print_date($line->date_validation, 'dayhour')." (".$langs->trans("TransactionBlockedLockedDesc").")", 'fa-lock', 'class="paddingleft pictofixedwidth opacitymedium"');
}
print '</span>';
print '</td>';
if (!$i) {
$totalarray['nbfield']++;

View File

@@ -1420,17 +1420,19 @@ while ($i < min($num, $limit)) {
}
// Piece number
if (!empty($arrayfields['t.piece_num']['checked'])) {
print '<td>';
print '<td class="nowraponall">';
$object->id = $line->id;
$object->piece_num = $line->piece_num;
$object->ref = $line->ref;
print $object->getNomUrl(1, '', 0, '', 1);
print '<span class="hideonsmartphone">';
if (!empty($line->date_export)) {
print img_picto($langs->trans("DateExport").": ".dol_print_date($line->date_export, 'dayhour')." (".$langs->trans("TransactionExportDesc").")", 'fa-file-export', 'class="paddingleft pictofixedwidth opacitymedium"');
}
if (!empty($line->date_validation)) {
print img_picto($langs->trans("DateValidation").": ".dol_print_date($line->date_validation, 'dayhour')." (".$langs->trans("TransactionBlockedLockedDesc").")", 'fa-lock', 'class="paddingleft pictofixedwidth opacitymedium"');
}
print '</span>';
print '</td>';
if (!$i) {
$totalarray['nbfield']++;

View File

@@ -1,8 +1,8 @@
<?php
/* 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>
/* 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>
*
* 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,4 +906,326 @@ 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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -230,7 +230,7 @@ class AccountancyExport
);
global $hookmanager;
$code = $formatcode[$type];
$code = $formatcode[$type] ?? '';
$parameters = array('type' => $type);
$reshook = $hookmanager->executeHooks('getFormatCode', $parameters, $code);
@@ -382,12 +382,12 @@ class AccountancyExport
*/
public function export(&$TData, $formatexportset, $withAttachment = 0, $downloadMode = 1, $outputMode = 1, $noouput = 1)
{
global $db, $conf, $langs; // The tpl file use $db
global $search_date_end; // Used into /accountancy/tpl/export_journal.tpl.php
global $db, $conf, $langs; // Used into /accountancy/tpl/export_journal.tpl.php
global $search_date_end, $hookmanager; // Used into /accountancy/tpl/export_journal.tpl.php
// Define name of file to save
$filename = 'general_ledger-'.$this->getFormatCode($formatexportset);
$type_export = 'general_ledger';
$filename = 'general_ledger-'.$this->getFormatCode($formatexportset); // Used into /accountancy/tpl/export_journal.tpl.php
$type_export = 'general_ledger'; // Used into /accountancy/tpl/export_journal.tpl.php
$completefilename = '';
$exportFile = null;
@@ -422,7 +422,8 @@ class AccountancyExport
top_httphead($mimetype, 1);
}
include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
// Set var $completefilename and add HTTP header.
include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php'; // TODO Fix this: A tpl is for rendering data on output. For including common code, we must use .inc.php
if ($outputMode == 1 || $outputMode == 2) {
if ($outputMode == 1) {
@@ -902,8 +903,13 @@ class AccountancyExport
$end_line = "\r\n";
$conf->cache['archiveFileList_notfound'] = array();
// We should use dol_now function not time however this is wrong date to transfer in accounting
$i = 0;
foreach ($objectLines as $line) {
$i++;
// Clean some data
$line->doc_ref = dol_string_unaccent($line->doc_ref);
@@ -1034,12 +1040,14 @@ class AccountancyExport
$tab['num_piece3'] = str_pad(substr(self::trunc($line->doc_ref, 20), -10), 10);
$tab['reserved'] = str_repeat(' ', 10); // position 159
$tab['currency_amount'] = str_repeat(' ', 13); // position 169
// get document file
$attachmentFileName = '';
if ($withAttachment == 1) {
$attachmentFileKey = trim((string) $line->piece_num);
if (!isset($archiveFileList[$attachmentFileKey])) {
// We complete the $archiveFileList to add the file to the existing list (first entry was filled when function was called, we add here the next one)
$objectDirPath = '';
$objectFileName = dol_sanitizeFileName($line->doc_ref);
if ($line->doc_type == 'customer_invoice') {
@@ -1053,33 +1061,45 @@ class AccountancyExport
$objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
$objectDirPath .= '/'.rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
}
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = str_pad(self::trunc((string) $line->piece_num, 8), 8, '0', STR_PAD_LEFT);
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
if ($objectDirPath && empty($conf->cache['archiveFileList_notfound'][$attachmentFileKey])) {
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundPath = '';
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = str_pad(self::trunc((string) $line->piece_num, 8), 8, '0', STR_PAD_LEFT);
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
}
}
}
}
if (empty($fileFoundPath)) {
// Use also a cache if no file were found
$conf->cache['archiveFileList_notfound'][$attachmentFileKey] = 1;
}
}
}
@@ -1087,6 +1107,7 @@ class AccountancyExport
$attachmentFileName = $archiveFileList[$attachmentFileKey]['name'];
}
}
if (dol_strlen((string) $attachmentFileName) == 12) {
$tab['attachment'] = $attachmentFileName; // position 182
} else {
@@ -1370,7 +1391,7 @@ class AccountancyExport
$separator = ';';
$end_line = "\n";
// parcours du tableau pour recuperation des numero de compte des tiers pour pouvoir les fournir dans la bonne ligne pour istea
// Extract the Third party account numbers from the table to provide the correct line for ISTEA
$tiers = [];
foreach ($objectLines as $line) {
if ($line->subledger_account && substr($line->subledger_account, 0, 1) == '4') {
@@ -1462,11 +1483,16 @@ class AccountancyExport
print $output;
}
$conf->cache['archiveFileList_notfound'] = array();
$i = 0;
foreach ($objectLines as $line) {
if ($line->debit == 0 && $line->credit == 0) {
//var_dump($line->id);
//unset($array[$line]);
} else {
$i++;
$date_creation = dol_print_date($line->date_creation, '%Y%m%d');
$date_document = dol_print_date($line->doc_date, '%Y%m%d');
$date_lettering = dol_print_date($line->date_lettering, '%Y%m%d');
@@ -1475,6 +1501,8 @@ class AccountancyExport
$refInvoice = '';
$invoice = null;
// TODO The fetch of invoice is just to get the ->id, ->ref (and ->ref_supplier for supplier invoice) so
// may be we can get them into the $objectLines and reuse a generic static objectinstead ?
if ($line->doc_type == 'customer_invoice') {
// Customer invoice
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
@@ -1567,6 +1595,7 @@ class AccountancyExport
$attachmentFileKey = trim((string) $line->piece_num);
if (!isset($archiveFileList[$attachmentFileKey])) {
// We complete the $archiveFileList to add the file to the existing list (first entry was filled when function was called, we add here the next one)
$objectDirPath = '';
$objectFileName = dol_sanitizeFileName($line->doc_ref);
if ($line->doc_type == 'customer_invoice') {
@@ -1584,33 +1613,45 @@ class AccountancyExport
$objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
}
}
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = $line->doc_ref;
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
if ($objectDirPath && empty($conf->cache['archiveFileList_notfound'][$attachmentFileKey])) {
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundPath = ''; // The path of last file found
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = $line->doc_ref;
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
}
}
}
}
if (empty($fileFoundPath)) {
// Use also a cache if no file were found
$conf->cache['archiveFileList_notfound'][$attachmentFileKey] = 1;
}
}
}
@@ -1683,10 +1724,15 @@ class AccountancyExport
print $output;
}
$conf->cache['archiveFileList_notfound'] = array();
$i = 0;
foreach ($objectLines as $line) {
if ($line->debit == 0 && $line->credit == 0) {
//unset($array[$line]);
} else {
$i++;
$date_creation = dol_print_date($line->date_creation, '%Y%m%d');
$date_document = dol_print_date($line->doc_date, '%Y%m%d');
$date_lettering = dol_print_date($line->date_lettering, '%Y%m%d');
@@ -1695,6 +1741,8 @@ class AccountancyExport
$refInvoice = '';
$invoice = null;
// TODO The fetch of invoice is just to get the ->id, ->ref (and ->ref_supplier for supplier invoice) so
// may be we can get them into the $objectLines and reuse a generic static objectinstead ?
if ($line->doc_type == 'customer_invoice') {
// Customer invoice
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
@@ -1787,6 +1835,7 @@ class AccountancyExport
$attachmentFileKey = trim((string) $line->piece_num);
if (!isset($archiveFileList[$attachmentFileKey])) {
// We complete the $archiveFileList to add the file to the existing list (first entry was filled when function was called, we add here the next one)
$objectDirPath = '';
$objectFileName = dol_sanitizeFileName($line->doc_ref);
if ($line->doc_type == 'customer_invoice') {
@@ -1804,33 +1853,45 @@ class AccountancyExport
$objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
}
}
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = $line->doc_ref;
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
if ($objectDirPath && empty($conf->cache['archiveFileList_notfound'][$attachmentFileKey])) {
$arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file
$arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').(($line->doc_type == 'supplier_invoice') ? '.+' : '').'\.pdf$';
$fileFoundPath = ''; // The path of last file found
$fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, 1);
if (!empty($fileFoundList)) {
$attachmentFileNameTrunc = $line->doc_ref;
foreach ($fileFoundList as $fileFound) {
if (strstr($fileFound['name'], $objectFileName)) {
// skip native invoice pdfs (canelle)
// We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
if ($line->doc_type == 'supplier_invoice') {
if ($fileFound['name'] === $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
} elseif ($fileFound['name'] !== $objectFileName.'.pdf') {
continue;
}
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
$fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name'];
if (file_exists($fileFoundPath)) {
$archiveFileList[$attachmentFileKey] = array(
'path' => $fileFoundPath,
'name' => $attachmentFileNameTrunc.'.pdf',
);
break;
}
}
}
}
if (empty($fileFoundPath)) {
// Use also a cache if no file were found
$conf->cache['archiveFileList_notfound'][$attachmentFileKey] = 1;
}
}
}
@@ -2691,7 +2752,7 @@ class AccountancyExport
$tab[] = substr($date, 3, 2);
$tab[] = substr($date, 0, 2);
$tab[] = $line->doc_ref;
//Conversion de chaine UTF8 en Latin9
// Convert the UTF-8 string in 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 Alexandre Spangaro <alexandre@inovea-conseil.com>
/* Copyright (C) 2024-2026 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,6 +72,11 @@ 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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* 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 {
// si TVA = 0, pousser les 2 lignes view/bookkeeping déjà constituées
// When VAT = 0, push the 2 lines view/bookkeeping already prepared
if ($type == 'view') {
$element['blocks'][] = $lines_view;
} elseif ($type == 'bookkeeping') {

View File

@@ -1,11 +1,11 @@
<?php
/* Copyright (C) 2014-2017 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2015-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015-2020 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
* Copyright (C) 2025 Nicolas Barrouillet <nicolas@pragma-tech.fr>
* Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
* Copyright (C) 2025 Nicolas Barrouillet <nicolas@pragma-tech.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
@@ -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,";
$sql = "SELECT piece_num, ref, doc_date, code_journal, journal_label, doc_ref, doc_type, fk_doc,";
$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,6 +1985,7 @@ 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") {
@@ -2522,7 +2523,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');
$result = $this->loadFiscalPeriods($force, 'active'); // This set $conf->cache['active_fiscal_period_cached']
if ($result < 0) {
return null;
}
@@ -2533,9 +2534,10 @@ 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($fiscal_period['date_end'])."'";
$sql_list[$i] .= $this->db->sanitize($alias)."doc_date <= '" . $this->db->idate((int) $fiscal_period['date_end'])."'";
}
$sql_list[$i] .= ")";
$i++;
@@ -2595,6 +2597,7 @@ 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;
}
@@ -2693,6 +2696,7 @@ 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;
}
@@ -2968,11 +2972,13 @@ class BookKeeping extends CommonObject
// Current fiscal period
$fiscal_period_id = max(0, $fiscal_period_id);
if (empty($fiscal_period_id)) {
$langs->load('errors');
$this->errors[] = $langs->trans('ErrorBadParameters');
return -1;
}
$fiscal_period = new Fiscalyear($this->db);
$result = $fiscal_period->fetch($fiscal_period_id);
if ($result < 0) {
@@ -2989,7 +2995,7 @@ class BookKeeping extends CommonObject
$new_fiscal_period_id = max(0, $new_fiscal_period_id);
if (empty($new_fiscal_period_id)) {
$langs->load('errors');
$this->errors[] = $langs->trans('ErrorBadParameters');
$this->errors[] = $langs->trans('ErrorBadParameters').' - '.$langs->trans('AccountancyClosureStep3NewFiscalPeriod');
return -1;
}
$new_fiscal_period = new Fiscalyear($this->db);
@@ -3146,7 +3152,7 @@ class BookKeeping extends CommonObject
}
}
// Insert bookkeeping record for income statement
// Insert bookkeeping record for income statement (loss or profit when closing)
if (!$error && $income_statement_amount != 0) {
$mt = $income_statement_amount;
$accountingaccount = new AccountingAccount($this->db);
@@ -3164,6 +3170,7 @@ class BookKeeping extends CommonObject
$bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
$bookkeeping->thirdparty_code = '';
/* $obj->subledger_account is not defined, so all code into if do the same then in else
if ($separate_auxiliary_account) {
$bookkeeping->subledger_account = $obj->subledger_account;
$sql = 'SELECT';
@@ -3180,10 +3187,14 @@ class BookKeeping extends CommonObject
}
$objtmp = $this->db->fetch_object($result);
$bookkeeping->subledger_label = $objtmp->subledger_label ?? null; // latest subledger label used
} else {
$bookkeeping->subledger_account = null;
$bookkeeping->subledger_label = null;
}
} else {
*/
$bookkeeping->subledger_account = null;
$bookkeeping->subledger_label = null;
//}
$bookkeeping->numero_compte = $accountingaccount->account_number;
$bookkeeping->label_compte = $accountingaccount->label;
@@ -3750,7 +3761,7 @@ class BookKeeping extends CommonObject
$newBookKeeping->sens = 'D';
}
$newBookKeeping->label_operation = "Extourne " . $bookKeeping->piece_num . " - " . $bookKeeping->numero_compte . " - " . date('d/m/Y', dol_now()) . " - " . $i;
$newBookKeeping->label_operation = $langs->trans("ReturnAccount") . " " . $bookKeeping->piece_num . " - " . $bookKeeping->numero_compte . " - " . date('d/m/Y', dol_now()) . " - " . $i;
$newBookKeeping->numero_compte = $bookKeeping->numero_compte;
$newBookKeeping->label_compte = $bookKeeping->label_compte;
@@ -3766,14 +3777,14 @@ class BookKeeping extends CommonObject
}
$createResult = $newBookKeeping->create($user);
if ($createResult > 0) {
if ($createResult >= 0) {
$newBookKeeping->piece_num = $pieceNumNext;
$newBookKeeping->fk_doc = $bookKeeping->fk_doc;
$newBookKeeping->fk_docdet = $bookKeeping->fk_docdet;
$result = $newBookKeeping->update($user);
$newBookKeeping->update($user);
setEventMessages($langs->trans("SuccessReturnedAccount", $bookKeeping->piece_num), null, 'mesgs');
} else {
setEventMessages($langs->trans("ErrorWhileCreating", $newBookKeeping->error), null, 'errors');
setEventMessages($langs->trans("ErrorWhileCreating", $newBookKeeping->error), $newBookKeeping->errors, 'errors');
$error++;
}
}

View File

@@ -0,0 +1,561 @@
<?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

@@ -0,0 +1,368 @@
<?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-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2018-2026 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)
{
@@ -889,12 +889,12 @@ class Lettering extends BookKeeping
while ($obj = $this->db->fetch_object($resql)) {
$current_document_ids[$obj->fk_doc] = $obj->fk_doc;
$link_key = $linked_info['prefix'] . $obj->fk_link;
$link_key = (string) $linked_info['prefix'] . (string) $obj->fk_link;
$element_by_link[$link_key][$obj->fk_doc] = $obj->fk_doc;
$link_by_element[$obj->fk_doc][$link_key] = $link_key;
$link_by_element[(int) $obj->fk_doc][$link_key] = $link_key;
if ($is_fk_link_is_also_fk_doc) {
$element_by_link[$link_key][$obj->fk_link] = $obj->fk_link;
$link_by_element[$obj->fk_link][$link_key] = $link_key;
$link_by_element[(int) $obj->fk_link][$link_key] = $link_key;
}
}
$this->db->free($resql);
@@ -910,11 +910,11 @@ class Lettering extends BookKeeping
/**
* Get element ids grouped by link or element in common
*
* @param array<array<string,int>> $link_by_element List of payment ids by link key
* @param array<int,array<string,int|string>> $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)
* @return array<int,array<int,int>> List of element ids grouped by link or element in common
* @param string $link_key Link key (used for recursive function)
* @param array<int,int> $current_group Current group (used for recursive function)
* @return array<int,array<int,int>> List of element ids grouped by link or element in common
*/
public function getGroupElements(&$link_by_element, &$element_by_link, $link_key = '', &$current_group = array())
{

View File

@@ -26,12 +26,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -39,6 +33,11 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
// Load translation files required by the page
$langs->loadLangs(array("accountancy", "bills", "compta", "exports", "other"));
@@ -241,7 +240,7 @@ if (isset($current_fiscal_period)) {
$form_question,
'',
1,
300,
340,
600
);
} elseif ($action == 'step_2') {
@@ -279,7 +278,7 @@ if (isset($current_fiscal_period)) {
$form_question,
'',
1,
300,
340,
600
);
} elseif ($action == 'step_3') {
@@ -323,7 +322,7 @@ if (isset($current_fiscal_period)) {
$form_question,
'',
1,
300,
340,
600
);
}
@@ -343,11 +342,13 @@ print $formconfirm;
$fiscal_period_nav_text = $langs->trans("FiscalPeriod");
$fiscal_period_nav_text .= '&nbsp;<a href="' . (isset($last_fiscal_period) ? $_SERVER["PHP_SELF"] . '?fiscal_period_id=' . $last_fiscal_period['id'] : '#" class="disabled') . '">' . img_previous() . '</a>';
$fiscal_period_nav_text .= '&nbsp;<a href="' . (isset($next_fiscal_period) ? $_SERVER["PHP_SELF"] . '?fiscal_period_id=' . $next_fiscal_period['id'] : '#" class="disabled') . '">' . img_next() . '</a>';
if (!empty($current_fiscal_period)) {
$fiscal_period_nav_text .= $current_fiscal_period['label'].' &nbsp;(' . dol_print_date($current_fiscal_period['date_start'], 'day') . '&nbsp;-&nbsp;' . dol_print_date($current_fiscal_period['date_end'], 'day') . ')';
$fiscal_period_nav_text .= ' '.$current_fiscal_period['label'].' &nbsp;(' . dol_print_date($current_fiscal_period['date_start'], 'day') . '&nbsp;-&nbsp;' . ($current_fiscal_period['date_end'] ? dol_print_date($current_fiscal_period['date_end'], 'day') : '?'). ')';
}
$fiscal_period_nav_text .= '&nbsp; &nbsp; ';
$fiscal_period_nav_text .= '<a href="' . (isset($last_fiscal_period) ? $_SERVER["PHP_SELF"] . '?fiscal_period_id=' . $last_fiscal_period['id'] : '#" class="disabled') . '">' . img_previous() . '</a>';
$fiscal_period_nav_text .= '&nbsp;';
$fiscal_period_nav_text .= '<a href="' . (isset($next_fiscal_period) ? $_SERVER["PHP_SELF"] . '?fiscal_period_id=' . $next_fiscal_period['id'] : '#" class="disabled') . '">' . img_next() . '</a>';
print load_fiche_titre($langs->trans("Closure") . " - " . $fiscal_period_nav_text, '', 'title_accountancy');
@@ -362,7 +363,7 @@ if (empty($current_fiscal_period)) {
$head[0][2] = 'step1';
print dol_get_fiche_head($head, 'step1', '', -1, '');
print '<span class="opacitymedium">' . $langs->trans("AccountancyClosureStep1Desc") . '</span><br>';
//print '<span class="opacitymedium">' . $langs->trans("AccountancyClosureStep1Desc") . '</span><br>';
$count_by_month = $object->getCountByMonthForFiscalPeriod((int) $current_fiscal_period['date_start'], (int) $current_fiscal_period['date_end']);
@@ -391,7 +392,7 @@ if (empty($current_fiscal_period)) {
print '<td class="right"><b>' . $langs->trans("Total") . '</b></td>';
print '</tr>';
if (is_array($count_by_month['list'])) {
if (is_array($count_by_month['list']) && count($count_by_month['list']) > 0) {
foreach ($count_by_month['list'] as $info) {
print '<tr class="oddeven">';
if ($nb_years > 1) {
@@ -400,8 +401,15 @@ if (empty($current_fiscal_period)) {
for ($i = 1; $i <= 12; $i++) {
print '<td class="right">' . ((int) $info['count'][$i]) . '</td>';
}
print '<td class="right"><b>' . $info['total'] . '</b></td></tr>';
print '<td class="right"><b>' . $info['total'] . '</b></td>';
print '</tr>';
}
} else {
print '<tr class="oddeven"><td colspan="' . (12 + ($nb_years > 1 ? 1 : 0) + 1) . '">';
print '<span class="opacitymedium">';
print $langs->trans("None");
print '</span>';
print '</td></tr>';
}
print "</table>\n";

View File

@@ -132,12 +132,14 @@ if (isModEnabled('accounting')) {
print load_fiche_titre($langs->trans("AccountancyArea"), empty($resultboxes['selectboxlist']) ? '' : $resultboxes['selectboxlist'], 'accountancy', 0, '', '', $showtutorial);
/*
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
$messagewarning = $langs->trans("SorryThisModuleIsNotCompatibleWithTheExperimentalFeatureOfSituationInvoices");
$messagewarning .= ' '.$langs->trans("WarningExperimentalFeatureInvoiceSituationNeedToUpgradeToProgressiveMode", 'https://partners.dolibarr.org');
print info_admin($messagewarning);
print "<br>";
}
*/
if (!$helpisexpanded && empty($resultboxes['boxlista']) && empty($resultboxes['boxlistb'])) {
print '<div class="opacitymedium idfaq2"><br>'.$langs->trans("ClickOnUseTutorialForHelp", $langs->transnoentities("ShowTutorial"))."</div>\n";

View File

@@ -310,7 +310,7 @@ if ($result) {
}
// VAT Reverse charge
if (($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) && $obj->vat_reverse_charge == 1 && in_array($obj->country_code, $country_code_in_EEC)) {
if (($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) && $obj->vat_reverse_charge == 1 && (in_array($obj->country_code, $country_code_in_EEC) || getDolGlobalString('ACCOUNTING_REVERSE_CHARGE_ALSO_NON_EEC'))) {
$rcvatdata = getTaxesFromId($obj->product_buy_vat . ($obj->product_buy_default_vat_code ? ' (' . $obj->product_buy_default_vat_code . ')' : ''), $mysoc, $mysoc, 0);
$rcc_compta_tva = (!empty($vatdata['accountancy_code_vat_reverse_charge_credit']) ? $vatdata['accountancy_code_vat_reverse_charge_credit'] : $rcctva);
$rcd_compta_tva = (!empty($vatdata['accountancy_code_vat_reverse_charge_debit']) ? $vatdata['accountancy_code_vat_reverse_charge_debit'] : $rcdtva);

View File

@@ -20,9 +20,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// $formatexportset must be defined
// $downloadMode =0 for direct download or =1 to download after writing files or =-1 not to download files
'
@phan-var-force int $formatexportset
@phan-var-force string $type_export
@@ -34,10 +31,13 @@
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
*
* @var string $action
* @var int $formatexportset
* @var string $type_export
* @var string $filename
* @var int<-1,1> $downloadMode
* @var string $search_date_end
* @var int<-1,1> $downloadMode Value =0 for direct download or =1 to download after writing files or =-1 not to download files
*/
// Protection to avoid direct call of template
@@ -53,13 +53,10 @@ $nodateexport = getDolGlobalInt('ACCOUNTING_EXPORT_NO_DATE_IN_FILENAME');
$siren = getDolGlobalString('MAIN_INFO_SIREN');
$date_export = "_".dol_print_date(dol_now(), '%Y%m%d%H%M%S');
$startaccountingperiod = '';
$endaccountingperiod = dol_print_date(dol_now(), '%Y%m%d');
if (empty($downloadMode)) {
header('Content-Type: text/csv');
}
include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
$accountancyexport = new AccountancyExport($db);
@@ -102,7 +99,7 @@ if (is_object($hookmanager)) {
'code' => $code ?? '',
'prefix' => $prefix ?? '',
'filename' => $filename ?? '',
'period_start' => $startaccountingperiod ?? '',
'period_start' => $startaccountingperiod,
'period_end' => $endaccountingperiod ?? '',
'siren' => $siren ?? '',
'ndate_in_filename' => $nodateexport ?? 0,
@@ -123,5 +120,6 @@ if (is_object($hookmanager)) {
}
if (empty($downloadMode)) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=' . $completefilename);
}

View File

@@ -35,10 +35,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -48,9 +44,12 @@ require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
*
* @var array<string,array{name:string,paper-size:string|array{0:float,1:float},orientation:string,metric:string,marginLeft:float,marginTop:float,NX:int,NY:int,SpaceX:float,SpaceY:float,width:float,height:float,font-size:int,custom_x:float,custom_y:float}> $_Avery_Labels
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "members"));
$langs->loadLangs(array("admin", "members", "other"));
if (!$user->admin) {
accessforbidden();
@@ -302,7 +301,7 @@ $head = member_admin_prepare_head();
print dol_get_fiche_head($head, 'general', $langs->trans("Members"), -1, 'user');
$dirModMember = array_merge(array('/core/modules/member/'), $conf->modules_parts['member']);
$dirModMember = array_merge(array('/core/modules/member/'), (array) $conf->modules_parts['member']);
foreach ($conf->modules_parts['models'] as $mo) {
//Add more models
$dirModMember[] = $mo.'core/modules/member/';

View File

@@ -61,6 +61,7 @@ if (GETPOSTISARRAY('actioncode')) {
$search_rowid = GETPOST('search_rowid');
$search_agenda_label = GETPOST('search_agenda_label');
$search_complete = GETPOST('search_complete');
$search_filtert = GETPOSTINT('search_filtert');
$search_dateevent_start = GETPOSTDATE('dateevent_start');
$search_dateevent_end = GETPOSTDATE('dateevent_end');
@@ -129,6 +130,7 @@ if (empty($reshook)) {
$search_rowid = '';
$search_agenda_label = '';
$search_complete = '';
$search_filtert = '';
}
}
@@ -249,8 +251,9 @@ if ($object->id > 0) {
$filters['search_agenda_label'] = $search_agenda_label;
$filters['search_rowid'] = $search_rowid;
$filters['search_complete'] = $search_complete; // Can be 'na', '0', '100', '50'
$filters['search_filtert'] = $search_filtert;
// TODO Replace this with same code than into list.php
// TODO Replace this with the same code than into list.php
show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module);
}
}

View File

@@ -336,7 +336,7 @@ if (empty($reshook)) {
$object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
// Change values
$object->civility_id = trim(GETPOST("civility_id", 'alphanohtml'));
$object->civility_code = trim(GETPOST("civility_code", 'alphanohtml'));
$object->firstname = trim(GETPOST("firstname", 'alphanohtml'));
$object->lastname = trim(GETPOST("lastname", 'alphanohtml'));
$object->gender = trim(GETPOST("gender", 'alphanohtml'));
@@ -513,7 +513,7 @@ if (empty($reshook)) {
}
$typeid = GETPOSTINT("typeid");
$civility_id = GETPOST("civility_id", 'alphanohtml');
$civility_code = GETPOST("civility_code", 'alphanohtml');
$lastname = GETPOST("lastname", 'alphanohtml');
$firstname = GETPOST("firstname", 'alphanohtml');
$gender = GETPOST("gender", 'alphanohtml');
@@ -539,7 +539,7 @@ if (empty($reshook)) {
$socid = GETPOSTINT("socid");
$default_lang = GETPOST('default_lang', 'alpha');
$object->civility_id = $civility_id;
$object->civility_code = $civility_code;
$object->firstname = $firstname;
$object->lastname = $lastname;
$object->gender = $gender;
@@ -1076,7 +1076,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$generated_password = getRandomPassword(false);
print '<tr><td><span class="fieldrequired">'.$langs->trans("Password").'</span></td><td>';
print '<input type="text" class="minwidth300" maxlength="50" name="password" value="'.dol_escape_htmltag($generated_password).'">';
print '<input type="password" class="minwidth300" maxlength="50" name="password" value="'.dol_escape_htmltag(GETPOST('password') ? GETPOST('password') : $generated_password).'">';
print '</td></tr>';
}
@@ -1190,7 +1190,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Civility
print '<tr><td>'.$langs->trans("UserTitle").'</td><td>';
print $formcompany->select_civility(GETPOSTINT('civility_id') ? GETPOSTINT('civility_id') : $object->civility_id, 'civility_id', 'maxwidth150', 1).'</td>';
print $formcompany->select_civility(GETPOSTISSET('civility_code') ? GETPOST('civility_code') : $object->civility_code, 'civility_code', 'maxwidth150', 1).'</td>';
print '</tr>';
// Lastname
@@ -1424,7 +1424,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Civility
print '<tr><td>'.$langs->trans("UserTitle").'</td><td>';
print $formcompany->select_civility(GETPOSTISSET("civility_id") ? GETPOST("civility_id", 'alpha') : $object->civility_id, 'civility_id', 'maxwidth150', 1);
print $formcompany->select_civility(GETPOSTISSET("civility_code") ? GETPOST("civility_code", 'alpha') : $object->civility_code, 'civility_code', 'maxwidth150', 1);
print '</td>';
print '</tr>';

View File

@@ -369,7 +369,7 @@ class Adherent extends CommonObject
'morphy' => array('type' => 'varchar(3)', 'label' => 'MemberNature', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 55),
'fk_adherent_type' => array('type' => 'integer', 'label' => 'MemberType', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 60),
'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => 1, 'position' => 65, 'showoncombobox' => 2),
'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => 1, 'position' => 70),
'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'LinkedToDolibarrThirdParty', 'enabled' => 1, 'visible' => 1, 'position' => 70),
'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75),
'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80),
'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 85),
@@ -2191,7 +2191,7 @@ class Adherent extends CommonObject
$now = dol_now();
// Check parameters
if ($this->statut == self::STATUS_VALIDATED) {
if ($this->status == self::STATUS_VALIDATED) {
dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2208,6 +2208,7 @@ 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);
@@ -2231,7 +2232,7 @@ class Adherent extends CommonObject
/**
* Fonction qui resilie un adherent
* Function that terminates a member
*
* @param User $user User making change
* @return int Return integer <0 if KO, >0 if OK
@@ -2243,7 +2244,7 @@ class Adherent extends CommonObject
$error = 0;
// Check parameters
if ($this->statut == self::STATUS_RESILIATED) {
if ($this->status == self::STATUS_RESILIATED) {
dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2258,6 +2259,7 @@ 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);
@@ -2291,7 +2293,7 @@ class Adherent extends CommonObject
$error = 0;
// Check parameters
if ($this->statut == self::STATUS_EXCLUDED) {
if ($this->status == self::STATUS_EXCLUDED) {
dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
return 0;
}
@@ -2306,6 +2308,7 @@ 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);
@@ -2515,7 +2518,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 Chaine avec URL
* @return string String with URL
*/
public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
{
@@ -2746,7 +2749,7 @@ class Adherent extends CommonObject
global $conf, $langs;
if ($user->socid) {
return -1; // protection pour eviter appel par utilisateur externe
return -1; // Protection to prevent calls by external users
}
$now = dol_now();
@@ -2921,7 +2924,7 @@ class Adherent extends CommonObject
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
* Returns the complete DN (Distinguished Name) string in the LDAP directory for the object
*
* @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)
@@ -3147,7 +3150,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 erreur, 0 non envoye, 1 envoye avec success
$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with 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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -111,8 +111,10 @@ 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",),
"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",),
"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",),
"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",),
@@ -160,15 +162,25 @@ 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 int Amount can be chosen by the visitor during subscription (0 or 1)
* @var string Describe the subscription amount formula to follow
*/
public $caneditamount;
public $amountformuladescription;
/**
* @var string Public note
@@ -273,7 +285,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) { // si on a les traduct. dans la langue courante on les charge en infos principales.
if ($obj->lang == $current_lang) { // if we have the translations in the current language, we load them as main information.
$this->label = $obj->label;
$this->description = $obj->description;
$this->email = $obj->email;
@@ -495,8 +507,10 @@ 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 .= "amount = ".((empty($this->amount) && $this->amount == '') ? "null" : ((float) $this->amount)).",";
$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 .= "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).",";
@@ -586,7 +600,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.amount, d.caneditamount, 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.caneditamount, d.minimumamount, d.amount, d.amountformuladescription, 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;
@@ -606,8 +620,10 @@ 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->amount = $obj->amount;
$this->caneditamount = $obj->caneditamount;
$this->minimumamount = $obj->minimumamount;
$this->amount = $obj->amount;
$this->amountformuladescription = $obj->amountformuladescription;
$this->mail_valid = $obj->mail_valid;
$this->note = $obj->note_public; // deprecated
$this->note_public = $obj->note_public;
@@ -782,6 +798,80 @@ 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)
*
@@ -1002,7 +1092,7 @@ class AdherentType extends CommonObject
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
* Returns full DN description in LDAP directory format for the object
*
* @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)
@@ -1183,7 +1273,7 @@ class AdherentType extends CommonObject
//$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
if ($user->hasRight('adherent', 'configurer')) {
$return .= '<span class="right paddingleft"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.urlencode($this->ref).'">'.img_edit().'</a></span>';
$return .= '<span class="right paddingleft"><a class="editfielda showonhover" href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.urlencode($this->ref).'">'.img_edit().'</a></span>';
} else {
$return .= '<span class="right">&nbsp;</span>';
}

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 Chaine avec URL
* @return string String with 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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 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>
*
@@ -169,7 +169,7 @@ $arrayfields = array(
'd.lastname' => array('label' => "Lastname", 'checked' => 1),
'd.firstname' => array('label' => "Firstname", 'checked' => 1),
'd.gender' => array('label' => "Gender", 'checked' => 0),
'd.company' => array('label' => "Company", 'checked' => 1, 'position' => 70),
'd.societe' => array('label' => "Company", 'checked' => 1, 'position' => 70),
'd.login' => array('label' => "Login", 'checked' => 1),
'd.morphy' => array('label' => "MemberNature", 'checked' => 1),
't.libelle' => array('label' => "MemberType", 'checked' => 1, 'position' => 55),
@@ -503,7 +503,7 @@ if ($search_filter == 'outofdate') {
$sql .= " AND (datefin < '".$db->idate($now)."')";
}
if ($search_status != '') {
// Peut valoir un nombre ou liste de nombre separates par virgules
// Can be a number or comma separated list of numbers
$sql .= " AND d.statut in (".$db->sanitize($db->escape($search_status)).")";
}
if ($search_morphy != '' && $search_morphy != '-1') {
@@ -931,7 +931,7 @@ if (!empty($arrayfields['d.gender']['checked'])) {
}
// Company
if (!empty($arrayfields['d.company']['checked'])) {
if (!empty($arrayfields['d.societe']['checked'])) {
print '<td class="liste_titre left">';
print '<input class="flat maxwidth75imp" type="text" name="search_company" value="'.dol_escape_htmltag($search_company).'"></td>';
}
@@ -1131,8 +1131,8 @@ if (!empty($arrayfields['d.gender']['checked'])) {
print_liste_field_titre($arrayfields['d.gender']['label'], $_SERVER['PHP_SELF'], 'd.gender', '', $param, '', $sortfield, $sortorder);
$totalarray['nbfield']++;
}
if (!empty($arrayfields['d.company']['checked'])) {
print_liste_field_titre($arrayfields['d.company']['label'], $_SERVER["PHP_SELF"], 'companyname', '', $param, '', $sortfield, $sortorder);
if (!empty($arrayfields['d.societe']['checked'])) {
print_liste_field_titre($arrayfields['d.societe']['label'], $_SERVER["PHP_SELF"], 'companyname', '', $param, '', $sortfield, $sortorder);
$totalarray['nbfield']++;
}
if (!empty($arrayfields['d.login']['checked'])) {
@@ -1364,7 +1364,7 @@ while ($i < $imaxinloop) {
}
}
// Company
if (!empty($arrayfields['d.company']['checked'])) {
if (!empty($arrayfields['d.societe']['checked'])) {
print '<td class="tdoverflowmax125" title="'.dolPrintHTMLForAttribute((string) $companyname).'">';
print $companynametoshow;
print "</td>\n";

View File

@@ -50,10 +50,12 @@ $langs->loadLangs(array('agenda', 'bills', 'companies', 'orders', 'propal'));
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'useragenda';
if (GETPOST('actioncode', 'array')) {
$actioncode = GETPOST('actioncode', 'array', 3);
if (GETPOSTISARRAY('actioncode')) {
$actioncode = GETPOST('actioncode', 'array:alpha', 3);
if (!count($actioncode)) {
$actioncode = '0';
} else {
$actioncode = implode(',', $actioncode);
}
} else {
$actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT'));

View File

@@ -149,7 +149,9 @@ if (empty($reshook) && $action == 'confirm_create_thirdparty' && $confirm == 'ye
$langs->load("errors");
setEventMessages($company->error, $company->errors, 'errors');
} else {
$action = 'addsubscription';
$object->socid = $result;
$action = 'createsubscription';
}
} else {
setEventMessages($object->error, $object->errors, 'errors');
@@ -248,14 +250,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 = 'addsubscription';
$action = 'createsubscription';
}
if (GETPOST('end') && !$datesubend) {
$error++;
$langs->load("errors");
$errmsg = $langs->trans("ErrorBadDateFormat", $langs->transnoentitiesnoconv("DateEndSubscription"));
setEventMessages($errmsg, null, 'errors');
$action = 'addsubscription';
$action = 'createsubscription';
}
if (!$datesubend) {
$datesubend = dol_time_plus_duree(dol_time_plus_duree($datesubscription, $defaultdelay, $defaultdelayunit), -1, 'd');
@@ -264,7 +266,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$error++;
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePayment"));
setEventMessages($errmsg, null, 'errors');
$action = 'addsubscription';
$action = 'createsubscription';
}
// Check if a payment is mandatory or not
@@ -274,7 +276,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'addsubscription';
$action = 'createsubscription';
} 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') {
@@ -283,26 +285,26 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'addsubscription';
$action = 'createsubscription';
}
if (GETPOST("paymentsave") != 'invoiceonly' && !GETPOST("operation")) {
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'addsubscription';
$action = 'createsubscription';
}
if (GETPOST("paymentsave") != 'invoiceonly' && !(GETPOSTINT("accountid") > 0)) {
$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("FinancialAccount"));
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'addsubscription';
$action = 'createsubscription';
}
} else {
if (GETPOSTINT("accountid")) {
$errmsg = $langs->trans("ErrorDoNotProvideAccountsIfNullAmount");
setEventMessages($errmsg, null, 'errors');
$error++;
$action = 'addsubscription';
$action = 'createsubscription';
}
}
}
@@ -335,7 +337,7 @@ if (empty($reshook) && $user->hasRight('adherent', 'cotisation', 'creer') && $ac
$db->commit();
} else {
$db->rollback();
$action = 'addsubscription';
$action = 'createsubscription';
}
if (!$error) {
@@ -695,11 +697,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 != 'addsubscription' && $action != 'create_thirdparty') {
if ($action != 'createsubscription' && $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=addsubscription&token='.newToken().'">'.$langs->trans("AddSubscription")."</a></div>";
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$rowid.'&action=createsubscription">'.$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>';
}
@@ -711,7 +713,7 @@ if ($user->hasRight('adherent', 'cotisation', 'creer')) {
/*
* List of subscriptions
*/
if ($action != 'addsubscription' && $action != 'create_thirdparty') {
if ($action != 'createsubscription' && $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,";
@@ -820,7 +822,7 @@ if ($action != 'addsubscription' && $action != 'create_thirdparty') {
}
if (($action != 'addsubscription' && $action != 'create_thirdparty')) {
if (($action != 'createsubscription' && $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';
@@ -839,7 +841,7 @@ if (($action != 'addsubscription' && $action != 'create_thirdparty')) {
/*
* Add new subscription form
*/
if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->hasRight('adherent', 'cotisation', 'creer')) {
if (($action == 'createsubscription' || $action == 'create_thirdparty') && $user->hasRight('adherent', 'cotisation', 'creer')) {
print '<br>';
print load_fiche_titre($langs->trans("NewCotisation"));
@@ -932,7 +934,7 @@ if (($action == 'addsubscription' || $action == 'create_thirdparty') && $user->h
// 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 = $companyname;
$tmpcompany->name = (string) $companyname;
$tmpcompany->get_codeclient($tmpcompany, 0);
$customercode = $tmpcompany->code_client;
$formquestion[] = array(

View File

@@ -2,6 +2,7 @@
/* 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
@@ -344,7 +345,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($object->note_public)).'</td></tr>';
print '<tr><td>'.$langs->trans("Label").'</td><td class="valeur sensiblehtmlcontent">'.dol_string_onlythesehtmltags(dol_htmlentitiesbr((string) $object->note_public)).'</td></tr>';
// Bank line
if (isModEnabled("bank") && (getDolGlobalString('ADHERENT_BANK_USE') || $object->fk_bank)) {

View File

@@ -40,7 +40,6 @@ require '../main.inc.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
@@ -92,13 +91,15 @@ $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);
@@ -173,8 +174,10 @@ if ($action == 'add' && $user->hasRight('adherent', 'configurer')) {
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (string) (int) $subscription;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->caneditamount = $caneditamount;
$object->minimumamount = ($minimumamount == '' ? '' : price2num($minimumamount, 'MT'));
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->amountformuladescription = trim($amountformuladescription);
$object->duration_value = $duration_value;
$object->duration_unit = $duration_unit;
$object->note_public = trim($comment);
@@ -234,8 +237,10 @@ if ($action == 'update' && $user->hasRight('adherent', 'configurer')) {
$object->morphy = trim($morphy);
$object->status = (int) $status;
$object->subscription = (string) (int) $subscription;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->caneditamount = $caneditamount;
$object->minimumamount = $minimumamount;
$object->amount = ($amount == '' ? '' : price2num($amount, 'MT'));
$object->amountformuladescription = trim($amountformuladescription);
$object->duration_value = $duration_value;
$object->duration_unit = $duration_unit;
$object->note_public = trim($comment);
@@ -297,7 +302,7 @@ $totalarray = [
if (!$rowid && $action != 'create' && $action != 'edit') {
//print dol_get_fiche_head([]);
$sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.caneditamount, d.vote,";
$sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.caneditamount, d.minimumamount, d.amount, d.amountformuladescription, d.vote,";
$sql .= " d.statut as status, d.morphy, d.duration,";
$sql .= " d.tms";
$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d";
@@ -381,12 +386,20 @@ 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("Amount").'</th>';
print '<th class="center">'.$langs->trans("RecommendedAmount").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.caneditamount']['checked'])) {
print '<th class="center">'.$langs->trans("CanEditAmountShort").'</th>';
if (!empty($arrayfields['t.amountformuladescription']['checked'])) {
print '<th class="center">'.$langs->trans("AmountFormulaDescription").'</th>';
$totalarray['nbfield']++;
}
if (!empty($arrayfields['t.vote']['checked'])) {
@@ -424,8 +437,10 @@ if (!$rowid && $action != 'create' && $action != 'edit') {
$membertype->label = $objp->rowid;
$membertype->status = $objp->status;
$membertype->subscription = $objp->subscription;
$membertype->amount = $objp->amount;
$membertype->caneditamount = $objp->caneditamount;
$membertype->minimumamount = $objp->minimumamount;
$membertype->amount = $objp->amount;
$membertype->amountformuladescription = $objp->amountformuladescription;
if ($mode == 'kanban') {
if ($i == 0) {
@@ -484,17 +499,27 @@ 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.caneditamount']['checked'])) {
print '<td class="center">'.yn($objp->caneditamount).'</td>';
if (!empty($arrayfields['t.amountformuladescription']['checked'])) {
print '<td class="center">'.dol_escape_htmltag($objp->amountformuladescription).'</td>';
}
if (!empty($arrayfields['t.vote']['checked'])) {
print '<td class="center">'.yn($objp->vote).'</td>';
@@ -553,7 +578,7 @@ if ($action == 'create') {
print '<table class="border centpercent">';
print '<tbody>';
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td><td><input type="text" class="minwidth200" name="label" value= "'. $label. '" autofocus="autofocus"></td></tr>';
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td><td><input type="text" class="minwidth300" name="label" value= "'. $label. '" autofocus="autofocus"></td></tr>';
print '<tr><td>'.$langs->trans("Status").'</td><td>';
print $form->selectarray('status', array('0' => $langs->trans('ActivityCeased'), '1' => $langs->trans('InActivity')), 1, 0, 0, 0, '', 0, 0, 0, '', 'minwidth100');
@@ -566,27 +591,36 @@ if ($action == 'create') {
"mor" => $langs->trans("Moral"),
];
print '<tr><td><span>'.$langs->trans("MembersNature").'</span></td><td>';
print $form->selectarray("morphy", $morphys, GETPOSTISSET("morphy") ? GETPOST("morphy", 'aZ09') : 'morphy');
print $form->selectarray("morphy", $morphys, GETPOSTISSET("morphy") ? GETPOST("morphy", 'aZ09') : 'morphy', 0, 0, 0, '', 0, 0, 0, '', 'minwidth300');
print "</td></tr>";
print '<tr><td>'.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).'</td><td>';
print $form->selectyesno("subscription", 1, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("Amount").'</td><td>';
print '<input name="amount" size="5" value="'.(GETPOSTISSET('amount') ? GETPOST('amount') : price($amount)).'">';
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 '<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>'.$langs->trans("VoteAllowed").'</td><td>';
print $form->selectyesno("vote", GETPOSTISSET("vote") ? GETPOST('vote', 'aZ09') : 1, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("Duration").'</td><td colspan="3">';
print '<input name="duration_value" size="5" value="'. $duration_value .'"> ';
print '<input name="duration_value" size="5" value="'. ($duration_value ? $duration_value : 1) .'"> ';
print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOSTISSET("duration_unit") ? GETPOST('duration_unit', 'aZ09') : 'y', 0, 1);
print '</td></tr>';
@@ -650,17 +684,29 @@ if ($rowid > 0) {
print '</tr>';
// Amount
print '<tr><td class="titlefield">'.$langs->trans("Amount").'</td><td>';
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>';
$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>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmount")).'</td><td>';
print yn($object->caneditamount);
print '</td></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>'.$langs->trans("VoteAllowed").'</td><td>';
print yn($object->vote);
@@ -682,7 +728,7 @@ if ($rowid > 0) {
// Description
print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td><div class="longmessagecut">';
print dol_string_onlythesehtmltags(dol_htmlentitiesbr($object->note_public));
print dol_string_onlythesehtmltags(dol_htmlentitiesbr((string) $object->note_public));
print "</div></td></tr>";
// Welcome email content
@@ -1097,15 +1143,28 @@ if ($rowid > 0) {
print $form->selectyesno("subscription", $object->subscription, 1);
print '</td></tr>';
print '<tr><td>'.$langs->trans("Amount").'</td><td>';
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>';
$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>'.$form->textwithpicto($langs->trans("CanEditAmountShort"), $langs->transnoentities("CanEditAmountDetail")).'</td><td>';
print $form->selectyesno("caneditamount", $object->caneditamount, 1);
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 '</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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -282,6 +282,7 @@ if (getDolGlobalString('BARCODE_USE_ON_PRODUCT') && isModEnabled('product')) {
dol_include_once($dirroot.$file.'.php');
} catch (Exception $e) {
dol_syslog($e->getMessage(), LOG_ERR);
continue;
}
$modBarCode = new $file();
@@ -349,6 +350,7 @@ if (getDolGlobalString('BARCODE_USE_ON_THIRDPARTY') && isModEnabled('societe'))
dol_include_once($dirroot.$file.'.php');
} catch (Exception $e) {
dol_syslog($e->getMessage(), LOG_ERR);
continue;
}
$modBarCode = new $file();
@@ -428,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 "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 "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 '</td>';
// Show example
@@ -518,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($conf->global->GENBARCODE_LOCATION)) {
if (getDolGlobalString('GENBARCODE_LOCATION') && !@file_exists(getDolGlobalString('GENBARCODE_LOCATION'))) {
$langs->load("errors");
print '<br><span class="error">'.$langs->trans("ErrorFileNotFound", getDolGlobalString('GENBARCODE_LOCATION')).'</span>';
}

View File

@@ -1,7 +1,8 @@
<?php
/* Copyright (C) 2019 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2019 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* 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
@@ -29,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
require_once DOL_DOCUMENT_ROOT.'/bom/lib/bom.lib.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
/**
* @var Conf $conf
@@ -151,27 +153,27 @@ if ($action == 'updateMask') {
$error++;
}
$bomsearch = GETPOST('activate_BOM_USE_SEARCH_TO_SELECT', 'alpha');
$res = dolibarr_set_const($db, "BOM_USE_SEARCH_TO_SELECT", $bomsearch, 'chaine', 0, '', $conf->entity);
if (!($res > 0)) {
$error++;
}
$freetext = GETPOST("BOM_FREE_TEXT", 'restricthtml'); // No alpha here, we want exact string
$res = dolibarr_set_const($db, "BOM_FREE_TEXT", $freetext, 'chaine', 0, '', $conf->entity);
if (!($res > 0)) {
$error++;
}
if (!$error) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
} elseif ($action == 'updateoptions') {
if (GETPOST('BOM_USE_SEARCH_TO_SELECT')) {
$bomsearch = GETPOST('activate_BOM_USE_SEARCH_TO_SELECT', 'alpha');
if (dolibarr_set_const($db, "BOM_USE_SEARCH_TO_SELECT", $bomsearch, 'chaine', 0, '', $conf->entity)) {
$conf->global->BOM_USE_SEARCH_TO_SELECT = $bomsearch;
}
}
}
/*
* View
*/
@@ -486,9 +488,6 @@ if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 1) {
print '<tr class="oddeven">';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="updateoptions">';
print '<td>'.$langs->trans("UseSearchToSelectBom").'</td>';
if (!$conf->use_javascript_ajax) {
print '<td></td>';
@@ -496,15 +495,13 @@ if (!$conf->use_javascript_ajax) {
print $langs->trans("NotAvailableWhenAjaxDisabled");
print "</td>";
} else {
print '<td class="right">';
print '<td>';
$arrval = array('0' => $langs->trans("No"),
'1' => $langs->trans("Yes").' ('.$langs->trans("NumberOfKeyToSearch", 1).')',
'2' => $langs->trans("Yes").' ('.$langs->trans("NumberOfKeyToSearch", 2).')',
'3' => $langs->trans("Yes").' ('.$langs->trans("NumberOfKeyToSearch", 3).')',
);
print $form->selectarray("activate_BOM_USE_SEARCH_TO_SELECT", $arrval, getDolGlobalString("BOM_USE_SEARCH_TO_SELECT")).'</td>';
print '<td class="right"><input type="submit" class="button small reposition" name="BOM_USE_SEARCH_TO_SELECT" value="'.$langs->trans("Modify").'">';
print "</td>";
}
print '</form>';
print '</tr>';
@@ -538,17 +535,13 @@ print '<input class="flat minwidth200" type="text" name="BOM_DRAFT_WATERMARK" va
print "</td></tr>\n";
print '</table>';
print '<center><input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'"></center>';
print '</div>';
print $form->buttonsSaveCancel("Save", '');
print '</form>';
print '<br>';
print dol_get_fiche_end();
// End of page
llxFooter();

View File

@@ -459,7 +459,9 @@ print '<td class="liste_titre"></td>';
print '</tr>';
// Activate FileCache (so content of file boxes are stored into a cache file int boxes/temp for 3600 seconds)
print '<tr class="oddeven"><td>'.$langs->trans("EnableFileCache").'</td><td>';
print '<tr class="oddeven"><td>'.$langs->trans("EnableFileCache");
print ' <span class="opacitymedium">('.getDolGlobalInt('MAIN_ACTIVATE_FILECACHE_DELAY', 900)." ".$langs->trans("seconds").")</span>";
print '</td><td>';
if ($conf->use_javascript_ajax) {
print ajax_constantonoff('MAIN_ACTIVATE_FILECACHE', array(), null, 0, 0, 0, 2, 0, 1);
} else {

View File

@@ -24,9 +24,6 @@
// Load Dolibarr environment
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/dav/dav.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -37,6 +34,8 @@ require_once DOL_DOCUMENT_ROOT.'/dav/dav.lib.php';
*
* @var string $dolibarr_main_url_root
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/dav/dav.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "other", "agenda"));

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-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2019-2026 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 ";
// Modifie valeur des champs
// Update fields value
if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) {
$sql .= $tabrowid[$id]."=";
$sql .= "'".$db->escape($rowid)."', ";
@@ -1378,6 +1378,7 @@ if (empty($reshook)) {
*/
$form = new Form($db);
$formother = new FormOther($db);
$title = $langs->trans("DictionarySetup");
@@ -1478,7 +1479,11 @@ if ($id > 0) {
$sql .= " WHERE 1 = 1";
}
if ($search_country_id > 0) {
$sql .= " AND c.rowid = ".((int) $search_country_id);
if ($id == DICT_HRM_PUBLIC_HOLIDAY || $id == DICT_HOLIDAY_TYPES) {
$sql .= " AND (c.rowid IS NULL OR c.rowid = 0 OR c.rowid = ".((int) $search_country_id).")";
} else {
$sql .= " AND c.rowid = ".((int) $search_country_id);
}
}
if ($search_code != '') {
$sql .= natural_search($tablecode, $search_code);
@@ -2621,6 +2626,8 @@ 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}, '');
}
@@ -2825,14 +2832,13 @@ $db->close();
function dictFieldList($fieldlist, $obj = null, $tabname = '', $context = '')
{
global $langs, $db, $mysoc;
global $form;
global $form, $formother;
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,6 +662,8 @@ 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

@@ -26,6 +26,13 @@
// 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/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/events.class.php';
@@ -36,14 +43,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/emailcollector/class/emailcollector.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
* @var HookManager $hookmanager
* @var Translate $langs
* @var User $user
*/
// Load translation files required by page
$langs->loadLangs(array("admin", "other"));
@@ -53,7 +52,7 @@ $show_files = GETPOSTINT('show_files'); // Show files area generated by bulk act
$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'emailcollectorlist'; // To manage different context of search
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : getDolDefaultContextPage(__FILE__); // To manage different context of search
$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
$mode = GETPOST('mode', 'aZ');
@@ -125,12 +124,13 @@ foreach ($object->fields as $key => $val) {
}
// Definition of array of fields for columns
$tableprefix = 't';
$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((string) $val['visible'], 1);
$arrayfields['t.'.$key] = array(
$arrayfields[$tableprefix.'.'.$key] = array(
'label' => $val['label'],
'checked' => (($visible < 0) ? '0' : '1'),
'enabled' => (string) (int) (abs($visible) != 3 && (bool) dol_eval((string) $val['enabled'], 1)),
@@ -257,25 +257,42 @@ foreach ($search as $key => $val) {
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] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
$field_spec = $object->fields[$key];
// @phpstan-ignore-next-line PHPStan thinks that $field_spec is never null
if ($field_spec === null) {
continue;
}
$mode_search = (($object->isInt($field_spec) || $object->isFloat($field_spec)) ? 1 : 0);
if ((strpos($field_spec['type'], 'integer:') === 0) || (strpos($field_spec['type'], 'sellist:') === 0) || !empty($field_spec['arrayofkeyval'])) {
if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($field_spec['arrayofkeyval']) || !array_key_exists('0', $field_spec['arrayofkeyval'])))) {
$search[$key] = '';
}
$mode_search = 2;
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
if ($field_spec['type'] === 'boolean') {
$mode_search = 1;
if ($search[$key] == '-1') {
$search[$key] = '';
}
}
if (empty($field_spec['searchmulti'])) {
if (!is_array($search[$key]) && $search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (is_array($search[$key]) && !empty($search[$key])) {
$sql .= natural_search("t.".$db->escape($key), implode(',', $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])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}
@@ -364,7 +381,7 @@ $param = '';
if (!empty($mode)) {
$param .= '&mode='.urlencode($mode);
}
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
if (!empty($contextpage) && $contextpage != getDolDefaultContextPage(__FILE__)) {
$param .= '&contextpage='.urlencode($contextpage);
}
if ($limit > 0 && $limit != $conf->liste_limit) {
@@ -383,17 +400,18 @@ foreach ($search as $key => $val) {
$param .= '&search_'.$key.'[]='.urlencode($skey);
}
}
} elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
$param .= '&search_'.$key.'month='.GETPOSTINT('search_'.$key.'month');
$param .= '&search_'.$key.'day='.GETPOSTINT('search_'.$key.'day');
$param .= '&search_'.$key.'year='.GETPOSTINT('search_'.$key.'year');
} elseif ($search[$key] != '') {
$param .= '&search_'.$key.'='.urlencode($search[$key]);
}
}
if ($optioncss != '') {
$param .= '&optioncss='.urlencode($optioncss);
}
// Add $param from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
// Add $param from hooks
$parameters = array();
$parameters = array('param' => &$param);
$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
$param .= $hookmanager->resPrint;
@@ -402,7 +420,7 @@ $arrayofmassactions = array(
//'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
);
if ($permissiontodelete) {
if (!empty($permissiontodelete)) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
}
if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
@@ -421,6 +439,8 @@ 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="page_y" value="">';
print '<input type="hidden" name="mode" value="'.$mode.'">';
$newcardbutton = '';
$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', 'emailcollector_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
@@ -446,6 +466,9 @@ if (empty($reshook)) {
} else {
$moreforfilter = $hookmanager->resPrint;
}
$parameters = array(
'arrayfields' => &$arrayfields,
);
if (!empty($moreforfilter)) {
print '<div class="liste_titre liste_titre_bydiv centpercent">';
@@ -484,11 +507,15 @@ foreach ($object->fields as $key => $val) {
$cssforfield .= ($cssforfield ? ' ' : '').'right';
}
if (!empty($arrayfields['t.'.$key]['checked'])) {
print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
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', 1);
if (empty($val['searchmulti'])) {
print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 1, 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
} else {
print $form->multiselectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : array()), 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_', 'maxwidth125', 1);
print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth125', 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'));
@@ -499,9 +526,11 @@ foreach ($object->fields as $key => $val) {
} 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, array(), 1, 0, 0, 'minwidth100imp maxwidth125', 2);
print $formadmin->select_language((isset($search[$key]) ? $search[$key] : ''), 'search_lang', 0, array(), 1, 0, 0, 'minwidth100imp maxwidth125', 2);
} elseif ($val['type'] === 'boolean') {
print $form->selectyesno('search_' . $key, $search[$key] ?? '', 1, false, 1);
} 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 '<input type="text" class="flat maxwidth'.(in_array($val['type'], array('integer', 'price')) ? '50' : '75').'" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
}
print '</td>';
}
@@ -561,7 +590,6 @@ if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
$totalarray['nbfield']++;
print '</tr>'."\n";
@@ -760,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, $conf->global->MAIN_IMAP_USE_PHPIMAP);
print $form->selectarray("MAIN_IMAP_USE_PHPIMAP", $arrval, getDolGlobalString("MAIN_IMAP_USE_PHPIMAP"));
}
print '</td>';
print '</tr>';

View File

@@ -398,13 +398,13 @@ foreach ($dirmodels as $reldir) {
// Active
if (in_array($name, $def)) {
print '<td class="center">'."\n";
print '<a href="'.$_SERVER["PHP_SELF"].'?action=del&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'">';
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=del&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'">';
print img_picto($langs->trans("Enabled"), 'switch_on');
print '</a>';
print "</td>";
} else {
print '<td class="center">'."\n";
print '<a href="'.$_SERVER["PHP_SELF"].'?action=set&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').'</a>';
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=set&token='.newToken().'&value='.urlencode($name).'&scan_dir='.urlencode($module->scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').'</a>';
print "</td>";
}

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-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -61,7 +61,7 @@ if (!$user->admin) {
*/
$error = 0;
// positionne la variable pour le nombre de rss externes
// Set the variable for the number of external RSS
$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 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@@ -193,7 +193,8 @@ if ($action == 'updatesocialnetwork') {
$paramsKey = GETPOST('paramsKey', 'array');
$paramsVal = GETPOST('paramsVal', 'array');
$result = dolibarr_get_const($db, "SOCIAL_NETWORKS_DATA_".$name, $conf->entity);
$result = getDolGlobalString("SOCIAL_NETWORKS_DATA_".$name);
$socialNetworkData = json_decode($result, true);
foreach ($paramsKey as $index => $key) {
@@ -244,7 +245,9 @@ if ($action == 'editsocialnetwork' && GETPOST('confirm') == 'yes') {
$paramKey = GETPOST('paramkey', 'alpha');
$key = GETPOST('key', 'alpha');
$name = GETPOST('name');
$result = dolibarr_get_const($db, "SOCIAL_NETWORKS_DATA_".$name, $conf->entity);
$result = getDolGlobalString("SOCIAL_NETWORKS_DATA_".$name);
$socialNetworkData = json_decode($result, true);
unset($socialNetworkData[$paramKey]);
@@ -349,7 +352,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) $conf->global->OAUTH_SERVICE_SOCIAL_NETWORK);
print $form->selectarray('OAUTH_SERVICE_SOCIAL_NETWORK', $oauthservicesStringKeys, (string) getDolGlobalString("OAUTH_SERVICE_SOCIAL_NETWORK"));
} else {
$selectedKey = (string) getDolGlobalString('OAUTH_SERVICE_SOCIAL_NETWORK');
$text = isset($oauthservicesStringKeys[$selectedKey]) ? $oauthservicesStringKeys[$selectedKey]['label'] : '';
@@ -387,17 +390,17 @@ print '<script type="text/javascript">
$(document).ready(function() {
function toggleOAuthServiceDisplay() {
if ($("#radio_oauth").is(":checked")) {
$("#oauth_service_div").show(); // Afficher le sélecteur OAuth
$("#oauth_service_div").show(); // Show the OAuth selector
} else {
$("#oauth_service_div").hide(); // Cacher le sélecteur OAuth
$("#oauth_service_div").hide(); // Hide the OAuth selector
}
}
function toggleAddParamRow() {
if ($("#radio_oauth").is(":checked")) {
$("#add_param_row").hide(); // Cacher toute la ligne
$("#add_param_row").hide(); // Hide the entire line
} else {
$("#add_param_row").show(); // Afficher toute la ligne
$("#add_param_row").show(); // Show the entire line
}
}

View File

@@ -49,7 +49,7 @@ $langs->loadLangs(array("admin", "errors"));
$action = GETPOST('action', 'aZ09');
if (!isset($conf->global->GEOIP_VERSION)) {
if (!getDolGlobalString("GEOIP_VERSION")) {
$conf->global->GEOIP_VERSION = '2';
}
@@ -95,6 +95,7 @@ if ($action == 'set') {
if ($diroffile) {
$dirforterms = $diroffile.'/';
$original_file = $_FILES[$varname]["name"];
// @phan-suppress-next-line PhanTypeInvalidDimOffset
$result = dol_move_uploaded_file($_FILES[$varname]["tmp_name"], $dirforterms.$original_file, 1, 0, $_FILES[$varname]['error']);
if ((int) $result > 0) {
dolibarr_set_const($db, $varname, $original_file, 'chaine', 0, '', $conf->entity);

View File

@@ -27,11 +27,6 @@
// Load Dolibarr environment
require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/holiday.lib.php';
/**
* @var Conf $conf
* @var DoliDB $db
@@ -40,9 +35,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/holiday.lib.php';
* @var Translate $langs
* @var User $user
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/holiday.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "errors", "holiday"));
$langs->loadLangs(array("admin", "errors", "holiday", "other"));
if (!$user->admin) {
accessforbidden();
@@ -199,7 +198,7 @@ print '<td>'.$langs->trans("Description").'</td>';
print '<td>'.$langs->trans("Example").'</td>';
print '<td align="center" width="60">'.$langs->trans("Status").'</td>';
print '<td align="center" width="16">'.$langs->trans("ShortInfo").'</td>';
print "</tr>\n";
print '</tr>'."\n";
clearstatcache();
@@ -228,7 +227,7 @@ foreach ($dirmodels as $reldir) {
}
if ($module->isEnabled()) {
print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
print '<tr class="oddeven"><td>'.$module->getName($langs)."</td><td>\n";
print $module->info($langs);
print '</td>';
@@ -448,6 +447,32 @@ if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
}
/*
* Type of leaves
*/
print load_fiche_titre($langs->trans("LeaveType"), '', '');
print '<div class="urllink">';
print img_picto('', 'url', 'class="pictofixedwidth"').' <a href="'.DOL_URL_ROOT.'/admin/dict.php?id=28&search_country_id='.($conf->entity).'">'.$langs->trans("ClickHereToGoToDictionary", $langs->transnoentitiesnoconv("Setup"), $langs->transnoentitiesnoconv("Dictionary"), $langs->transnoentitiesnoconv("LeaveType")).'</a>';
print '</div>';
print '<br><br>';
/*
* Type of leaves
*/
print load_fiche_titre($langs->trans("DictionaryPublicHolidays"), '', '');
print '<div class="urllink">';
print img_picto('', 'url', 'class="pictofixedwidth"').' <a href="'.DOL_URL_ROOT.'/admin/dict.php?id=32&search_country_id='.($conf->entity).'">'.$langs->trans("ClickHereToGoToDictionary", $langs->transnoentitiesnoconv("Setup"), $langs->transnoentitiesnoconv("Dictionary"), $langs->transnoentitiesnoconv("DictionaryPublicHolidays")).'</a>';
print '</div>';
print '<br><br>';
/*
* Other options
*/

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', $_FILES[$varforimage]["name"], $reg)) {
if (preg_match('/([^\\/:]+)$/i', (string) $_FILES[$varforimage]["name"], $reg)) {
$original_file = $reg[1];
$isimage = image_format_supported($original_file);

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