From bd353ede426d4240384211ca57943ceac7db5c8d Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 17:11:28 +0100
Subject: [PATCH 01/25] Handle bordereaudoc actions and email
---
bordereaudoc_card.php | 308 +++++++++
class/bordereaudoc.class.php | 370 +++++++++++
class/diffusion.class.php | 2 +-
core/modules/modDiffusionPlans.class.php | 108 +--
diffusion_card.php | 814 -----------------------
diffusion_list.php | 4 +-
langs/en_US/diffusionplans.lang | 17 +
langs/fr_FR/diffusionplans.lang | 17 +
lib/diffusionplans_diffusion.lib.php | 2 +-
sql/llx_bordereaudoc.key.sql | 7 +
sql/llx_bordereaudoc.sql | 31 +
sql/llx_bordereaudoc_contact.key.sql | 7 +
sql/llx_bordereaudoc_contact.sql | 31 +
sql/llx_bordereaudoc_file.key.sql | 7 +
sql/llx_bordereaudoc_file.sql | 27 +
15 files changed, 895 insertions(+), 857 deletions(-)
create mode 100644 bordereaudoc_card.php
create mode 100644 class/bordereaudoc.class.php
delete mode 100644 diffusion_card.php
create mode 100644 sql/llx_bordereaudoc.key.sql
create mode 100644 sql/llx_bordereaudoc.sql
create mode 100644 sql/llx_bordereaudoc_contact.key.sql
create mode 100644 sql/llx_bordereaudoc_contact.sql
create mode 100644 sql/llx_bordereaudoc_file.key.sql
create mode 100644 sql/llx_bordereaudoc_file.sql
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
new file mode 100644
index 0000000..6476861
--- /dev/null
+++ b/bordereaudoc_card.php
@@ -0,0 +1,308 @@
+
+*
+* 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 .
+*/
+
+/**
+* \file bordereaudoc_card.php
+* \ingroup diffusionplans
+* \brief Card page for Bordereaudoc object.
+*/
+
+// Load Dolibarr environment
+$res = 0;
+if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
+ $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
+}
+$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
+$tmp2 = realpath(__FILE__);
+$i = strlen($tmp) - 1;
+$j = strlen($tmp2) - 1;
+while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
+ $i--;
+ $j--;
+}
+if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
+ $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
+}
+if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
+ $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
+}
+if (!$res && file_exists("../main.inc.php")) {
+ $res = @include "../main.inc.php";
+}
+if (!$res && file_exists("../../main.inc.php")) {
+ $res = @include "../../main.inc.php";
+}
+if (!$res && file_exists("../../../main.inc.php")) {
+ $res = @include "../../../main.inc.php";
+}
+if (!$res) {
+ die("Include of main fails");
+}
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
+require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
+dol_include_once('/diffusionplans/class/bordereaudoc.class.php');
+
+// Load translations
+$langs->loadLangs(array('diffusionplans@diffusionplans', 'other', 'projects'));
+
+// Get parameters
+$id = GETPOSTINT('id');
+$ref = GETPOST('ref', 'alpha');
+$action = GETPOST('action', 'aZ09');
+$backtopage = GETPOST('backtopage', 'alpha');
+$cancel = GETPOST('cancel', 'alpha');
+$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bordereaudoccard';
+$optioncss = GETPOST('optioncss', 'aZ');
+
+// Objects
+$object = new Bordereaudoc($db);
+$form = new Form($db);
+$formproject = new FormProjets($db);
+$hookmanager = new HookManager($db);
+$hookmanager->initHooks(array('bordereaudoccard', 'globalcard'));
+
+// Permissions
+$permissiontoread = $user->hasRight('diffusionplans', 'bordereaudoc', 'read');
+$permissiontoadd = $user->hasRight('diffusionplans', 'bordereaudoc', 'write');
+$permissiontovalidate = $user->hasRight('diffusionplans', 'bordereaudoc', 'validate');
+$permissiontosend = $user->hasRight('diffusionplans', 'bordereaudoc', 'send');
+$permissiontoarchive = $user->hasRight('diffusionplans', 'bordereaudoc', 'archive');
+$permissiondelete = $user->hasRight('diffusionplans', 'bordereaudoc', 'delete');
+
+if (!$permissiontoread) {
+ accessforbidden();
+}
+
+// Fetch object
+if (!empty($id) || !empty($ref)) {
+ $object->fetch($id, $ref);
+}
+
+// Actions
+if ($cancel && $backtopage) {
+ header("Location: ".$backtopage);
+ exit;
+}
+
+$parameters = array('id' => $object->id, 'ref' => $object->ref);
+$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
+if ($reshook < 0) {
+ setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
+}
+if (empty($reshook)) {
+ if ($action === 'add' && $permissiontoadd) {
+ $object->ref = GETPOST('ref', 'alpha');
+ $object->title = GETPOST('title', 'alpha');
+ $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
+ $object->fk_project = GETPOSTINT('fk_project');
+
+ $result = $object->create($user);
+ if ($result > 0) {
+ if (!empty($backtopage)) {
+ header('Location: '.$backtopage);
+ exit;
+ }
+ header('Location: '.dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id);
+ exit;
+ }
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = 'create';
+ }
+
+ if ($action === 'update' && $permissiontoadd && $object->id > 0) {
+ $object->title = GETPOST('title', 'alpha');
+ $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
+ $object->fk_project = GETPOSTINT('fk_project');
+ $object->fk_user_modif = $user->id;
+ $result = $object->update($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = 'edit';
+ }
+ }
+
+ if ($action === 'confirm_delete' && GETPOST('confirm', 'alpha') === 'yes' && $permissiondelete && $object->id > 0) {
+ $result = $object->delete($user);
+ if ($result > 0) {
+ header('Location: '.dol_buildpath('/diffusionplans/diffusion_list.php', 1));
+ exit;
+ }
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+
+ if ($action === 'confirm_validate' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontovalidate && $object->id > 0) {
+ $result = $object->validate($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocValidated'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+
+ if ($action === 'confirm_delivered' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontoarchive && $object->id > 0) {
+ $result = $object->setDelivered($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocDelivered'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+
+ if ($action === 'confirm_close' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontoarchive && $object->id > 0) {
+ $result = $object->setClosed($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocClosed'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+
+ if ($action === 'builddoc' && $permissiontoread && $object->id > 0) {
+ $model = GETPOST('model', 'alpha');
+ if (empty($model)) {
+ $model = $object->model_pdf ? $object->model_pdf : 'standard';
+ }
+ if ($model !== $object->model_pdf) {
+ $object->model_pdf = $model;
+ $object->update($user);
+ }
+
+ $result = $object->generateDocument($model, $langs);
+ if ($result <= 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+
+ if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
+ require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+
+ if (empty($object->last_main_doc)) {
+ $object->generateDocument($object->model_pdf ? $object->model_pdf : 'standard', $langs);
+ }
+
+ $filepath = dol_buildpath('/custom/diffusionplans/documents/'.$object->ref, 0);
+ $filename = dol_sanitizeFileName($object->ref.'.pdf');
+ $fullpath = $filepath.'/'.$filename;
+
+ $recipients = array();
+ $lines = $object->getRecipients(1);
+ foreach ($lines as $line) {
+ if (!empty($line->send_email) && !empty($line->fk_contact)) {
+ $contact = new Contact($db);
+ if ($contact->fetch($line->fk_contact) > 0 && !empty($contact->email)) {
+ $recipients[] = $contact->email;
+ }
+ }
+ }
+
+ if (empty($recipients)) {
+ setEventMessages($langs->trans('ErrorNoEMailRecipientSelected'), null, 'errors');
+ } else {
+ $subject = $langs->trans('Bordereaudoc').' '.$object->ref;
+ $body = dol_htmlentitiesbr($object->description);
+ $mailfile = new CMailFile($subject, implode(',', $recipients), $user->email, $body, array($fullpath), array($filename), array('application/pdf'));
+ if ($mailfile->sendfile()) {
+ setEventMessages($langs->trans('MailSuccessfulySent', implode(',', $recipients)), null, 'mesgs');
+ } else {
+ setEventMessages($mailfile->error, $mailfile->errors, 'errors');
+ }
+ }
+ }
+}
+
+// View
+$help_url = '';
+llxHeader('', $langs->trans('BordereaudocCard'), $help_url);
+
+if ($action === 'create') {
+ print load_fiche_titre($langs->trans('BordereaudocNew'), '', 'fa fa-paper-plane');
+ print '
';
+
+ dol_print_footer();
+ llxFooter();
+ $db->close();
+ exit;
+}
+
+if ($object->id > 0) {
+ $head = array();
+ $head[0][0] = dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id;
+ $head[0][1] = $langs->trans('Card');
+ $head[0][2] = 'card';
+
+ dol_fiche_head($head, 'card', $langs->trans('Bordereaudoc'), -1, 'fa-paper-plane');
+
+ $linkback = ''.$langs->trans('BackToList').' ';
+ $morehtmlref = '';
+ if (!empty($object->fk_project)) {
+ $projectstatic = new Project($db);
+ $projectstatic->fetch($object->fk_project);
+ $morehtmlref .= ' '.$projectstatic->getNomUrl(1);
+ }
+ print '';
+ print ''.$langs->trans('Ref').' '.$form->showrefnav($object, 'ref', $linkback, true, 'ref', 'ref', '').' ';
+ print ''.$langs->trans('BordereaudocTitle').' '.dol_escape_htmltag($object->title).' ';
+ print ''.$langs->trans('Project').' '.$morehtmlref.' ';
+ print ''.$langs->trans('Description').' '.dol_htmlentitiesbr($object->description).' ';
+ print ''.$langs->trans('Status').' '.$object->getLibStatut(5).' ';
+ print '
';
+
+ dol_fiche_end();
+}
+
+// Footer
+dol_print_footer();
+llxFooter();
+$db->close();
diff --git a/class/bordereaudoc.class.php b/class/bordereaudoc.class.php
new file mode 100644
index 0000000..a9acdab
--- /dev/null
+++ b/class/bordereaudoc.class.php
@@ -0,0 +1,370 @@
+
+*
+* 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 .
+*/
+
+/**
+* \file class/bordereaudoc.class.php
+* \ingroup diffusionplans
+* \brief Business class for delivery slip of documents.
+*/
+
+// Dolibarr includes
+require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+
+/**
+* Class for Bordereaudoc
+*/
+class Bordereaudoc extends CommonObject
+{
+ /**
+ * @var string Module name
+ */
+ public $module = 'diffusionplans';
+
+ /**
+ * @var string Element name
+ */
+ public $element = 'bordereaudoc';
+
+ /**
+ * @var string Table without prefix
+ */
+ public $table_element = 'bordereaudoc';
+
+ /**
+ * @var string Picto code
+ */
+ public $picto = 'fa-paper-plane';
+
+ /**
+ * Status constants
+ */
+ const STATUS_DRAFT = 0;
+ const STATUS_VALIDATED = 1;
+ const STATUS_DELIVERED = 2;
+ const STATUS_CLOSED = 3;
+
+ /**
+ * @var array Fields definition
+ */
+ public $fields = array(
+ 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => '1', 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1),
+ 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => '1', 'position' => 10, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1),
+ 'title' => array('type' => 'varchar(255)', 'label' => 'Title', 'enabled' => '1', 'position' => 20, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'validate' => 1),
+ 'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => '1', 'position' => 30, 'notnull' => 0, 'visible' => 3, 'validate' => 1),
+ 'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1', 'label' => 'Project', 'picto' => 'project', 'enabled' => "isModEnabled('project')", 'position' => 40, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'validate' => 1),
+ 'status' => array('type' => 'integer', 'label' => 'Status', 'enabled' => '1', 'position' => 50, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'arrayofkeyval' => array('0' => 'Draft', '1' => 'Validated', '2' => 'Delivered', '3' => 'Closed'), 'validate' => 1),
+ 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => '1', 'position' => 60, 'notnull' => 1, 'visible' => -2, 'index' => 1),
+ 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => '1', 'position' => 70, 'notnull' => 1, 'visible' => -2),
+ 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => '1', 'position' => 80, 'notnull' => 0, 'visible' => -2),
+ 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'picto' => 'user', 'enabled' => '1', 'position' => 90, 'notnull' => 1, 'visible' => -2),
+ 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'picto' => 'user', 'enabled' => '1', 'position' => 100, 'notnull' => -1, 'visible' => -2),
+ 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => '1', 'position' => 110, 'notnull' => -1, 'visible' => -2),
+ 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => '1', 'position' => 120, 'notnull' => 0, 'visible' => 0),
+ 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'ModelPDF', 'enabled' => '1', 'position' => 130, 'notnull' => -1, 'visible' => 0),
+ );
+
+ public $rowid;
+ public $ref;
+ public $title;
+ public $description;
+ public $fk_project;
+ public $status;
+ public $entity;
+ public $datec;
+ public $tms;
+ public $fk_user_creat;
+ public $fk_user_modif;
+ public $import_key;
+ public $last_main_doc;
+ public $model_pdf;
+
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct(DoliDB $db)
+ {
+ global $conf;
+
+ $this->db = $db;
+ $this->ismultientitymanaged = 1;
+ $this->isextrafieldmanaged = 1;
+
+ $this->fields['entity']['default'] = !empty($conf->entity) ? (int) $conf->entity : 1;
+ $this->fields['datec']['default'] = dol_now();
+ $this->fields['status']['default'] = self::STATUS_DRAFT;
+ }
+
+ /**
+ * Get next reference for object
+ *
+ * @param User $user Current user
+ * @return string
+ */
+ public function getNextNumRef(User $user)
+ {
+ $prefix = getDolGlobalString('DIFFUSIONPLANS_BORDEREAU_REF_PREFIX', 'BRD');
+
+ return $this->getDefaultRef($this->db, $prefix, '', 'bordereaudoc', 'ref');
+ }
+
+ /**
+ * Create object in database
+ *
+ * @param User $user Current user
+ * @param bool $notrigger Disable triggers
+ * @return int
+ */
+ public function create(User $user, $notrigger = false)
+ {
+ if (empty($this->fk_project)) {
+ $this->error = 'ErrorFieldRequired';
+
+ return -1;
+ }
+
+ if (empty($this->ref)) {
+ $this->ref = '(PROV)';
+ }
+
+ $this->entity = !empty($this->entity) ? $this->entity : $user->entity;
+ $this->datec = dol_now();
+ $this->fk_user_creat = $user->id;
+ $this->status = self::STATUS_DRAFT;
+
+ return parent::create($user, $notrigger);
+ }
+
+ /**
+ * Validate object
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function validate(User $user)
+ {
+ if (empty($this->fk_project)) {
+ $this->error = 'ErrorFieldRequired';
+
+ return -1;
+ }
+
+ if ($this->ref == '(PROV)') {
+ $this->ref = $this->getNextNumRef($user);
+ }
+
+ $this->status = self::STATUS_VALIDATED;
+ $this->fk_user_modif = $user->id;
+
+ return $this->update($user);
+ }
+
+ /**
+ * Set status back to draft
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function setDraft(User $user)
+ {
+ $this->status = self::STATUS_DRAFT;
+ $this->fk_user_modif = $user->id;
+
+ return $this->update($user);
+ }
+
+ /**
+ * Mark as delivered
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function setDelivered(User $user)
+ {
+ $this->status = self::STATUS_DELIVERED;
+ $this->fk_user_modif = $user->id;
+
+ return $this->update($user);
+ }
+
+ /**
+ * Close object
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function setClosed(User $user)
+ {
+ $this->status = self::STATUS_CLOSED;
+ $this->fk_user_modif = $user->id;
+
+ return $this->update($user);
+ }
+
+ /**
+ * Load project contacts into bordereaudoc contacts table
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function loadProjectContacts(User $user)
+ {
+ if (empty($this->fk_project)) {
+ return 0;
+ }
+
+ $project = new Project($this->db);
+ $res = $project->fetch($this->fk_project);
+ if ($res <= 0) {
+ return -1;
+ }
+
+ $contacts = $project->liste_contact(0, 'external', '', 1, 'contact', 1);
+ if (empty($contacts)) {
+ return 0;
+ }
+
+ $count = 0;
+ foreach ($contacts as $contact) {
+ $already = $this->recipientExists($contact['id']);
+ if ($already) {
+ continue;
+ }
+
+ $this->addRecipient($user, $contact['socid'], $contact['id'], $contact['libelle_fonction'], 'External', 1, 0, 0);
+ $count++;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Check if recipient already exists
+ *
+ * @param int $contactId Contact id
+ * @return bool
+ */
+ protected function recipientExists($contactId)
+ {
+ $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX."bordereaudoc_contact WHERE fk_bordereaudoc = ".((int) $this->id)." AND fk_contact =".((int) $contactId);
+ $sql .= " AND entity = ".((int) $this->entity);
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ return false;
+ }
+
+ return ($this->db->num_rows($resql) > 0);
+ }
+
+ /**
+ * Add a recipient
+ *
+ * @param User $user Current user
+ * @param int $socid Thirdparty id
+ * @param int $contactId Contact id
+ * @param string $typeContact Type label
+ * @param string $nature Nature label
+ * @param int $email Send email flag
+ * @param int $mail Send mail flag
+ * @param int $hand Hand delivery flag
+ * @return int
+ */
+ public function addRecipient(User $user, $socid, $contactId, $typeContact = '', $nature = '', $email = 1, $mail = 0, $hand = 0)
+ {
+ $sql = 'INSERT INTO '.MAIN_DB_PREFIX."bordereaudoc_contact (datec, tms, fk_bordereaudoc, fk_soc, fk_contact, nature_contact, type_contact, send_email, send_mail, send_hand, active, entity, fk_user_creat)";
+ $sql .= " VALUES (".$this->db->idate(dol_now()).", ".$this->db->idate(dol_now()).", ".((int) $this->id).", ".((int) $socid).", ".((int) $contactId).", ";
+ $sql .= "'".$this->db->escape($nature)."', '".$this->db->escape($typeContact)."', ".((int) $email).", ".((int) $mail).", ".((int) $hand).", 1, ".((int) $this->entity).", ".((int) $user->id).")";
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return -1;
+ }
+
+ return $this->db->last_insert_id(MAIN_DB_PREFIX.'bordereaudoc_contact');
+ }
+
+ /**
+ * Update recipient flags
+ *
+ * @param int $lineId Line id
+ * @param array $data Data to update
+ * @return int
+ */
+ public function updateRecipientFlags($lineId, array $data)
+ {
+ $fields = array();
+ foreach (array('send_email', 'send_mail', 'send_hand', 'active') as $key) {
+ if (isset($data[$key])) {
+ $fields[] = $key.' = '.((int) $data[$key]);
+ }
+ }
+
+ if (empty($fields)) {
+ return 0;
+ }
+
+ $sql = 'UPDATE '.MAIN_DB_PREFIX.'bordereaudoc_contact SET '.implode(', ', $fields).' WHERE rowid = '.((int) $lineId);
+ $sql .= " AND fk_bordereaudoc = ".((int) $this->id)." AND entity = ".((int) $this->entity);
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return -1;
+ }
+
+ return 1;
+ }
+
+ /**
+ * Get recipients list
+ *
+ * @param int $onlyActive Restrict to active
+ * @return array
+ */
+ public function getRecipients($onlyActive = 0)
+ {
+ $sql = 'SELECT bc.rowid, bc.fk_soc, bc.fk_contact, bc.nature_contact, bc.type_contact, bc.send_email, bc.send_mail, bc.send_hand, bc.active, s.nom as socname, c.lastname, c.firstname, c.civility as civility';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'bordereaudoc_contact as bc';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON bc.fk_soc = s.rowid';
+ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."socpeople as c ON bc.fk_contact = c.rowid";
+ $sql .= ' WHERE bc.fk_bordereaudoc = '.((int) $this->id).' AND bc.entity = '.((int) $this->entity);
+ if ($onlyActive) {
+ $sql .= ' AND bc.active = 1';
+ }
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return array();
+ }
+
+ $lines = array();
+ while ($obj = $this->db->fetch_object($resql)) {
+ $lines[] = $obj;
+ }
+
+ return $lines;
+ }
+}
diff --git a/class/diffusion.class.php b/class/diffusion.class.php
index 5ef4b40..20689d3 100644
--- a/class/diffusion.class.php
+++ b/class/diffusion.class.php
@@ -914,7 +914,7 @@ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss
$label = implode($this->getTooltipContentArray($params));
}
- $url = dol_buildpath('/diffusionplans/diffusion_card.php', 1).'?id='.$this->id;
+$url = dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$this->id;
if ($option !== 'nolink') {
// Add param to save lastsearch_values or not
diff --git a/core/modules/modDiffusionPlans.class.php b/core/modules/modDiffusionPlans.class.php
index 12305e1..55d2232 100644
--- a/core/modules/modDiffusionPlans.class.php
+++ b/core/modules/modDiffusionPlans.class.php
@@ -347,43 +347,73 @@ public function __construct($db)
// 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'isModEnabled("diffusionplans")', 'priority'=>50)
// );
- // Permissions provided by this module
- $this->rights = array();
- $r = 0;
- // Add here entries to declare new permissions
- /* BEGIN MODULEBUILDER PERMISSIONS */
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 0 + 1);
- $this->rights[$r][1] = 'Read Diffusion object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusion';
- $this->rights[$r][5] = 'read';
- $r++;
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 1 + 1);
- $this->rights[$r][1] = 'Create/Update Diffusion object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusion';
- $this->rights[$r][5] = 'write';
- $r++;
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 2 + 1);
- $this->rights[$r][1] = 'Delete Diffusion object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusion';
- $this->rights[$r][5] = 'delete';
- $r++;
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 0 + 1);
- $this->rights[$r][1] = 'Read DiffusionContact object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusioncontact';
- $this->rights[$r][5] = 'read';
- $r++;
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 1 + 1);
- $this->rights[$r][1] = 'Create/Update DiffusionContact object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusioncontact';
- $this->rights[$r][5] = 'write';
- $r++;
- $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 2 + 1);
- $this->rights[$r][1] = 'Delete DiffusionContact object of DiffusionPlans';
- $this->rights[$r][4] = 'diffusioncontact';
- $this->rights[$r][5] = 'delete';
- $r++;
-
- /* END MODULEBUILDER PERMISSIONS */
+// Permissions provided by this module
+$this->rights = array();
+$r = 0;
+// Add here entries to declare new permissions
+ /* BEGIN MODULEBUILDER PERMISSIONS */
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 0 + 1);
+ $this->rights[$r][1] = 'Read Diffusion object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusion';
+ $this->rights[$r][5] = 'read';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 1 + 1);
+ $this->rights[$r][1] = 'Create/Update Diffusion object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusion';
+ $this->rights[$r][5] = 'write';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 2 + 1);
+ $this->rights[$r][1] = 'Delete Diffusion object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusion';
+ $this->rights[$r][5] = 'delete';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 0 + 1);
+ $this->rights[$r][1] = 'Read DiffusionContact object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusioncontact';
+ $this->rights[$r][5] = 'read';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 1 + 1);
+ $this->rights[$r][1] = 'Create/Update DiffusionContact object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusioncontact';
+ $this->rights[$r][5] = 'write';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 2 + 1);
+ $this->rights[$r][1] = 'Delete DiffusionContact object of DiffusionPlans';
+ $this->rights[$r][4] = 'diffusioncontact';
+ $this->rights[$r][5] = 'delete';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 0 + 1);
+ $this->rights[$r][1] = 'Read Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'read';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 1 + 1);
+ $this->rights[$r][1] = 'Create/Update Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'write';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 2 + 1);
+ $this->rights[$r][1] = 'Validate Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'validate';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 3 + 1);
+ $this->rights[$r][1] = 'Send Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'send';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 4 + 1);
+ $this->rights[$r][1] = 'Archive Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'archive';
+ $r++;
+ $this->rights[$r][0] = $this->numero . sprintf('%02d', (2 * 10) + 5 + 1);
+ $this->rights[$r][1] = 'Delete Bordereaudoc object of DiffusionPlans';
+ $this->rights[$r][4] = 'bordereaudoc';
+ $this->rights[$r][5] = 'delete';
+ $r++;
+
+ /* END MODULEBUILDER PERMISSIONS */
// Main menu entries to add
@@ -451,7 +481,7 @@ public function __construct($db)
'titre' => 'New Diffusion',
'mainmenu' => 'diffusionplans',
'leftmenu' => 'diffusionplans_diffusion_new',
- 'url' => '/diffusionplans/diffusion_card.php?action=create',
+'url' => '/diffusionplans/bordereaudoc_card.php?action=create',
'langs' => 'diffusionplans@diffusionplans',
'position' => 1003,
'enabled' => 'isModEnabled(\'diffusionplans\')',
@@ -486,7 +516,7 @@ public function __construct($db)
'titre' => 'New_Diffusion',
'mainmenu' => 'diffusionplans',
'leftmenu' => 'diffusionplans_diffusion_new',
- 'url' => '/diffusionplans/diffusion_card.php?action=create',
+'url' => '/diffusionplans/bordereaudoc_card.php?action=create',
'langs' => 'diffusionplans@diffusionplans', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
'position' => 1000 + $r,
'enabled' => 'isModEnabled("diffusionplans")', // Define condition to show or hide menu entry. Use 'isModEnabled("diffusionplans")' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
diff --git a/diffusion_card.php b/diffusion_card.php
deleted file mode 100644
index 585b5ab..0000000
--- a/diffusion_card.php
+++ /dev/null
@@ -1,814 +0,0 @@
-
- * Copyright (C) 2024 Frédéric France
- * Copyright (C) 2025 Pierre ARDOIN
- *
- * 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 .
- */
-
-/**
- * \file diffusion_card.php
- * \ingroup diffusionplans
- * \brief Page to create/edit/view diffusion
- */
-
-
-// General defined Options
-//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET
-//if (! defined('MAIN_AUTHENTICATION_MODE')) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler
-//if (! defined('MAIN_LANG_DEFAULT')) define('MAIN_LANG_DEFAULT', 'auto'); // Force LANG (language) to a particular value
-//if (! defined('MAIN_SECURITY_FORCECSP')) define('MAIN_SECURITY_FORCECSP', 'none'); // Disable all Content Security Policies
-//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification
-//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
-//if (! defined('NOLOGIN')) define('NOLOGIN', '1'); // Do not use login - if this page is public (can be called outside logged session). This includes the NOIPCHECK too.
-//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
-//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db
-//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // Do not load html.form.class.php
-//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // Do not load and show top and left menu
-//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc
-//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs
-//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user
-//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters
-//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters
-//if (! defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions
-//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data
-//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on)
-
-
-// Load Dolibarr environment
-$res = 0;
-// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
-if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
- $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
-}
-// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
-$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
-$tmp2 = realpath(__FILE__);
-$i = strlen($tmp) - 1;
-$j = strlen($tmp2) - 1;
-while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
- $i--;
- $j--;
-}
-if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
- $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
-}
-if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
- $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
-}
-// Try main.inc.php using relative path
-if (!$res && file_exists("../main.inc.php")) {
- $res = @include "../main.inc.php";
-}
-if (!$res && file_exists("../../main.inc.php")) {
- $res = @include "../../main.inc.php";
-}
-if (!$res && file_exists("../../../main.inc.php")) {
- $res = @include "../../../main.inc.php";
-}
-if (!$res) {
- die("Include of main fails");
-}
-
-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.formprojet.class.php';
-require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
-require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
-
-
-dol_include_once('/diffusionplans/class/diffusion.class.php');
-dol_include_once('/diffusionplans/class/diffusioncontact.class.php');
-dol_include_once('/diffusionplans/lib/diffusionplans_diffusion.lib.php');
-
-/**
- * @var Conf $conf
- * @var DoliDB $db
- * @var HookManager $hookmanager
- * @var Societe $mysoc
- * @var Translate $langs
- * @var User $user
- */
-
-// Load translation files required by the page
-$langs->loadLangs(array("diffusionplans@diffusionplans", "other"));
-
-// Get parameters
-$id = GETPOSTINT('id');
-$ref = GETPOST('ref', 'alpha');
-$lineid = GETPOSTINT('lineid');
-
-$action = GETPOST('action', 'aZ09');
-$confirm = GETPOST('confirm', 'alpha');
-$cancel = GETPOST('cancel', 'aZ09');
-$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
-$backtopage = GETPOST('backtopage', 'alpha'); // if not set, a default page will be used
-$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // if not set, $backtopage will be used
-$backtopagejsfields = GETPOST('backtopagejsfields', 'alpha');
-$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
-$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09');
-
-
-if (!empty($backtopagejsfields)) {
- $tmpbacktopagejsfields = explode(':', $backtopagejsfields);
- $dol_openinpopup = preg_replace('/[^a-z0-9_]/i', '', $tmpbacktopagejsfields[0]);
-}
-
-// Initialize a technical objects
-$object = new Diffusion($db);
-
-$diffusion_project = new Project($db);
-
-$extrafields = new ExtraFields($db);
-
-$object->dir_output = $conf->monmodule->dir_output . '/' . dol_sanitizeFileName($object->ref);
-$diroutputmassaction = $conf->diffusionplans->dir_output.'/temp/massgeneration/'.$user->id;
-$hookmanager->initHooks(array($object->element.'card', 'globalcard')); // Note that conf->hooks_modules contains array
-$soc = null;
-
-// 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($ref)) {
- $action = 'view';
-}
-
-// Load object
-include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
-
-// There is several ways to check permission.
-// Set $enablepermissioncheck to 1 to enable a minimum low level of checks
-$enablepermissioncheck = getDolGlobalInt('DIFFUSIONPLANS_ENABLE_PERMISSION_CHECK');
-if ($enablepermissioncheck) {
- $permissiontoread = $user->hasRight('diffusionplans', 'diffusion', 'read');
- $permissiontoadd = $user->hasRight('diffusionplans', 'diffusion', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
- $permissiontodelete = $user->hasRight('diffusionplans', 'diffusion', 'delete') || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
- $permissionnote = $user->hasRight('diffusionplans', 'diffusion', 'write'); // Used by the include of actions_setnotes.inc.php
- $permissiondellink = $user->hasRight('diffusionplans', 'diffusion', 'write'); // Used by the include of actions_dellink.inc.php
-} else {
- $permissiontoread = 1;
- $permissiontoadd = 1; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
- $permissiontodelete = 1;
- $permissionnote = 1;
- $permissiondellink = 1;
-}
-
-$upload_dir = $conf->diffusionplans->multidir_output[isset($object->entity) ? $object->entity : 1].'/diffusion';
-
-// Security check (enable the most restrictive one)
-//if ($user->socid > 0) accessforbidden();
-//if ($user->socid > 0) $socid = $user->socid;
-$isdraft = (isset($object->status) && ($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-//restrictedArea($user, $object->module, $object, $object->table_element, $object->element, 'fk_soc', 'rowid', $isdraft);
-if (!isModEnabled($object->module)) {
- accessforbidden("Module ".$object->module." not enabled");
-}
-if (!$permissiontoread) {
- accessforbidden();
-}
-
-$error = 0;
-
-
-/*
- * Actions
- */
-
-$parameters = array();
-$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
-if ($reshook < 0) {
- setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
-}
-
-if (empty($reshook)) {
- $backurlforlist = dol_buildpath('/diffusionplans/diffusion_list.php', 1);
-
- 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_buildpath('/diffusionplans/diffusion_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
- }
- }
- }
-
- $triggermodname = 'DIFFUSIONPLANS_DIFFUSION_MODIFY'; // Name of trigger action code to execute when we modify record
-
- // 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 move up and down lines of object
- //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php';
-
- // Action to build doc
- include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
-
- if ($action == 'set_thirdparty' && $permissiontoadd) {
- $object->setValueFrom('fk_soc', GETPOSTINT('fk_soc'), '', null, 'date', '', $user, $triggermodname);
- }
- if ($action == 'classin' && $permissiontoadd) {
- $object->setProject(GETPOSTINT('projectid'));
- }
-
- // Actions to send emails
- $triggersendname = 'DIFFUSIONPLANS_DIFFUSION_SENTBYMAIL';
- $autocopy = 'MAIN_MAIL_AUTOCOPY_DIFFUSION_TO';
- $trackid = 'diffusion'.$object->id;
- include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
-}
-
-/*
- * Add a new contact
- */
-
-if ($action == 'addcontact' && $permissiontoadd) {
- $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
- $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
- $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
- if ($result >= 0) {
- $diffusioncontactstatic = new DiffusionContact($db);
-
- $resql = $diffusioncontactstatic->create($object->id, $contactid, GETPOST("source", 'aZ09'));
- //var_dump("Contact ID : ".$result);
- header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
- exit;
- } else {
- if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
- $langs->load("errors");
- setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
- } else {
- setEventMessages($object->error, $object->errors, 'errors');
- }
- }
-} elseif ($action == 'swapstatut' && $permissiontoadd) {
- // Toggle the status of a contact
- $result = $object->swapContactStatus(GETPOSTINT('ligne'));
-} elseif ($action == 'deletecontact' && $permissiontoadd) { // Permission to add on object because this is an update of a link of object, not a deletion of data
- // Deletes a contact
- $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid'));
- $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
- $result = $object->delete_contact($lineid);
-
- if ($result >= 0) {
-
- $diffusioncontactstatic = new DiffusionContact($db);
-
- $deletediffusioncontact = $diffusioncontactstatic->deleteLine($object->id, $contactid, GETPOST("source", 'aZ09'));
-
- header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
- exit;
- } else {
- dol_print_error($db);
- }
-} elseif ($action == 'add' && $usercancreate) {
- //$db->begin();
- $object->ref = GETPOST('ref');
- $object->label = GETPOST('label');
- $object->fk_project = GETPOSTINT('projectid');
- $object->description = GETPOST('description', 'restricthtml');
-
- var_dump($object->fk_project);
- //$id = $object->create($user, $db);
-}
-
-/*
- * View
- */
-
-$form = new Form($db);
-$formfile = new FormFile($db);
-$formproject = new FormProjets($db);
-
-//$title = $langs->trans("Diffusion")." - ".$langs->trans('Card');
-$title = $object->ref." - ".$langs->trans('Card');
-if ($action == 'create') {
- $title = $langs->trans("NewDiffusion", $langs->transnoentitiesnoconv("Diffusion"));
-}
-$help_url = '';
-
-llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-diffusionplans page-card');
-
-// Example : Adding jquery code
-// print '';
-
-
-// Part to create
-if ($action == 'create') {
- if (empty($permissiontoadd)) {
- accessforbidden('NotEnoughPermissions', 0, 1);
- }
-
- print load_fiche_titre($title, '', $object->picto);
-
- print '';
-
- //dol_set_focus('input[name="ref"]');
-}
-
-// Part to edit record
-if (($id || $ref) && $action == 'edit') {
- print load_fiche_titre($langs->trans("Diffusion"), '', $object->picto);
-
- print '';
-}
-
-// Part to show record
-if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
- $head = diffusionPrepareHead($object);
-
- print dol_get_fiche_head($head, 'card', $langs->trans("Diffusion"), -1, $object->picto, 0, '', '', 0, '', 1);
-
- $formconfirm = '';
-
- // Confirmation to delete (using preloaded confirm popup)
- if ($action == 'delete' || ($conf->use_javascript_ajax && empty($conf->dol_use_jmobile))) {
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteDiffusion'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 'action-delete');
- }
- // 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->ref), 'confirm_clone', $formquestion, 'yes', 1);
- }
-
- // Confirmation of action xxxx (You can use it for xxx = 'close', xxx = 'reopen', ...)
- if ($action == 'xxx') {
- $text = $langs->trans('ConfirmActionXxx', $object->ref);
- /*if (isModEnabled('notification'))
- {
- require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
- $notify = new Notify($db);
- $text .= ' ';
- $text .= $notify->confirmMessage('DIFFUSION_CLOSE', $object->socid, $object);
- }*/
-
- $formquestion = array();
-
- /*
- $forcecombo=0;
- if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
- $formquestion = array(
- // 'text' => $langs->trans("ConfirmClone"),
- // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
- // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
- // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
- );
- */
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220);
- }
-
- // Call Hook formConfirm
- $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
- $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
- if (empty($reshook)) {
- $formconfirm .= $hookmanager->resPrint;
- } elseif ($reshook > 0) {
- $formconfirm = $hookmanager->resPrint;
- }
-
- // Print form confirm
- print $formconfirm;
-
-
- // Object card
- // ------------------------------------------------------------
- $linkback = ''.$langs->trans("BackToList").' ';
-
- $morehtmlref = '';
- /*
- // Ref customer
- $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1);
- $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string'.(getDolGlobalInt('THIRDPARTY_REF_INPUT_SIZE') ? ':'.getDolGlobalInt('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1);
- // Thirdparty
- $morehtmlref .= '
'.$object->thirdparty->getNomUrl(1, 'customer');
- if (!getDolGlobalInt('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' (
'.$langs->trans("OtherOrders").' )';
- }
- // Project
- if (isModEnabled('project')) {
- $langs->load("projects");
- $morehtmlref .= '
';
- if ($permissiontoadd) {
- $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
- if ($action != 'classify') {
- $morehtmlref .= '
'.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
- }
- $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
- } else {
- if (!empty($object->fk_project)) {
- $proj = new Project($db);
- $proj->fetch($object->fk_project);
- $morehtmlref .= $proj->getNomUrl(1);
- if ($proj->title) {
- $morehtmlref .= '
- '.dol_escape_htmltag($proj->title).' ';
- }
- }
- }
- }
- */
- $morehtmlref .= '
';
-
-
- dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
-
-
- print '';
- print '
';
- print '
';
- print '
'."\n";
-
- $fieldsBackup = $object->fields;
- $labelFieldDef = isset($object->fields['label']) ? $object->fields['label'] : null;
- $descriptionFieldDef = isset($object->fields['description']) ? $object->fields['description'] : null;
- if ($labelFieldDef !== null) {
- unset($object->fields['label']);
- }
- if ($descriptionFieldDef !== null) {
- unset($object->fields['description']);
- }
-
- $inlineEditable = ($permissiontoadd && $object->status == $object::STATUS_DRAFT);
-
- if ($labelFieldDef !== null) {
- $valueClasses = array('valuefield');
- if (!empty($labelFieldDef['cssview'])) {
- $valueClasses[] = $labelFieldDef['cssview'];
- }
- $valueClassAttr = implode(' ', array_unique(array_filter($valueClasses)));
-
- print ''; // Label row
- print ''.$form->editfieldkey($labelFieldDef['label'], 'label', '', $object, $inlineEditable, 'string').' ';
- print ''.$form->editfieldval($labelFieldDef['label'], 'label', $object->label, $object, $inlineEditable, 'string', '', null, null, '', 1).' ';
- print ' ';
- }
-
- if ($descriptionFieldDef !== null) {
- $descValueClasses = array('valuefield', 'wordbreak');
- if (!empty($descriptionFieldDef['cssview'])) {
- $descValueClasses[] = $descriptionFieldDef['cssview'];
- }
- $descValueClassAttr = implode(' ', array_unique(array_filter($descValueClasses)));
-
- print '';
- print ''.$form->editfieldkey($descriptionFieldDef['label'], 'description', '', $object, $inlineEditable, 'textarea').' ';
- print ''.$form->editfieldval($descriptionFieldDef['label'], 'description', $object->description, $object, $inlineEditable, 'textarea:100:6', '', null, null, '', 1).' ';
- print ' ';
- }
-
- // Common attributes
- //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field
- //unset($object->fields['fk_project']); // Hide field already shown in banner
- //unset($object->fields['fk_soc']); // Hide field already shown in banner
- include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
-
- $object->fields = $fieldsBackup;
-
- // Other attributes. Fields from hook formObjectOptions and Extrafields.
- include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
-
- print '
';
- print '
';
- print '
';
-
- print '
';
-
- print dol_get_fiche_end();
-
-
- /*
- * Lines
- */
-
- include './tpl/diffusion_contacts.tpl.php';
-
- if (!empty($object->table_element_line)) {
- // Show object lines
- $result = $object->getLinesArray();
-
- print ' \n";
- }
-
-
- // Buttons for actions
-
- if ($action != 'presend' && $action != 'editline') {
- print ''."\n";
- $parameters = array();
- $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
- if ($reshook < 0) {
- setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
- }
-
- if (empty($reshook)) {
- // Send
- if (empty($user->socid) && $object->status == $object::STATUS_VALIDATED) {
- print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&token='.newToken().'&mode=init#formmailbeforetitle');
- }
-
- // Back to draft
- if ($object->status == $object::STATUS_VALIDATED) {
- print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_setdraft&confirm=yes&token='.newToken(), '', $permissiontoadd);
- }
-
- // Modify
- //print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoadd);
-
- // Validate
- if ($object->status == $object::STATUS_DRAFT) {
- if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) {
- print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=confirm_validate&confirm=yes&token='.newToken(), '', $permissiontoadd);
- } else {
- $langs->load("errors");
- print dolGetButtonAction($langs->trans("ErrorAddAtLeastOneLineFirst"), $langs->trans("Validate"), 'default', '#', '', 0);
- }
- }
-
- // Clone
- if ($permissiontoadd) {
- print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid) ? '&socid='.$object->socid : '').'&action=clone&token='.newToken(), '', $permissiontoadd);
- }
-
- /*
- // Disable / Enable
- if ($permissiontoadd) {
- if ($object->status == $object::STATUS_ENABLED) {
- print dolGetButtonAction('', $langs->trans('Disable'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=disable&token='.newToken(), '', $permissiontoadd);
- } else {
- print dolGetButtonAction('', $langs->trans('Enable'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=enable&token='.newToken(), '', $permissiontoadd);
- }
- }
- if ($permissiontoadd) {
- if ($object->status == $object::STATUS_VALIDATED) {
- print dolGetButtonAction('', $langs->trans('Cancel'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=close&token='.newToken(), '', $permissiontoadd);
- } else {
- print dolGetButtonAction('', $langs->trans('Re-Open'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen&token='.newToken(), '', $permissiontoadd);
- }
- }
- */
-
- // Delete (with preloaded confirm popup)
- $deleteUrl = $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken();
- $buttonId = 'action-delete-no-ajax';
- if ($conf->use_javascript_ajax && empty($conf->dol_use_jmobile)) { // We can use preloaded confirm if not jmobile
- $deleteUrl = '';
- $buttonId = 'action-delete';
- }
- $params = array();
- print dolGetButtonAction('', $langs->trans("Delete"), 'delete', $deleteUrl, $buttonId, $permissiontodelete, $params);
- }
- print '
'."\n";
- }
-
-
- // Select mail models is same action as presend
- if (GETPOST('modelselected')) {
- $action = 'presend';
- }
-
- if ($action != 'presend') {
- print '';
- print '
'; // ancre
-
- $includedocgeneration = 1;
-
- // Documents
-
- $object->element = "diffusion";
- if ($includedocgeneration) {
- $objref = dol_sanitizeFileName($object->ref);
- $relativepath = $objref.'/'.$objref.'.pdf';
- $filedir = $conf->diffusionplans->dir_output.'/'.$object->element.'/'.$objref;
- $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
- $genallowed = $permissiontoread; // If you can read, you can build the PDF to read content
- $delallowed = $permissiontoadd; // If you can create/edit, you can remove a file on card
- print $formfile->showdocuments('diffusionplans:Diffusion', $object->element.'/'.$objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang);
- }
- /*
- // Show links to link elements
- $object->element = "diffusion";
- $tmparray = $form->showLinkToObjectBlock($object, array(), array('diffusion'), 1);
- if (is_array($tmparray)) {
- $linktoelem = $tmparray['linktoelem'];
- $htmltoenteralink = $tmparray['htmltoenteralink'];
- print $htmltoenteralink;
- $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
- } else {
- // backward compatibility
- $somethingshown = $form->showLinkedObjectBlock($object, $tmparray);
- }
- */
- print '
';
-
- $MAXEVENT = 10;
-
- $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/diffusionplans/diffusion_agenda.php', 1).'?id='.$object->id);
-
- $includeeventlist = 0;
-
- // List of actions on element
- if ($includeeventlist) {
- include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
- $formactions = new FormActions($db);
- $somethingshown = $formactions->showactions($object, $object->element.'@'.$object->module, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
- }
-
- print '
';
- }
-
- //Select mail models is same action as presend
- if (GETPOST('modelselected')) {
- $action = 'presend';
- }
-
- // Presend form
- $modelmail = 'diffusion';
- $defaulttopic = 'InformationMessage';
- $diroutput = $conf->diffusionplans->dir_output;
- $trackid = 'diffusion'.$object->id;
-
- include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
-}
-
-// End of page
-llxFooter();
-$db->close();
diff --git a/diffusion_list.php b/diffusion_list.php
index 7219fa3..60d39ab 100644
--- a/diffusion_list.php
+++ b/diffusion_list.php
@@ -462,7 +462,7 @@
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_buildpath('/diffusionplans/diffusion_card.php', 1).'?id='.((int) $id));
+header("Location: ".dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.((int) $id));
exit;
}
@@ -561,7 +561,7 @@
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
$newcardbutton .= dolGetButtonTitleSeparator();
-$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/diffusionplans/diffusion_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
+$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index f6a2200..8b40f7b 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -151,3 +151,20 @@ methodHand = Hand delivered
methodLetter = Send by letter
methodMail = Send by email
or = or
+Bordereaudoc = Delivery slip
+Bordereaudocs = Delivery slips
+BordereaudocCard = Delivery slip card
+BordereaudocNew = New delivery slip
+BordereaudocList = List of delivery slips
+BordereaudocTitle = Title
+BordereaudocRecipients = Recipients
+BordereaudocSendEmail = Send by email
+BordereaudocSendMail = Send by mail
+BordereaudocSendHand = Hand delivery
+BordereaudocActive = Attached
+BordereaudocProjectRequired = A project is mandatory to validate the delivery slip.
+BordereaudocAddRecipients = Add project recipients
+BordereaudocFiles = Delivery slip files
+BordereaudocValidated = Delivery slip validated
+BordereaudocDelivered = Delivery slip marked as delivered
+BordereaudocClosed = Delivery slip archived
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index c3bea5c..71900ff 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -151,3 +151,20 @@ methodHand = Remis en main propre
methodLetter = Envoyer par courrier
methodMail = Envoyer par e-mail
or = ou
+Bordereaudoc = Bordereau d'envoi
+Bordereaudocs = Bordereaux d'envoi
+BordereaudocCard = Fiche bordereau d'envoi
+BordereaudocNew = Nouveau bordereau d'envoi
+BordereaudocList = Liste des bordereaux d'envoi
+BordereaudocTitle = Titre
+BordereaudocRecipients = Destinataires
+BordereaudocSendEmail = Envoi par e-mail
+BordereaudocSendMail = Envoi par courrier
+BordereaudocSendHand = Remis en main propre
+BordereaudocActive = Lié au bordereau
+BordereaudocProjectRequired = Un projet est obligatoire pour valider le bordereau.
+BordereaudocAddRecipients = Ajouter les contacts du projet
+BordereaudocFiles = Fichiers du bordereau
+BordereaudocValidated = Bordereau validé
+BordereaudocDelivered = Bordereau marqué comme diffusé/remis
+BordereaudocClosed = Bordereau archivé
diff --git a/lib/diffusionplans_diffusion.lib.php b/lib/diffusionplans_diffusion.lib.php
index 01dbc9a..7bd7c5e 100644
--- a/lib/diffusionplans_diffusion.lib.php
+++ b/lib/diffusionplans_diffusion.lib.php
@@ -41,7 +41,7 @@ function diffusionPrepareHead($object)
$h = 0;
$head = array();
- $head[$h][0] = dol_buildpath("/diffusionplans/diffusion_card.php", 1).'?id='.$object->id;
+$head[$h][0] = dol_buildpath("/diffusionplans/bordereaudoc_card.php", 1).'?id='.$object->id;
$head[$h][1] = $langs->trans("Diffusion");
$head[$h][2] = 'card';
$h++;
diff --git a/sql/llx_bordereaudoc.key.sql b/sql/llx_bordereaudoc.key.sql
new file mode 100644
index 0000000..a690529
--- /dev/null
+++ b/sql/llx_bordereaudoc.key.sql
@@ -0,0 +1,7 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- GNU GPL v3
+
+ALTER TABLE llx_bordereaudoc ADD INDEX idx_bordereaudoc_entity (entity);
+ALTER TABLE llx_bordereaudoc ADD INDEX idx_bordereaudoc_project (fk_project);
+ALTER TABLE llx_bordereaudoc ADD UNIQUE INDEX uk_bordereaudoc_ref (ref, entity);
diff --git a/sql/llx_bordereaudoc.sql b/sql/llx_bordereaudoc.sql
new file mode 100644
index 0000000..fd819e0
--- /dev/null
+++ b/sql/llx_bordereaudoc.sql
@@ -0,0 +1,31 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- 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/.
+
+CREATE TABLE llx_bordereaudoc(
+rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL,
+ref varchar(128) DEFAULT '(PROV)' NOT NULL,
+title varchar(255),
+description longtext,
+fk_project integer NOT NULL,
+statut integer NOT NULL DEFAULT 0,
+entity integer NOT NULL DEFAULT 1,
+datec datetime,
+tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+fk_user_creat integer,
+fk_user_modif integer,
+import_key varchar(14),
+last_main_doc varchar(255),
+model_pdf varchar(255)
+) ENGINE=innodb;
diff --git a/sql/llx_bordereaudoc_contact.key.sql b/sql/llx_bordereaudoc_contact.key.sql
new file mode 100644
index 0000000..c5c74ca
--- /dev/null
+++ b/sql/llx_bordereaudoc_contact.key.sql
@@ -0,0 +1,7 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- GNU GPL v3
+
+ALTER TABLE llx_bordereaudoc_contact ADD INDEX idx_bordereaudoc_contact_entity (entity);
+ALTER TABLE llx_bordereaudoc_contact ADD INDEX idx_bordereaudoc_contact_parent (fk_bordereaudoc);
+ALTER TABLE llx_bordereaudoc_contact ADD INDEX idx_bordereaudoc_contact_contact (fk_contact);
diff --git a/sql/llx_bordereaudoc_contact.sql b/sql/llx_bordereaudoc_contact.sql
new file mode 100644
index 0000000..261795b
--- /dev/null
+++ b/sql/llx_bordereaudoc_contact.sql
@@ -0,0 +1,31 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- 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/.
+
+CREATE TABLE llx_bordereaudoc_contact(
+rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL,
+fk_bordereaudoc integer NOT NULL,
+fk_soc integer,
+fk_contact integer,
+nature_contact varchar(64),
+type_contact varchar(64),
+send_email integer NOT NULL DEFAULT 1,
+send_mail integer NOT NULL DEFAULT 0,
+send_hand integer NOT NULL DEFAULT 0,
+active integer NOT NULL DEFAULT 1,
+entity integer NOT NULL DEFAULT 1,
+datec datetime,
+tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+fk_user_creat integer
+) ENGINE=innodb;
diff --git a/sql/llx_bordereaudoc_file.key.sql b/sql/llx_bordereaudoc_file.key.sql
new file mode 100644
index 0000000..bcf9dd1
--- /dev/null
+++ b/sql/llx_bordereaudoc_file.key.sql
@@ -0,0 +1,7 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- GNU GPL v3
+
+ALTER TABLE llx_bordereaudoc_file ADD INDEX idx_bordereaudoc_file_entity (entity);
+ALTER TABLE llx_bordereaudoc_file ADD INDEX idx_bordereaudoc_file_parent (fk_bordereaudoc);
+ALTER TABLE llx_bordereaudoc_file ADD UNIQUE INDEX uk_bordereaudoc_file_hash (hash, entity);
diff --git a/sql/llx_bordereaudoc_file.sql b/sql/llx_bordereaudoc_file.sql
new file mode 100644
index 0000000..6b77445
--- /dev/null
+++ b/sql/llx_bordereaudoc_file.sql
@@ -0,0 +1,27 @@
+-- Copyright (C) 2025 Pierre ARDOIN
+--
+-- 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/.
+
+CREATE TABLE llx_bordereaudoc_file(
+rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL,
+fk_bordereaudoc integer NOT NULL,
+filename varchar(255) NOT NULL,
+filepath varchar(255) NOT NULL,
+hash varchar(64) NOT NULL,
+is_visible integer NOT NULL DEFAULT 1,
+entity integer NOT NULL DEFAULT 1,
+datec datetime,
+tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+fk_user_creat integer
+) ENGINE=innodb;
From 3ee88bda2d9fb154b789f8407433009ce212b6a2 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 17:18:44 +0100
Subject: [PATCH 02/25] =?UTF-8?q?Am=C3=A9liorer=20l'affichage=20et=20l'?=
=?UTF-8?q?=C3=A9dition=20de=20la=20fiche=20bordereaudoc?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
bordereaudoc_card.php | 274 +++++++++++++++++++++++++-----------------
1 file changed, 161 insertions(+), 113 deletions(-)
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index 6476861..ef558bf 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -24,33 +24,33 @@
// Load Dolibarr environment
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
- $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
+$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
- $i--;
- $j--;
+$i--;
+$j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
- $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
+$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
- $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
+$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
if (!$res && file_exists("../main.inc.php")) {
- $res = @include "../main.inc.php";
+$res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
- $res = @include "../../main.inc.php";
+$res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
- $res = @include "../../../main.inc.php";
+$res = @include "../../../main.inc.php";
}
if (!$res) {
- die("Include of main fails");
+die("Include of main fails");
}
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
@@ -59,6 +59,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
dol_include_once('/diffusionplans/class/bordereaudoc.class.php');
@@ -93,6 +94,10 @@
accessforbidden();
}
+if (empty($action) && empty($id) && empty($ref)) {
+ $action = 'create';
+}
+
// Fetch object
if (!empty($id) || !empty($ref)) {
$object->fetch($id, $ref);
@@ -111,128 +116,133 @@
}
if (empty($reshook)) {
if ($action === 'add' && $permissiontoadd) {
- $object->ref = GETPOST('ref', 'alpha');
- $object->title = GETPOST('title', 'alpha');
- $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
- $object->fk_project = GETPOSTINT('fk_project');
-
- $result = $object->create($user);
- if ($result > 0) {
- if (!empty($backtopage)) {
- header('Location: '.$backtopage);
- exit;
- }
- header('Location: '.dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id);
- exit;
- }
- setEventMessages($object->error, $object->errors, 'errors');
- $action = 'create';
+ $object->ref = GETPOST('ref', 'alpha');
+ $object->title = GETPOST('title', 'alpha');
+ $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
+ $object->fk_project = GETPOSTINT('fk_project');
+
+ $result = $object->create($user);
+ if ($result > 0) {
+ if (!empty($backtopage)) {
+ header('Location: '.$backtopage);
+ exit;
+ }
+ header('Location: '.dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id);
+ exit;
+ }
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = 'create';
}
if ($action === 'update' && $permissiontoadd && $object->id > 0) {
- $object->title = GETPOST('title', 'alpha');
- $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
- $object->fk_project = GETPOSTINT('fk_project');
- $object->fk_user_modif = $user->id;
- $result = $object->update($user);
- if ($result > 0) {
- setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
- $action = 'view';
- } else {
- setEventMessages($object->error, $object->errors, 'errors');
- $action = 'edit';
- }
+ if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
+ setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
+ $action = 'view';
+ } else {
+ $object->title = GETPOST('title', 'alpha');
+ $object->description = dol_htmlcleanlastbr(GETPOST('description', 'restricthtml'));
+ $object->fk_project = GETPOSTINT('fk_project');
+ $object->fk_user_modif = $user->id;
+ $result = $object->update($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $action = 'edit';
+ }
+ }
}
if ($action === 'confirm_delete' && GETPOST('confirm', 'alpha') === 'yes' && $permissiondelete && $object->id > 0) {
- $result = $object->delete($user);
- if ($result > 0) {
- header('Location: '.dol_buildpath('/diffusionplans/diffusion_list.php', 1));
- exit;
- }
- setEventMessages($object->error, $object->errors, 'errors');
+ $result = $object->delete($user);
+ if ($result > 0) {
+ header('Location: '.dol_buildpath('/diffusionplans/diffusion_list.php', 1));
+ exit;
+ }
+ setEventMessages($object->error, $object->errors, 'errors');
}
if ($action === 'confirm_validate' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontovalidate && $object->id > 0) {
- $result = $object->validate($user);
- if ($result > 0) {
- setEventMessages($langs->trans('BordereaudocValidated'), null, 'mesgs');
- $action = 'view';
- } else {
- setEventMessages($object->error, $object->errors, 'errors');
- }
+ $result = $object->validate($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocValidated'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if ($action === 'confirm_delivered' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontoarchive && $object->id > 0) {
- $result = $object->setDelivered($user);
- if ($result > 0) {
- setEventMessages($langs->trans('BordereaudocDelivered'), null, 'mesgs');
- $action = 'view';
- } else {
- setEventMessages($object->error, $object->errors, 'errors');
- }
+ $result = $object->setDelivered($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocDelivered'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if ($action === 'confirm_close' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontoarchive && $object->id > 0) {
- $result = $object->setClosed($user);
- if ($result > 0) {
- setEventMessages($langs->trans('BordereaudocClosed'), null, 'mesgs');
- $action = 'view';
- } else {
- setEventMessages($object->error, $object->errors, 'errors');
- }
+ $result = $object->setClosed($user);
+ if ($result > 0) {
+ setEventMessages($langs->trans('BordereaudocClosed'), null, 'mesgs');
+ $action = 'view';
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if ($action === 'builddoc' && $permissiontoread && $object->id > 0) {
- $model = GETPOST('model', 'alpha');
- if (empty($model)) {
- $model = $object->model_pdf ? $object->model_pdf : 'standard';
- }
- if ($model !== $object->model_pdf) {
- $object->model_pdf = $model;
- $object->update($user);
- }
-
- $result = $object->generateDocument($model, $langs);
- if ($result <= 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- }
+ $model = GETPOST('model', 'alpha');
+ if (empty($model)) {
+ $model = $object->model_pdf ? $object->model_pdf : 'standard';
+ }
+ if ($model !== $object->model_pdf) {
+ $object->model_pdf = $model;
+ $object->update($user);
+ }
+
+ $result = $object->generateDocument($model, $langs);
+ if ($result <= 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
- require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
-
- if (empty($object->last_main_doc)) {
- $object->generateDocument($object->model_pdf ? $object->model_pdf : 'standard', $langs);
- }
-
- $filepath = dol_buildpath('/custom/diffusionplans/documents/'.$object->ref, 0);
- $filename = dol_sanitizeFileName($object->ref.'.pdf');
- $fullpath = $filepath.'/'.$filename;
-
- $recipients = array();
- $lines = $object->getRecipients(1);
- foreach ($lines as $line) {
- if (!empty($line->send_email) && !empty($line->fk_contact)) {
- $contact = new Contact($db);
- if ($contact->fetch($line->fk_contact) > 0 && !empty($contact->email)) {
- $recipients[] = $contact->email;
- }
- }
- }
-
- if (empty($recipients)) {
- setEventMessages($langs->trans('ErrorNoEMailRecipientSelected'), null, 'errors');
- } else {
- $subject = $langs->trans('Bordereaudoc').' '.$object->ref;
- $body = dol_htmlentitiesbr($object->description);
- $mailfile = new CMailFile($subject, implode(',', $recipients), $user->email, $body, array($fullpath), array($filename), array('application/pdf'));
- if ($mailfile->sendfile()) {
- setEventMessages($langs->trans('MailSuccessfulySent', implode(',', $recipients)), null, 'mesgs');
- } else {
- setEventMessages($mailfile->error, $mailfile->errors, 'errors');
- }
- }
+ require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+
+ if (empty($object->last_main_doc)) {
+ $object->generateDocument($object->model_pdf ? $object->model_pdf : 'standard', $langs);
+ }
+
+ $filepath = dol_buildpath('/custom/diffusionplans/documents/'.$object->ref, 0);
+ $filename = dol_sanitizeFileName($object->ref.'.pdf');
+ $fullpath = $filepath.'/'.$filename;
+
+ $recipients = array();
+ $lines = $object->getRecipients(1);
+ foreach ($lines as $line) {
+ if (!empty($line->send_email) && !empty($line->fk_contact)) {
+ $contact = new Contact($db);
+ if ($contact->fetch($line->fk_contact) > 0 && !empty($contact->email)) {
+ $recipients[] = $contact->email;
+ }
+ }
+ }
+
+ if (empty($recipients)) {
+ setEventMessages($langs->trans('ErrorNoEMailRecipientSelected'), null, 'errors');
+ } else {
+ $subject = $langs->trans('Bordereaudoc').' '.$object->ref;
+ $body = dol_htmlentitiesbr($object->description);
+ $mailfile = new CMailFile($subject, implode(',', $recipients), $user->email, $body, array($fullpath), array($filename), array('application/pdf'));
+ if ($mailfile->sendfile()) {
+ setEventMessages($langs->trans('MailSuccessfulySent', implode(',', $recipients)), null, 'mesgs');
+ } else {
+ setEventMessages($mailfile->error, $mailfile->errors, 'errors');
+ }
+ }
}
}
@@ -277,6 +287,10 @@
}
if ($object->id > 0) {
+ if ($action === 'edit' && (((int) $object->status) !== Bordereaudoc::STATUS_DRAFT || !$permissiontoadd)) {
+ $action = 'view';
+ }
+
$head = array();
$head[0][0] = dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id;
$head[0][1] = $langs->trans('Card');
@@ -291,14 +305,47 @@
$projectstatic->fetch($object->fk_project);
$morehtmlref .= ' '.$projectstatic->getNomUrl(1);
}
+
+ $editmode = ($action === 'edit');
+ if ($editmode) {
+ print '';
+ } else {
+ print '';
+ }
+
dol_fiche_end();
}
@@ -306,3 +353,4 @@
dol_print_footer();
llxFooter();
$db->close();
+
From cc71091355972ba21b3489518be3ab692b85c5f7 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 17:25:50 +0100
Subject: [PATCH 03/25] Add action toolbar to bordereaudoc card
---
bordereaudoc_card.php | 46 ++++++++++++++++++++++++++++++---
langs/en_US/diffusionplans.lang | 7 +++++
langs/fr_FR/diffusionplans.lang | 7 +++++
3 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index ef558bf..85643cf 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -286,17 +286,32 @@
exit;
}
+
if ($object->id > 0) {
if ($action === 'edit' && (((int) $object->status) !== Bordereaudoc::STATUS_DRAFT || !$permissiontoadd)) {
$action = 'view';
}
+ $confirmform = '';
+ if ($action === 'valid' && $permissiontovalidate && $object->status == Bordereaudoc::STATUS_DRAFT) {
+ $confirmform = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateBordereaudoc'), $langs->trans('ConfirmValidateBordereaudoc'), 'confirm_validate', '', 0, 1);
+ }
+ if ($action === 'deliver' && $permissiontoarchive && $object->status == Bordereaudoc::STATUS_VALIDATED) {
+ $confirmform = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeliverBordereaudoc'), $langs->trans('ConfirmDeliverBordereaudoc'), 'confirm_delivered', '', 0, 1);
+ }
+ if ($action === 'close' && $permissiontoarchive && $object->status == Bordereaudoc::STATUS_DELIVERED) {
+ $confirmform = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CloseBordereaudoc'), $langs->trans('ConfirmCloseBordereaudoc'), 'confirm_close', '', 0, 1);
+ }
+
$head = array();
$head[0][0] = dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.$object->id;
$head[0][1] = $langs->trans('Card');
$head[0][2] = 'card';
dol_fiche_head($head, 'card', $langs->trans('Bordereaudoc'), -1, 'fa-paper-plane');
+ if (!empty($confirmform)) {
+ print $confirmform;
+ }
$linkback = ''.$langs->trans('BackToList').' ';
$morehtmlref = '';
@@ -339,14 +354,37 @@
print '';
print '';
} else {
- print '';
+ if ($object->status == Bordereaudoc::STATUS_DRAFT && $permissiontovalidate) {
+ $buttons[] = ''.$langs->trans('Validate').' ';
+ }
+ if ($object->status == Bordereaudoc::STATUS_VALIDATED && $permissiontoarchive) {
+ $buttons[] = ''.$langs->trans('MarkDelivered').' ';
+ }
+ if ($object->status == Bordereaudoc::STATUS_DELIVERED && $permissiontoarchive) {
+ $buttons[] = ''.$langs->trans('Close').' ';
+ }
+ if ($object->status >= Bordereaudoc::STATUS_VALIDATED && $permissiontosend) {
+ $buttons[] = ''.$langs->trans('SendMail').' ';
+ }
+ if ($permissiontoread) {
+ $buttons[] = ''.$langs->trans('GeneratePDF').' ';
+ if (!empty($object->last_main_doc)) {
+ $modulepart = 'diffusionplans';
+ $filename = basename($object->last_main_doc);
+ $filelink = DOL_URL_ROOT.'/document.php?modulepart='.urlencode($modulepart).'&file='.urlencode($object->last_main_doc);
+ $buttons[] = ''.$langs->trans('Download').' ';
+ }
+ }
+
+ print ''.implode(' ', $buttons).'
';
}
- dol_fiche_end();
+
+dol_fiche_end();
}
// Footer
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index 8b40f7b..52b1d5f 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -168,3 +168,10 @@ BordereaudocFiles = Delivery slip files
BordereaudocValidated = Delivery slip validated
BordereaudocDelivered = Delivery slip marked as delivered
BordereaudocClosed = Delivery slip archived
+ValidateBordereaudoc = Validate the delivery slip
+ConfirmValidateBordereaudoc = Do you confirm validation of this delivery slip?
+DeliverBordereaudoc = Mark delivery slip as delivered
+ConfirmDeliverBordereaudoc = Do you confirm to mark this delivery slip as delivered?
+CloseBordereaudoc = Archive the delivery slip
+ConfirmCloseBordereaudoc = Do you confirm to archive this delivery slip?
+MarkDelivered = Mark as delivered
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index 71900ff..f3be6bb 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -168,3 +168,10 @@ BordereaudocFiles = Fichiers du bordereau
BordereaudocValidated = Bordereau validé
BordereaudocDelivered = Bordereau marqué comme diffusé/remis
BordereaudocClosed = Bordereau archivé
+ValidateBordereaudoc = Valider le bordereau
+ConfirmValidateBordereaudoc = Confirmez-vous la validation de ce bordereau ?
+DeliverBordereaudoc = Marquer le bordereau comme remis
+ConfirmDeliverBordereaudoc = Confirmez-vous le passage de ce bordereau en remis ?
+CloseBordereaudoc = Archiver le bordereau
+ConfirmCloseBordereaudoc = Confirmez-vous l'archivage de ce bordereau ?
+MarkDelivered = Marquer comme remis
From 0dcffae980f5eea6cb529f027f9b259f5ea4ab30 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 17:33:05 +0100
Subject: [PATCH 04/25] Add recipient management to bordereaudoc card
---
bordereaudoc_card.php | 139 +++++++++++++++++++++++++++++++-
class/bordereaudoc.class.php | 65 +++++++++++----
langs/en_US/diffusionplans.lang | 4 +
langs/fr_FR/diffusionplans.lang | 4 +
4 files changed, 194 insertions(+), 18 deletions(-)
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index 85643cf..b2f9546 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -59,6 +59,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
dol_include_once('/diffusionplans/class/bordereaudoc.class.php');
@@ -123,6 +124,10 @@
$result = $object->create($user);
if ($result > 0) {
+ if (!empty($object->fk_project)) {
+ $object->addProjectExternalContacts($user);
+ }
+
if (!empty($backtopage)) {
header('Location: '.$backtopage);
exit;
@@ -209,6 +214,46 @@
}
}
+ if ($action === 'addprojectcontacts' && $permissiontoadd && $object->id > 0) {
+ if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
+ setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
+ } else {
+ $added = $object->addProjectExternalContacts($user);
+ if ($added >= 0) {
+ setEventMessages($langs->trans('BordereaudocAddRecipients'), null, 'mesgs');
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ }
+ $action = 'view';
+ }
+
+ if ($action === 'saverecipients' && $permissiontoadd && $object->id > 0) {
+ if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
+ setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
+ } else {
+ $sendEmail = GETPOST('send_email', 'array');
+ $sendMail = GETPOST('send_mail', 'array');
+ $sendHand = GETPOST('send_hand', 'array');
+ $active = GETPOST('active', 'array');
+
+ $lines = $object->getRecipients();
+ foreach ($lines as $line) {
+ $lineData = array(
+ 'send_email' => isset($sendEmail[$line->rowid]) ? 1 : 0,
+ 'send_mail' => isset($sendMail[$line->rowid]) ? 1 : 0,
+ 'send_hand' => isset($sendHand[$line->rowid]) ? 1 : 0,
+ 'active' => isset($active[$line->rowid]) ? 1 : 0,
+ );
+ $object->updateRecipientFlags($line->rowid, $lineData);
+ }
+
+ setEventMessages($langs->trans('BordereaudocRecipientsUpdated'), null, 'mesgs');
+ }
+
+ $action = 'view';
+ }
+
if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
@@ -380,11 +425,99 @@
}
}
- print ''.implode(' ', $buttons).'
';
+ print ''.implode(' ', $buttons).'
';
}
-
-dol_fiche_end();
+ $recipients = $object->getRecipients();
+ $caneditrecipients = ((int) $object->status === Bordereaudoc::STATUS_DRAFT && $permissiontoadd);
+
+ print '';
+ print load_fiche_titre($langs->trans('BordereaudocRecipients'), '', 'fa-address-book');
+
+ if ($caneditrecipients) {
+ print '
';
+ }
+
+ print '
';
+ print '
';
+
+ dol_fiche_end();
}
// Footer
diff --git a/class/bordereaudoc.class.php b/class/bordereaudoc.class.php
index a9acdab..e7f68b8 100644
--- a/class/bordereaudoc.class.php
+++ b/class/bordereaudoc.class.php
@@ -153,11 +153,11 @@ public function create(User $user, $notrigger = false)
}
/**
- * Validate object
- *
- * @param User $user Current user
- * @return int
- */
+ * Validate object
+ *
+ * @param User $user Current user
+ * @return int
+ */
public function validate(User $user)
{
if (empty($this->fk_project)) {
@@ -177,11 +177,11 @@ public function validate(User $user)
}
/**
- * Set status back to draft
- *
- * @param User $user Current user
- * @return int
- */
+ * Set status back to draft
+ *
+ * @param User $user Current user
+ * @return int
+ */
public function setDraft(User $user)
{
$this->status = self::STATUS_DRAFT;
@@ -191,11 +191,11 @@ public function setDraft(User $user)
}
/**
- * Mark as delivered
- *
- * @param User $user Current user
- * @return int
- */
+ * Mark as delivered
+ *
+ * @param User $user Current user
+ * @return int
+ */
public function setDelivered(User $user)
{
$this->status = self::STATUS_DELIVERED;
@@ -204,6 +204,41 @@ public function setDelivered(User $user)
return $this->update($user);
}
+ /**
+ * Add external project contacts as recipients
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function addProjectExternalContacts(User $user)
+ {
+ if (empty($this->fk_project) || empty($this->id)) {
+ return 0;
+ }
+
+ $project = new Project($this->db);
+ if ($project->fetch($this->fk_project) <= 0) {
+ return -1;
+ }
+
+ $contacts = $project->liste_contact(-1, 'external');
+ if (empty($contacts)) {
+ return 0;
+ }
+
+ $added = 0;
+ foreach ($contacts as $contact) {
+ if ($this->recipientExists($contact['id'])) {
+ continue;
+ }
+
+ $this->addRecipient($user, $contact['socid'], $contact['id'], $contact['libelle_fonction'], 'External', 1, 0, 0);
+ $added++;
+ }
+
+ return $added;
+ }
+
/**
* Close object
*
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index 52b1d5f..61a7f43 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -162,6 +162,10 @@ BordereaudocSendEmail = Send by email
BordereaudocSendMail = Send by mail
BordereaudocSendHand = Hand delivery
BordereaudocActive = Attached
+BordereaudocContactNature = Contact nature
+BordereaudocContactType = Contact type
+BordereaudocDetach = Detach
+BordereaudocRecipientsUpdated = Recipients updated
BordereaudocProjectRequired = A project is mandatory to validate the delivery slip.
BordereaudocAddRecipients = Add project recipients
BordereaudocFiles = Delivery slip files
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index f3be6bb..4ffca09 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -162,6 +162,10 @@ BordereaudocSendEmail = Envoi par e-mail
BordereaudocSendMail = Envoi par courrier
BordereaudocSendHand = Remis en main propre
BordereaudocActive = Lié au bordereau
+BordereaudocContactNature = Nature du contact
+BordereaudocContactType = Type de contact
+BordereaudocDetach = Dissocier
+BordereaudocRecipientsUpdated = Destinataires mis à jour
BordereaudocProjectRequired = Un projet est obligatoire pour valider le bordereau.
BordereaudocAddRecipients = Ajouter les contacts du projet
BordereaudocFiles = Fichiers du bordereau
From 395d900def5a4a04e2ecb430aaf8a99e0b08fd89 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 18:26:16 +0100
Subject: [PATCH 05/25] Add document handling for bordereaudoc
---
bordereaudoc_card.php | 108 +++++++++--
class/bordereaudoc.class.php | 322 +++++++++++++++++++++++++-------
langs/en_US/diffusionplans.lang | 4 +
langs/fr_FR/diffusionplans.lang | 4 +
4 files changed, 361 insertions(+), 77 deletions(-)
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index b2f9546..fb29dc6 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -58,6 +58,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
@@ -80,6 +81,7 @@
$object = new Bordereaudoc($db);
$form = new Form($db);
$formproject = new FormProjets($db);
+$formfile = new FormFile($db);
$hookmanager = new HookManager($db);
$hookmanager->initHooks(array('bordereaudoccard', 'globalcard'));
@@ -96,12 +98,27 @@
}
if (empty($action) && empty($id) && empty($ref)) {
- $action = 'create';
+$action = 'create';
}
// Fetch object
if (!empty($id) || !empty($ref)) {
- $object->fetch($id, $ref);
+$object->fetch($id, $ref);
+}
+
+$upload_dir = '';
+$modulepart = 'diffusionplans';
+$relativepath = '';
+if ($object->id > 0) {
+$upload_dir = $object->getDocumentsDirectory();
+$relativepath = 'bordereaudoc/'.dol_sanitizeFileName($object->ref);
+}
+
+if ($object->id > 0) {
+$permissiontoaddfile = $permissiontoadd;
+$param = '?id='.$object->id;
+include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_pre_headers.tpl.php';
+$object->syncDocumentIndex($user);
}
// Actions
@@ -228,11 +245,11 @@
$action = 'view';
}
- if ($action === 'saverecipients' && $permissiontoadd && $object->id > 0) {
- if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
- setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
- } else {
- $sendEmail = GETPOST('send_email', 'array');
+if ($action === 'saverecipients' && $permissiontoadd && $object->id > 0) {
+if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
+setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
+} else {
+$sendEmail = GETPOST('send_email', 'array');
$sendMail = GETPOST('send_mail', 'array');
$sendHand = GETPOST('send_hand', 'array');
$active = GETPOST('active', 'array');
@@ -249,10 +266,26 @@
}
setEventMessages($langs->trans('BordereaudocRecipientsUpdated'), null, 'mesgs');
- }
+}
- $action = 'view';
- }
+$action = 'view';
+}
+
+if ($action === 'savefiles' && $permissiontoadd && $object->id > 0) {
+if ((int) $object->status !== Bordereaudoc::STATUS_DRAFT) {
+setEventMessages($langs->trans('ErrorForbidden'), null, 'errors');
+} else {
+$visible = GETPOST('is_visible', 'array');
+$lines = $object->getDocumentIndex();
+foreach ($lines as $line) {
+$flag = isset($visible[$line->rowid]) ? 1 : 0;
+$object->updateFileVisibility($line->rowid, $flag);
+}
+setEventMessages($langs->trans('BordereaudocFilesUpdated'), null, 'mesgs');
+}
+
+$action = 'view';
+}
if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
@@ -517,7 +550,60 @@
print '';
print '';
- dol_fiche_end();
+ $caneditfiles = ((int) $object->status === Bordereaudoc::STATUS_DRAFT && $permissiontoadd);
+ $filedir = $upload_dir;
+ $urlsource = $_SERVER['PHP_SELF'].'?id='.$object->id;
+
+ print '';
+ print load_fiche_titre($langs->trans('BordereaudocFiles'), '', 'fa-files-o');
+ print $formfile->showdocuments($modulepart, $relativepath, $filedir, $urlsource, $caneditfiles, $caneditfiles, $object->model_pdf, 1, 0, 0, 0, 0, '', '', '', 1);
+
+ $doclines = $object->getDocumentIndex();
+ if (!empty($doclines)) {
+ if ($caneditfiles) {
+ print '
';
+ }
+ } else {
+ print '
'.$langs->trans('BordereaudocNoFiles').'
';
+ }
+
+ print '
';
+
+dol_fiche_end();
}
// Footer
diff --git a/class/bordereaudoc.class.php b/class/bordereaudoc.class.php
index e7f68b8..9b664e4 100644
--- a/class/bordereaudoc.class.php
+++ b/class/bordereaudoc.class.php
@@ -25,6 +25,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
/**
* Class for Bordereaudoc
@@ -32,36 +33,36 @@
class Bordereaudoc extends CommonObject
{
/**
- * @var string Module name
- */
+ * @var string Module name
+ */
public $module = 'diffusionplans';
/**
- * @var string Element name
- */
+ * @var string Element name
+ */
public $element = 'bordereaudoc';
/**
- * @var string Table without prefix
- */
+ * @var string Table without prefix
+ */
public $table_element = 'bordereaudoc';
/**
- * @var string Picto code
- */
+ * @var string Picto code
+ */
public $picto = 'fa-paper-plane';
/**
- * Status constants
- */
+ * Status constants
+ */
const STATUS_DRAFT = 0;
const STATUS_VALIDATED = 1;
const STATUS_DELIVERED = 2;
const STATUS_CLOSED = 3;
/**
- * @var array Fields definition
- */
+ * @var array Fields definition
+ */
public $fields = array(
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => '1', 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1),
'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => '1', 'position' => 10, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1),
@@ -95,10 +96,10 @@ class Bordereaudoc extends CommonObject
public $model_pdf;
/**
- * Constructor
- *
- * @param DoliDB $db Database handler
- */
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
public function __construct(DoliDB $db)
{
global $conf;
@@ -113,11 +114,11 @@ public function __construct(DoliDB $db)
}
/**
- * Get next reference for object
- *
- * @param User $user Current user
- * @return string
- */
+ * Get next reference for object
+ *
+ * @param User $user Current user
+ * @return string
+ */
public function getNextNumRef(User $user)
{
$prefix = getDolGlobalString('DIFFUSIONPLANS_BORDEREAU_REF_PREFIX', 'BRD');
@@ -126,12 +127,12 @@ public function getNextNumRef(User $user)
}
/**
- * Create object in database
- *
- * @param User $user Current user
- * @param bool $notrigger Disable triggers
- * @return int
- */
+ * Create object in database
+ *
+ * @param User $user Current user
+ * @param bool $notrigger Disable triggers
+ * @return int
+ */
public function create(User $user, $notrigger = false)
{
if (empty($this->fk_project)) {
@@ -240,25 +241,214 @@ public function addProjectExternalContacts(User $user)
}
/**
- * Close object
- *
- * @param User $user Current user
- * @return int
- */
+ * Close object
+ *
+ * @param User $user Current user
+ * @return int
+ */
public function setClosed(User $user)
{
$this->status = self::STATUS_CLOSED;
$this->fk_user_modif = $user->id;
-
+
return $this->update($user);
}
+
+ /**
+ * Get documents directory for the bordereaudoc.
+ *
+ * @return string
+ */
+ public function getDocumentsDirectory()
+ {
+ global $conf;
+
+ $entity = !empty($this->entity) ? (int) $this->entity : (int) $conf->entity;
+ if (empty($conf->diffusionplans->multidir_output[$entity])) {
+ return '';
+ }
+
+ $path = rtrim($conf->diffusionplans->multidir_output[$entity], '/').'/bordereaudoc/'.dol_sanitizeFileName($this->ref);
+ dol_mkdir($path);
+
+ return $path;
+ }
+
+ /**
+ * Synchronize filesystem files with database index.
+ *
+ * @param User $user Current user
+ * @return int
+ */
+ public function syncDocumentIndex(User $user)
+ {
+ $dir = $this->getDocumentsDirectory();
+ if (empty($dir)) {
+ return -1;
+ }
+
+ $fsFiles = dol_dir_list($dir, 'files', 0, '', '(\.meta|_preview.*\.png)$', '', '', 1);
+ $existing = $this->fetchDocumentIndex();
+ $existingMap = array();
+ $basepath = 'bordereaudoc/'.dol_sanitizeFileName($this->ref);
+
+ foreach ($existing as $line) {
+ $key = trim($line->filepath, '/').'/'.$line->filename;
+ $existingMap[$key] = $line;
+ }
+
+ $seen = array();
+ foreach ($fsFiles as $file) {
+ $relativeName = !empty($file['relativename']) ? $file['relativename'] : $file['name'];
+ $key = $basepath.'/'.ltrim($relativeName, '/');
+ $seen[$key] = 1;
+ if (!isset($existingMap[$key])) {
+ $visible = ((int) $this->status === self::STATUS_DRAFT) ? 1 : 0;
+ $this->addFileIndex($file['name'], $basepath, $visible, $user);
+ }
+ }
+
+ foreach ($existingMap as $key => $line) {
+ if (!isset($seen[$key])) {
+ $this->deleteFileIndex($line->rowid);
+ }
+ }
+
+ return 1;
+ }
+
+ /**
+ * Get indexed files for the bordereaudoc.
+ *
+ * @param int $onlyVisible Restrict to visible files
+ * @return array
+ */
+ public function getDocumentIndex($onlyVisible = 0)
+ {
+ $sql = 'SELECT rowid, fk_bordereaudoc, filename, filepath, hash, is_visible, entity';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'bordereaudoc_file';
+ $sql .= ' WHERE fk_bordereaudoc = '.((int) $this->id).' AND entity = '.((int) $this->entity);
+ if (!empty($onlyVisible)) {
+ $sql .= ' AND is_visible = 1';
+ }
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return array();
+ }
+
+ $lines = array();
+ while ($obj = $this->db->fetch_object($resql)) {
+ $lines[] = $obj;
+ }
+
+ return $lines;
+ }
+
+ /**
+ * Fetch document index without filtering.
+ *
+ * @return array
+ */
+ protected function fetchDocumentIndex()
+ {
+ return $this->getDocumentIndex(0);
+ }
+
+ /**
+ * Add index entry for a file.
+ *
+ * @param string $filename File name
+ * @param string $filepath Relative path
+ * @param int $visible Visibility flag
+ * @param User $user Current user
+ * @param string $hashValue Hash value
+ * @return int
+ */
+ public function addFileIndex($filename, $filepath, $visible, User $user, $hashValue = '')
+ {
+ if (empty($hashValue)) {
+ $hashValue = $this->generateFileHash();
+ }
+
+ $sql = 'INSERT INTO '.MAIN_DB_PREFIX."bordereaudoc_file (fk_bordereaudoc, filename, filepath, hash, is_visible, entity, datec, tms, fk_user_creat)";
+ $sql .= " VALUES (".((int) $this->id).", '".$this->db->escape($filename)."', '".$this->db->escape($filepath)."', '".$this->db->escape($hashValue)."', ".((int) $visible).", ".((int) $this->entity).", ".$this->db->idate(dol_now()).", ".$this->db->idate(dol_now()).", ".((int) $user->id).")";
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return -1;
+ }
+
+ return $this->db->last_insert_id(MAIN_DB_PREFIX.'bordereaudoc_file');
+ }
+
+ /**
+ * Delete index entry.
+ *
+ * @param int $rowid Line id
+ * @return int
+ */
+ public function deleteFileIndex($rowid)
+ {
+ $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'bordereaudoc_file WHERE rowid = '.((int) $rowid);
+ $sql .= ' AND fk_bordereaudoc = '.((int) $this->id).' AND entity = '.((int) $this->entity);
+
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return -1;
+ }
+
+ return 1;
+ }
+
+ /**
+ * Update visibility flag for an indexed file.
+ *
+ * @param int $rowid Line id
+ * @param int $visible Visibility flag
+ * @return int
+ */
+ public function updateFileVisibility($rowid, $visible)
+ {
+ $sql = 'UPDATE '.MAIN_DB_PREFIX."bordereaudoc_file SET is_visible = ".((int) $visible);
+ $sql .= ' WHERE rowid = '.((int) $rowid).' AND fk_bordereaudoc = '.((int) $this->id).' AND entity = '.((int) $this->entity);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->error = $this->db->lasterror();
+
+ return -1;
+}
+
+ return 1;
+ }
+
/**
- * Load project contacts into bordereaudoc contacts table
- *
- * @param User $user Current user
- * @return int
- */
+ * Generate secure hash for document link.
+ *
+ * @return string
+ */
+ protected function generateFileHash()
+ {
+ try {
+ return hash('sha256', bin2hex(random_bytes(32)).microtime(true).$this->id.dol_print_date(dol_now(), 'dayrfc'));
+ } catch (Exception $e) {
+ return hash('sha256', uniqid((string) $this->id, true));
+ }
+ }
+
+ /**
+ * Load project contacts into bordereaudoc contacts table
+ *
+ * @param User $user Current user
+ * @return int
+ */
public function loadProjectContacts(User $user)
{
if (empty($this->fk_project)) {
@@ -291,11 +481,11 @@ public function loadProjectContacts(User $user)
}
/**
- * Check if recipient already exists
- *
- * @param int $contactId Contact id
- * @return bool
- */
+ * Check if recipient already exists
+ *
+ * @param int $contactId Contact id
+ * @return bool
+ */
protected function recipientExists($contactId)
{
$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX."bordereaudoc_contact WHERE fk_bordereaudoc = ".((int) $this->id)." AND fk_contact =".((int) $contactId);
@@ -310,18 +500,18 @@ protected function recipientExists($contactId)
}
/**
- * Add a recipient
- *
- * @param User $user Current user
- * @param int $socid Thirdparty id
- * @param int $contactId Contact id
- * @param string $typeContact Type label
- * @param string $nature Nature label
- * @param int $email Send email flag
- * @param int $mail Send mail flag
- * @param int $hand Hand delivery flag
- * @return int
- */
+ * Add a recipient
+ *
+ * @param User $user Current user
+ * @param int $socid Thirdparty id
+ * @param int $contactId Contact id
+ * @param string $typeContact Type label
+ * @param string $nature Nature label
+ * @param int $email Send email flag
+ * @param int $mail Send mail flag
+ * @param int $hand Hand delivery flag
+ * @return int
+ */
public function addRecipient(User $user, $socid, $contactId, $typeContact = '', $nature = '', $email = 1, $mail = 0, $hand = 0)
{
$sql = 'INSERT INTO '.MAIN_DB_PREFIX."bordereaudoc_contact (datec, tms, fk_bordereaudoc, fk_soc, fk_contact, nature_contact, type_contact, send_email, send_mail, send_hand, active, entity, fk_user_creat)";
@@ -339,12 +529,12 @@ public function addRecipient(User $user, $socid, $contactId, $typeContact = '',
}
/**
- * Update recipient flags
- *
- * @param int $lineId Line id
- * @param array $data Data to update
- * @return int
- */
+ * Update recipient flags
+ *
+ * @param int $lineId Line id
+ * @param array $data Data to update
+ * @return int
+ */
public function updateRecipientFlags($lineId, array $data)
{
$fields = array();
@@ -372,11 +562,11 @@ public function updateRecipientFlags($lineId, array $data)
}
/**
- * Get recipients list
- *
- * @param int $onlyActive Restrict to active
- * @return array
- */
+ * Get recipients list
+ *
+ * @param int $onlyActive Restrict to active
+ * @return array
+ */
public function getRecipients($onlyActive = 0)
{
$sql = 'SELECT bc.rowid, bc.fk_soc, bc.fk_contact, bc.nature_contact, bc.type_contact, bc.send_email, bc.send_mail, bc.send_hand, bc.active, s.nom as socname, c.lastname, c.firstname, c.civility as civility';
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index 61a7f43..5d7ae59 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -179,3 +179,7 @@ ConfirmDeliverBordereaudoc = Do you confirm to mark this delivery slip as delive
CloseBordereaudoc = Archive the delivery slip
ConfirmCloseBordereaudoc = Do you confirm to archive this delivery slip?
MarkDelivered = Mark as delivered
+BordereaudocListed = Listed in the delivery slip
+BordereaudocDownloadLink = Public download link
+BordereaudocNoFiles = No file is indexed for this delivery slip.
+BordereaudocFilesUpdated = File list updated
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index 4ffca09..e8df8f4 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -178,4 +178,8 @@ DeliverBordereaudoc = Marquer le bordereau comme remis
ConfirmDeliverBordereaudoc = Confirmez-vous le passage de ce bordereau en remis ?
CloseBordereaudoc = Archiver le bordereau
ConfirmCloseBordereaudoc = Confirmez-vous l'archivage de ce bordereau ?
+BordereaudocListed = Listé dans le bordereau
+BordereaudocDownloadLink = Lien public de téléchargement
+BordereaudocNoFiles = Aucun fichier indexé pour ce bordereau.
+BordereaudocFilesUpdated = Liste des fichiers mise à jour
MarkDelivered = Marquer comme remis
From 33baa2dc2d684d65118dd6b22a1d870529642ef7 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 18:26:23 +0100
Subject: [PATCH 06/25] Add PDF model and email content for bordereaudoc
---
bordereaudoc_card.php | 83 +++++---
.../bordereaudoc/modules_bordereaudoc.php | 83 ++++++++
.../pdf_bordereaudoc_standard.modules.php | 192 ++++++++++++++++++
langs/en_US/diffusionplans.lang | 3 +
langs/fr_FR/diffusionplans.lang | 3 +
5 files changed, 332 insertions(+), 32 deletions(-)
create mode 100644 core/modules/bordereaudoc/modules_bordereaudoc.php
create mode 100644 core/modules/bordereaudoc/pdf_bordereaudoc_standard.modules.php
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index fb29dc6..96121cb 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -287,41 +287,60 @@
$action = 'view';
}
- if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
- require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+if ($action === 'sendemail' && $permissiontosend && $object->id > 0) {
+require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
- if (empty($object->last_main_doc)) {
- $object->generateDocument($object->model_pdf ? $object->model_pdf : 'standard', $langs);
- }
+$model = $object->model_pdf ? $object->model_pdf : 'standard';
+if (empty($object->last_main_doc)) {
+$object->generateDocument($model, $langs);
+}
- $filepath = dol_buildpath('/custom/diffusionplans/documents/'.$object->ref, 0);
- $filename = dol_sanitizeFileName($object->ref.'.pdf');
- $fullpath = $filepath.'/'.$filename;
-
- $recipients = array();
- $lines = $object->getRecipients(1);
- foreach ($lines as $line) {
- if (!empty($line->send_email) && !empty($line->fk_contact)) {
- $contact = new Contact($db);
- if ($contact->fetch($line->fk_contact) > 0 && !empty($contact->email)) {
- $recipients[] = $contact->email;
- }
- }
- }
+$objectref = dol_sanitizeFileName($object->ref);
+$basedir = !empty($conf->diffusionplans->multidir_output[$object->entity]) ? $conf->diffusionplans->multidir_output[$object->entity] : $conf->document_root[$object->entity];
+$fullpath = $basedir.'/'.$objectref.'/'.$objectref.'.pdf';
+if (!file_exists($fullpath)) {
+setEventMessages($langs->trans('ErrorFailedToLoadFile'), null, 'errors');
+} else {
+$recipients = array();
+$lines = $object->getRecipients(1);
+foreach ($lines as $line) {
+if (!empty($line->send_email) && !empty($line->fk_contact)) {
+$contact = new Contact($db);
+if ($contact->fetch($line->fk_contact) > 0 && !empty($contact->email)) {
+$recipients[] = $contact->email;
+}
+}
+}
- if (empty($recipients)) {
- setEventMessages($langs->trans('ErrorNoEMailRecipientSelected'), null, 'errors');
- } else {
- $subject = $langs->trans('Bordereaudoc').' '.$object->ref;
- $body = dol_htmlentitiesbr($object->description);
- $mailfile = new CMailFile($subject, implode(',', $recipients), $user->email, $body, array($fullpath), array($filename), array('application/pdf'));
- if ($mailfile->sendfile()) {
- setEventMessages($langs->trans('MailSuccessfulySent', implode(',', $recipients)), null, 'mesgs');
- } else {
- setEventMessages($mailfile->error, $mailfile->errors, 'errors');
- }
- }
- }
+$recipients = array_unique($recipients);
+if (empty($recipients)) {
+setEventMessages($langs->trans('ErrorNoEMailRecipientSelected'), null, 'errors');
+} else {
+$subject = $langs->trans('BordereaudocMailSubject', $object->ref);
+$template = getDolGlobalString('DIFFUSIONPLANS_BORDEREAU_MAIL_TEMPLATE', '');
+$body = $template ? $template : $langs->trans('BordereaudocMailDefaultIntro', $object->ref);
+$body .= "\n\n".dol_string_nohtmltag($object->description, '', array(), 1);
+
+$docs = $object->getDocumentIndex(1);
+if (!empty($docs)) {
+$body .= "\n\n".$langs->trans('BordereaudocMailDocuments')."\n";
+foreach ($docs as $docline) {
+$link = dol_buildpath('/custom/diffusionplans/public/bordereaudocdownload.php?hash='.$docline->hash, 2);
+$body .= '- '.$docline->filename.' : '.$link."\n";
+}
+}
+
+$htmlbody = nl2br(dol_htmlentitiesbr($body));
+$mailfile = new CMailFile($subject, implode(',', $recipients), $user->email, $htmlbody, array($fullpath), array(basename($fullpath)), array('application/pdf'), '', '', 0, 1);
+if ($mailfile->sendfile()) {
+setEventMessages($langs->trans('MailSuccessfulySent', implode(',', $recipients)), null, 'mesgs');
+} else {
+setEventMessages($mailfile->error, $mailfile->errors, 'errors');
+}
+}
+}
+}
+}
}
// View
diff --git a/core/modules/bordereaudoc/modules_bordereaudoc.php b/core/modules/bordereaudoc/modules_bordereaudoc.php
new file mode 100644
index 0000000..026fe13
--- /dev/null
+++ b/core/modules/bordereaudoc/modules_bordereaudoc.php
@@ -0,0 +1,83 @@
+
+*
+* 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 .
+*/
+
+/**
+* \file core/modules/bordereaudoc/modules_bordereaudoc.php
+* \ingroup diffusionplans
+* \brief Parent classes for bordereaudoc PDF and numbering models.
+*/
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
+require_once DOL_DOCUMENT_ROOT+'/core/class/commonnumrefgenerator.class.php';
+
+/**
+* Parent class for bordereaudoc PDF models.
+*/
+abstract class ModelePDFBordereaudoc extends CommonDocGenerator
+ {
+ /**
+ * Return list of active generation modules.
+ *
+ * @param DoliDB $db Database handler
+ * @param int $maxfilenamelength Max length of value to show
+ * @return array|int
+ */
+ public static function liste_modeles($db, $maxfilenamelength = 0)
+ {
+ $type = 'bordereaudoc';
+ $list = array();
+
+ include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+ $list = getListOfModels($db, $type, $maxfilenamelength);
+
+ return $list;
+}
+
+/**
+* Build document on disk.
+*
+* @param Bordereaudoc $object Object source to build document
+* @param Translate $outputlangs Lang output object
+* @param string $srctemplatepath Full path of source filename for generator using a template file
+* @param int $hidedetails Do not show line details
+* @param int $hidedesc Do not show desc
+* @param int $hideref Do not show ref
+* @return int
+*/
+abstract public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0);
+}
+
+/**
+* Parent class to manage numbering of Bordereaudoc.
+*/
+abstract class ModeleNumRefBordereaudoc extends CommonNumRefGenerator
+ {
+ /**
+ * Return an example of numbering.
+ *
+ * @return string
+ */
+ abstract public function getExample();
+
+ /**
+ * Return next free value.
+ *
+ * @param Bordereaudoc $object Object we need next value for
+ * @return string|int
+ */
+ abstract public function getNextValue($object);
+}
diff --git a/core/modules/bordereaudoc/pdf_bordereaudoc_standard.modules.php b/core/modules/bordereaudoc/pdf_bordereaudoc_standard.modules.php
new file mode 100644
index 0000000..fc065ea
--- /dev/null
+++ b/core/modules/bordereaudoc/pdf_bordereaudoc_standard.modules.php
@@ -0,0 +1,192 @@
+
+ *
+ * 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 .
+ */
+
+/**
+ * \file core/modules/bordereaudoc/pdf_bordereaudoc_standard.modules.php
+ * \ingroup diffusionplans
+ * \brief PDF model for bordereaudoc.
+ */
+
+dol_include_once('/diffusionplans/core/modules/bordereaudoc/modules_bordereaudoc.php');
+require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
+require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+
+class pdf_bordereaudoc_standard extends ModelePDFBordereaudoc
+{
+ /**
+ * @var DoliDB Database handler
+ */
+ public $db;
+
+ /**
+ * @var string Model name
+ */
+ public $name;
+
+ /**
+ * @var string Model description
+ */
+ public $description;
+
+ /**
+ * @var string Document type
+ */
+ public $type = 'pdf';
+
+ /**
+ * @var string Document format
+ */
+ public $format;
+
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct($db)
+ {
+ global $langs;
+
+ $this->db = $db;
+ $this->name = 'standard';
+ $this->description = 'Standard';
+ $this->option_freetext = getDolGlobalString('DIFFUSIONPLANS_FREE_TEXT', '');
+ $this->format = array(210, 297);
+
+ $langs->loadLangs(array('main', 'companies', 'projects', 'diffusionplans@diffusionplans'));
+ }
+
+ /**
+ * Write bordereaudoc PDF file
+ *
+ * @param Bordereaudoc $object Bordereaudoc
+ * @param Translate $outputlangs Output langs
+ * @param string $srctemplatepath Not used
+ * @param int $hidedetails Not used
+ * @param int $hidedesc Not used
+ * @param int $hideref Not used
+ * @return int
+ */
+ public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
+ {
+ global $conf, $langs, $mysoc;
+
+ if (empty($outputlangs)) {
+ $outputlangs = $langs;
+ }
+ $outputlangs->loadLangs(array('main', 'companies', 'projects', 'diffusionplans@diffusionplans'));
+
+ if ($mysoc->country_code) {
+ $outputlangs->load('dict');
+ }
+
+ $default_font_size = pdf_getPDFFontSize($outputlangs);
+ $objectref = dol_sanitizeFileName($object->ref);
+ $dir = (!empty($conf->diffusionplans->multidir_output[$object->entity]) ? $conf->diffusionplans->multidir_output[$object->entity] : $conf->document_root[$object->entity]).'/'.$objectref;
+ dol_mkdir($dir);
+ $file = $dir.'/'.$objectref.'.pdf';
+
+ $pdf = pdf_getInstance($this->format);
+ $default_font = pdf_getPDFFont($outputlangs);
+ $pdf->SetTitle($outputlangs->transnoentities('Bordereaudoc').' '.$object->ref);
+ $pdf->SetSubject($outputlangs->transnoentities('Bordereaudoc'));
+ $pdf->SetCreator('Dolibarr');
+ $pdf->SetAuthor($outputlangs->transnoentities($mysoc->name));
+ pdf_setPrintHeader($pdf, $outputlangs);
+ pdf_setPrintFooter($pdf, $outputlangs);
+ $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
+ $pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM);
+ $pdf->AddPage();
+ $pdf->SetFont($default_font, 'B', $default_font_size + 2);
+ $pdf->SetTextColor(0, 0, 60);
+ $pdf->MultiCell(0, 6, $outputlangs->trans('Bordereaudoc').' '.$object->ref, 0, 'L', 0, 1);
+ $pdf->Ln(2);
+
+ if (!empty($object->title)) {
+ $pdf->SetFont($default_font, '', $default_font_size + 1);
+ $pdf->MultiCell(0, 5, $object->title, 0, 'L', 0, 1);
+ $pdf->Ln(1);
+ }
+
+ $pdf->SetFont($default_font, '', $default_font_size);
+ $pdf->MultiCell(0, 5, $outputlangs->trans('Project').': '.($object->fk_project ? $object->fk_project : ''), 0, 'L', 0, 1);
+ $pdf->Ln(1);
+
+ if (!empty($object->description)) {
+ $pdf->SetFont($default_font, 'B', $default_font_size);
+ $pdf->MultiCell(0, 5, $outputlangs->trans('Description'), 0, 'L', 0, 1);
+ $pdf->SetFont($default_font, '', $default_font_size);
+ $pdf->writeHTMLCell(0, 0, '', '', $object->description, 0, 1, 0, true, 'L', true);
+ $pdf->Ln(2);
+ }
+
+ $recipients = $object->getRecipients(1);
+ if (!empty($recipients)) {
+ $pdf->SetFont($default_font, 'B', $default_font_size);
+ $pdf->MultiCell(0, 5, $outputlangs->trans('BordereaudocRecipients'), 0, 'L', 0, 1);
+ $pdf->SetFont($default_font, '', $default_font_size);
+ $table = '';
+ $table .= '';
+ $table .= ''.$outputlangs->trans('ThirdParty').' ';
+ $table .= ''.$outputlangs->trans('Contact').' ';
+ $table .= ''.$outputlangs->trans('Nature').' ';
+ $table .= ''.$outputlangs->trans('Type').' ';
+ $table .= ''.$outputlangs->trans('SendByEmail').' ';
+ $table .= ''.$outputlangs->trans('SendByMail').' ';
+ $table .= ''.$outputlangs->trans('SendByHand').' ';
+ $table .= ' ';
+ foreach ($recipients as $line) {
+ $table .= '';
+ $table .= ''.dol_escape_htmltag($line->socname).' ';
+ $table .= ''.dol_escape_htmltag(dolGetFirstLastname($line->firstname, $line->lastname)).' ';
+ $table .= ''.dol_escape_htmltag($line->nature_contact).' ';
+ $table .= ''.dol_escape_htmltag($line->type_contact).' ';
+ $table .= ''.($line->send_email ? $outputlangs->trans('Yes') : $outputlangs->trans('No')).' ';
+ $table .= ''.($line->send_mail ? $outputlangs->trans('Yes') : $outputlangs->trans('No')).' ';
+ $table .= ''.($line->send_hand ? $outputlangs->trans('Yes') : $outputlangs->trans('No')).' ';
+ $table .= ' ';
+ }
+ $table .= '
';
+ $pdf->writeHTML($table, true, false, true, false, '');
+ $pdf->Ln(2);
+ }
+
+ $docs = $object->getDocumentIndex(1);
+ if (!empty($docs)) {
+ $pdf->SetFont($default_font, 'B', $default_font_size);
+ $pdf->MultiCell(0, 5, $outputlangs->trans('BordereaudocDocuments'), 0, 'L', 0, 1);
+ $pdf->SetFont($default_font, '', $default_font_size);
+ $list = '';
+ foreach ($docs as $doc) {
+ $link = dol_buildpath('/custom/diffusionplans/public/bordereaudocdownload.php?hash='.$doc->hash, 2);
+ $list .= ''.dol_escape_htmltag($doc->filename).' - '.$link.' ';
+ }
+ $list .= ' ';
+ $pdf->writeHTML($list, true, false, true, false, '');
+ }
+
+ $pdf->Close();
+ $pdf->Output($file, 'F');
+ $object->last_main_doc = 'diffusionplans/'.$objectref.'/'.$objectref.'.pdf';
+ $object->model_pdf = $this->name;
+
+ return 1;
+ }
+}
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index 5d7ae59..7cce4fb 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -183,3 +183,6 @@ BordereaudocListed = Listed in the delivery slip
BordereaudocDownloadLink = Public download link
BordereaudocNoFiles = No file is indexed for this delivery slip.
BordereaudocFilesUpdated = File list updated
+BordereaudocMailSubject=Delivery slip %s
+BordereaudocMailDefaultIntro=Please find below the delivery slip %s and the related documents.
+BordereaudocMailDocuments=Documents available
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index e8df8f4..e7db9d5 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -183,3 +183,6 @@ BordereaudocDownloadLink = Lien public de téléchargement
BordereaudocNoFiles = Aucun fichier indexé pour ce bordereau.
BordereaudocFilesUpdated = Liste des fichiers mise à jour
MarkDelivered = Marquer comme remis
+BordereaudocMailSubject=Bordereau %s
+BordereaudocMailDefaultIntro=Veuillez trouver ci-joint le bordereau %s et les documents associés.
+BordereaudocMailDocuments=Documents disponibles
From 5a1a62079c2f013be909842003cc4c985fc3bde9 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 19:19:46 +0100
Subject: [PATCH 07/25] Add bordereaudoc list routing and menu updates
---
bordereaudoc_card.php | 20 +-
bordereaudoc_list.php | 221 ++++++
core/modules/modDiffusionPlans.class.php | 106 +--
diffusion_agenda.php | 2 +-
diffusion_document.php | 2 +-
diffusion_list.php | 941 -----------------------
6 files changed, 286 insertions(+), 1006 deletions(-)
create mode 100644 bordereaudoc_list.php
delete mode 100644 diffusion_list.php
diff --git a/bordereaudoc_card.php b/bordereaudoc_card.php
index 96121cb..783f0a8 100644
--- a/bordereaudoc_card.php
+++ b/bordereaudoc_card.php
@@ -176,14 +176,14 @@
}
}
- if ($action === 'confirm_delete' && GETPOST('confirm', 'alpha') === 'yes' && $permissiondelete && $object->id > 0) {
- $result = $object->delete($user);
- if ($result > 0) {
- header('Location: '.dol_buildpath('/diffusionplans/diffusion_list.php', 1));
- exit;
- }
- setEventMessages($object->error, $object->errors, 'errors');
- }
+if ($action === 'confirm_delete' && GETPOST('confirm', 'alpha') === 'yes' && $permissiondelete && $object->id > 0) {
+$result = $object->delete($user);
+if ($result > 0) {
+header('Location: '.dol_buildpath('/diffusionplans/bordereaudoc_list.php', 1));
+exit;
+}
+setEventMessages($object->error, $object->errors, 'errors');
+}
if ($action === 'confirm_validate' && GETPOST('confirm', 'alpha') === 'yes' && $permissiontovalidate && $object->id > 0) {
$result = $object->validate($user);
@@ -372,7 +372,7 @@
print '';
print '';
@@ -410,7 +410,7 @@
print $confirmform;
}
- $linkback = ''.$langs->trans('BackToList').' ';
+$linkback = ''.$langs->trans('BackToList').' ';
$morehtmlref = '';
if (!empty($object->fk_project)) {
$projectstatic = new Project($db);
diff --git a/bordereaudoc_list.php b/bordereaudoc_list.php
new file mode 100644
index 0000000..4a10ded
--- /dev/null
+++ b/bordereaudoc_list.php
@@ -0,0 +1,221 @@
+
+ *
+ * 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 .
+ */
+
+/**
+ * \file bordereaudoc_list.php
+ * \ingroup diffusionplans
+ * \brief List page for Bordereaudoc objects.
+ */
+
+// Load Dolibarr environment
+$res = 0;
+if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
+ $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
+}
+$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
+$tmp2 = realpath(__FILE__);
+$i = strlen($tmp) - 1;
+$j = strlen($tmp2) - 1;
+while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
+ $i--;
+ $j--;
+}
+if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
+ $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
+}
+if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
+ $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
+}
+if (!$res && file_exists("../main.inc.php")) {
+ $res = @include "../main.inc.php";
+}
+if (!$res && file_exists("../../main.inc.php")) {
+ $res = @include "../../main.inc.php";
+}
+if (!$res && file_exists("../../../main.inc.php")) {
+ $res = @include "../../../main.inc.php";
+}
+if (!$res) {
+ die("Include of main fails");
+}
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once __DIR__.'/class/bordereaudoc.class.php';
+
+// Load translation files required by the page
+$langs->loadLangs(array('diffusionplans@diffusionplans', 'projects'));
+
+// Security check
+if (empty($user->rights->diffusionplans->bordereaudoc->read)) {
+ accessforbidden();
+}
+
+$sortfield = GETPOST('sortfield', 'aZ09comma');
+$sortorder = GETPOST('sortorder', 'aZ09comma');
+$page = (int) GETPOST('page', 'int');
+if ($page < 0) {
+ $page = 0;
+}
+$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
+$offset = $limit * $page;
+
+$search_ref = GETPOST('search_ref', 'alpha');
+$search_title = GETPOST('search_title', 'alpha');
+$search_project = GETPOSTINT('search_project');
+$search_status = GETPOSTINT('search_status', -1);
+
+// Objects
+$form = new Form($db);
+$projectstatic = new Project($db);
+
+if (empty($sortfield)) {
+ $sortfield = 't.ref';
+}
+if (empty($sortorder)) {
+ $sortorder = 'ASC';
+}
+
+$statusLabels = array(
+Bordereaudoc::STATUS_DRAFT => $langs->trans('Draft'),
+Bordereaudoc::STATUS_VALIDATED => $langs->trans('Validated'),
+Bordereaudoc::STATUS_DELIVERED => $langs->trans('Delivered'),
+Bordereaudoc::STATUS_CLOSED => $langs->trans('Closed')
+);
+
+$sql = 'SELECT t.rowid, t.ref, t.title, t.fk_project, t.status, p.ref as project_ref, p.title as project_title';
+$sql .= ' FROM '.MAIN_DB_PREFIX.'bordereaudoc as t';
+$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."projet as p ON p.rowid = t.fk_project";
+$sql .= ' WHERE t.entity IN ('.getEntity('bordereaudoc').')';
+if (!empty($search_ref)) {
+ $sql .= natural_search('t.ref', $search_ref);
+}
+if (!empty($search_title)) {
+ $sql .= natural_search('t.title', $search_title);
+}
+if (!empty($search_project)) {
+ $sql .= ' AND t.fk_project = '.((int) $search_project);
+}
+if ($search_status >= 0) {
+ $sql .= ' AND t.status = '.((int) $search_status);
+}
+
+$sql .= $db->order($sortfield, $sortorder);
+$sql .= $db->plimit($limit + 1, $offset);
+
+$resql = $db->query($sql);
+if (!$resql) {
+ dol_print_error($db);
+ $num = 0;
+} else {
+ $num = $db->num_rows($resql);
+}
+
+$newcardbutton = '';
+if (!empty($user->rights->diffusionplans->bordereaudoc->write)) {
+ $newcardbutton = dolGetButtonTitle($langs->trans('NewBordereaudoc'), '', 'fa fa-plus-circle', dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?action=create');
+}
+
+$param = '';
+if (!empty($search_ref)) {
+ $param .= '&search_ref='.urlencode($search_ref);
+}
+if (!empty($search_title)) {
+ $param .= '&search_title='.urlencode($search_title);
+}
+if (!empty($search_project)) {
+ $param .= '&search_project='.(int) $search_project;
+}
+if ($search_status >= 0) {
+ $param .= '&search_status='.(int) $search_status;
+}
+
+llxHeader('', $langs->trans('BordereaudocList'));
+
+print '';
+
+llxFooter();
+$db->close();
diff --git a/core/modules/modDiffusionPlans.class.php b/core/modules/modDiffusionPlans.class.php
index 55d2232..da6f6a5 100644
--- a/core/modules/modDiffusionPlans.class.php
+++ b/core/modules/modDiffusionPlans.class.php
@@ -440,57 +440,57 @@ public function __construct($db)
- /* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
- $this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=diffusionplans',
- 'type' => 'left',
- 'titre' => 'Diffusion',
- 'mainmenu' => 'diffusionplans',
- 'leftmenu' => 'diffusion',
- 'url' => '/diffusionplans/diffusion_list.php',
- 'langs' => 'diffusionplans@diffusionplans',
- 'position' => 1001,
- 'enabled' => 'isModEnabled(\'diffusionplans\')',
- 'perms' => '$user->hasRight(\'diffusionplans\', \'diffusion\', \'read\')',
- 'target' => '',
- 'user' => 2,
- 'object' => 'Diffusion',
- );
- /* END MODULEBUILDER LEFTMENU DIFFUSION */
- /* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
- $this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion',
- 'type' => 'left',
- 'titre' => 'List Diffusion',
- 'mainmenu' => 'diffusionplans',
- 'leftmenu' => 'diffusionplans_diffusion_list',
- 'url' => '/diffusionplans/diffusion_list.php',
- 'langs' => 'diffusionplans@diffusionplans',
- 'position' => 1002,
- 'enabled' => 'isModEnabled(\'diffusionplans\')',
- 'perms' => '$user->hasRight(\'diffusionplans\', \'diffusion\', \'read\')',
- 'target' => '',
- 'user' => 2,
- 'object' => 'Diffusion',
- );
- /* END MODULEBUILDER LEFTMENU DIFFUSION */
- /* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
- $this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion',
- 'type' => 'left',
- 'titre' => 'New Diffusion',
- 'mainmenu' => 'diffusionplans',
- 'leftmenu' => 'diffusionplans_diffusion_new',
+/* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
+$this->menu[$r++] = array(
+'fk_menu' => 'fk_mainmenu=diffusionplans',
+'type' => 'left',
+'titre' => 'Diffusion',
+'mainmenu' => 'diffusionplans',
+'leftmenu' => 'diffusion',
+'url' => '/diffusionplans/bordereaudoc_list.php',
+'langs' => 'diffusionplans@diffusionplans',
+'position' => 1001,
+'enabled' => 'isModEnabled(\'diffusionplans\')',
+'perms' => '$user->hasRight(\'diffusionplans\', \'bordereaudoc\', \'read\')',
+'target' => '',
+'user' => 2,
+'object' => 'Bordereaudoc',
+);
+/* END MODULEBUILDER LEFTMENU DIFFUSION */
+/* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
+$this->menu[$r++] = array(
+'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion',
+'type' => 'left',
+'titre' => 'List Diffusion',
+'mainmenu' => 'diffusionplans',
+'leftmenu' => 'diffusionplans_diffusion_list',
+'url' => '/diffusionplans/bordereaudoc_list.php',
+'langs' => 'diffusionplans@diffusionplans',
+'position' => 1002,
+'enabled' => 'isModEnabled(\'diffusionplans\')',
+'perms' => '$user->hasRight(\'diffusionplans\', \'bordereaudoc\', \'read\')',
+'target' => '',
+'user' => 2,
+'object' => 'Bordereaudoc',
+);
+/* END MODULEBUILDER LEFTMENU DIFFUSION */
+/* BEGIN MODULEBUILDER LEFTMENU DIFFUSION */
+$this->menu[$r++] = array(
+'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion',
+'type' => 'left',
+'titre' => 'New Diffusion',
+'mainmenu' => 'diffusionplans',
+'leftmenu' => 'diffusionplans_diffusion_new',
'url' => '/diffusionplans/bordereaudoc_card.php?action=create',
- 'langs' => 'diffusionplans@diffusionplans',
- 'position' => 1003,
- 'enabled' => 'isModEnabled(\'diffusionplans\')',
- 'perms' => '$user->hasRight(\'diffusionplans\', \'diffusion\', \'write\')',
- 'target' => '',
- 'user' => 2,
- 'object' => 'Diffusion',
- );
- /* END MODULEBUILDER LEFTMENU DIFFUSION */
+'langs' => 'diffusionplans@diffusionplans',
+'position' => 1003,
+'enabled' => 'isModEnabled(\'diffusionplans\')',
+'perms' => '$user->hasRight(\'diffusionplans\', \'bordereaudoc\', \'write\')',
+'target' => '',
+'user' => 2,
+'object' => 'Bordereaudoc',
+);
+/* END MODULEBUILDER LEFTMENU DIFFUSION */
/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */
/*
@@ -508,7 +508,7 @@ public function __construct($db)
'perms' => '$user->hasRight("diffusionplans", "diffusion", "read")',
'target' => '',
'user' => 2, // 0=Menu for internal users, 1=external users, 2=both
- 'object' => 'Diffusion'
+ 'object' => 'Bordereaudoc'
);
$this->menu[$r++]=array(
'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
@@ -523,7 +523,7 @@ public function __construct($db)
'perms' => '$user->hasRight("diffusionplans", "diffusion", "write")'
'target' => '',
'user' => 2, // 0=Menu for internal users, 1=external users, 2=both
- 'object' => 'Diffusion'
+ 'object' => 'Bordereaudoc'
);
$this->menu[$r++]=array(
'fk_menu' => 'fk_mainmenu=diffusionplans,fk_leftmenu=diffusion', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
@@ -538,7 +538,7 @@ public function __construct($db)
'perms' => '$user->hasRight("diffusionplans", "diffusion", "read")'
'target' => '',
'user' => 2, // 0=Menu for internal users, 1=external users, 2=both
- 'object' => 'Diffusion'
+ 'object' => 'Bordereaudoc'
);
*/
/* END MODULEBUILDER LEFTMENU MYOBJECT */
diff --git a/diffusion_agenda.php b/diffusion_agenda.php
index 279a3cc..46f136b 100644
--- a/diffusion_agenda.php
+++ b/diffusion_agenda.php
@@ -217,7 +217,7 @@
// Object card
// ------------------------------------------------------------
- $linkback = ''.$langs->trans("BackToList").' ';
+$linkback = ''.$langs->trans("BackToList").' ';
$morehtmlref = '';
/*
diff --git a/diffusion_document.php b/diffusion_document.php
index e77b90a..3ed2cc4 100644
--- a/diffusion_document.php
+++ b/diffusion_document.php
@@ -202,7 +202,7 @@
// Object card
// ------------------------------------------------------------
-$linkback = '
'.$langs->trans("BackToList").' ';
+$linkback = '
'.$langs->trans("BackToList").' ';
$morehtmlref = '
';
/*
diff --git a/diffusion_list.php b/diffusion_list.php
deleted file mode 100644
index 60d39ab..0000000
--- a/diffusion_list.php
+++ /dev/null
@@ -1,941 +0,0 @@
-
- * Copyright (C) 2024 Frédéric France
- * Copyright (C) 2025 Pierre ARDOIN
- *
- * 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 .
- */
-
-/**
- * \file diffusion_list.php
- * \ingroup diffusionplans
- * \brief List page for diffusion
- */
-
-
-// General defined Options
-//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET
-//if (! defined('MAIN_AUTHENTICATION_MODE')) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler
-//if (! defined('MAIN_LANG_DEFAULT')) define('MAIN_LANG_DEFAULT', 'auto'); // Force LANG (language) to a particular value
-//if (! defined('MAIN_SECURITY_FORCECSP')) define('MAIN_SECURITY_FORCECSP', 'none'); // Disable all Content Security Policies
-//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification
-//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
-//if (! defined('NOLOGIN')) define('NOLOGIN', '1'); // Do not use login - if this page is public (can be called outside logged session). This includes the NOIPCHECK too.
-//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
-//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db
-//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // Do not load html.form.class.php
-//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // Do not load and show top and left menu
-//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc
-//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs
-//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user
-//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters
-//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters
-//if (! defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions
-//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data
-//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on)
-
-
-// Load Dolibarr environment
-$res = 0;
-// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
-if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
- $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
-}
-// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
-$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
-$tmp2 = realpath(__FILE__);
-$i = strlen($tmp) - 1;
-$j = strlen($tmp2) - 1;
-while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
- $i--;
- $j--;
-}
-if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
- $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
-}
-if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
- $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
-}
-// Try main.inc.php using relative path
-if (!$res && file_exists("../main.inc.php")) {
- $res = @include "../main.inc.php";
-}
-if (!$res && file_exists("../../main.inc.php")) {
- $res = @include "../../main.inc.php";
-}
-if (!$res && file_exists("../../../main.inc.php")) {
- $res = @include "../../../main.inc.php";
-}
-if (!$res) {
- die("Include of main fails");
-}
-
-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';
-// load module libraries
-require_once __DIR__.'/class/diffusion.class.php';
-// for other modules
-//dol_include_once('/othermodule/class/otherobject.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("diffusionplans@diffusionplans", "other"));
-
-// Get parameters
-$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'create'/'add', 'edit'/'update', 'view', ...
-$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
-$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
-$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
-$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
-$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
-$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
-$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
-$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
-$mode = GETPOST('mode', 'aZ'); // The display mode ('list', 'kanban', 'hierarchy', 'calendar', 'gantt', ...)
-$groupby = GETPOST('groupby', 'aZ09'); // Example: $groupby = 'p.fk_opp_status' or $groupby = 'p.fk_statut'
-
-$id = GETPOSTINT('id');
-$ref = GETPOST('ref', 'alpha');
-
-// 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;
-
-// Initialize technical objects
-$object = new Diffusion($db);
-$extrafields = new ExtraFields($db);
-$diroutputmassaction = $conf->diffusionplans->dir_output.'/temp/massgeneration/'.$user->id;
-$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes
-
-// Fetch optionals attributes and labels
-$extrafields->fetch_name_optionals_label($object->table_element);
-//$extrafields->fetch_name_optionals_label($object->table_element_line);
-
-$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
-
-// Default sort order (if not yet defined by previous GETPOST)
-if (!$sortfield) {
- reset($object->fields); // Reset is required to avoid key() to return null.
- $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
-}
-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'));
- }
-}
-
-$fieldstosearchall = array();
-// List of fields to search into when doing a "search in all"
-// foreach ($object->fields as $key => $val) {
-// if (!empty($val['searchall'])) {
-// $fieldstosearchall['t.'.$key] = $val['label'];
-// }
-// }
-// $parameters = array('fieldstosearchall'=>$fieldstosearchall);
-// $reshook = $hookmanager->executeHooks('completeFieldsToSearchAll', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
-// if ($reshook > 0) {
-// $fieldstosearchall = empty($hookmanager->resArray['fieldstosearchall']) ? array() : $hookmanager->resArray['fieldstosearchall'];
-// } elseif ($reshook == 0) {
-// $fieldstosearchall = array_merge($fieldstosearchall, empty($hookmanager->resArray['fieldstosearchall']) ? array() : $hookmanager->resArray['fieldstosearchall']);
-// }
-
-// 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[$tableprefix.'.'.$key] = array(
- 'label' => $val['label'],
- 'checked' => (($visible < 0) ? 0 : 1),
- 'enabled' => (abs($visible) != 3 && (bool) 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['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
-$arrayfields = dol_sort_array($arrayfields, 'position');
-
-// There is several ways to check permission.
-// Set $enablepermissioncheck to 1 to enable a minimum low level of checks
-$enablepermissioncheck = getDolGlobalInt('DIFFUSIONPLANS_ENABLE_PERMISSION_CHECK');
-if ($enablepermissioncheck) {
- $permissiontoread = $user->hasRight('diffusionplans', 'diffusion', 'read');
- $permissiontoadd = $user->hasRight('diffusionplans', 'diffusion', 'write');
- $permissiontodelete = $user->hasRight('diffusionplans', 'diffusion', 'delete');
-} else {
- $permissiontoread = 1;
- $permissiontoadd = 1;
- $permissiontodelete = 1;
-}
-
-// Security check (enable the most restrictive one)
-if ($user->socid > 0) {
- accessforbidden();
-}
-//if ($user->socid > 0) accessforbidden();
-//$socid = 0; if ($user->socid > 0) $socid = $user->socid;
-//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-//restrictedArea($user, $object->module, 0, $object->table_element, $object->element, 'fk_soc', 'rowid', $isdraft);
-if (!isModEnabled("diffusionplans")) {
- accessforbidden('Module diffusionplans not enabled');
-}
-if (!$permissiontoread) {
- accessforbidden();
-}
-
-
-/*
- * Actions
- */
-
-if (GETPOST('cancel', 'alpha')) {
- $action = 'list';
- $massaction = '';
-}
-if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
- $massaction = '';
-}
-
-$parameters = array('arrayfields' => &$arrayfields);
-$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
-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')) { // All tests are required to be compatible with all browsers
- foreach ($object->fields as $key => $val) {
- $search[$key] = '';
- if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
- $search[$key.'_dtstart'] = '';
- $search[$key.'_dtend'] = '';
- }
- }
- $search_all = '';
- $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 = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
- }
-
- // Mass actions
- $objectclass = 'Diffusion';
- $objectlabel = 'Diffusion';
- $uploaddir = $conf->diffusionplans->dir_output;
-
- global $error;
- include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
-
- // You can add more action here
- // if ($action == 'xxx' && $permissiontoxxx) ...
-}
-
-
-
-/*
- * View
- */
-
-$form = new Form($db);
-
-$now = dol_now();
-
-$title = $langs->trans("Diffusions");
-//$help_url = "EN:Module_Diffusion|FR:Module_Diffusion_FR|ES:Módulo_Diffusion";
-$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); // Note that $action and $object may have been modified by hook
-$sql .= $hookmanager->resPrint;
-$sql = preg_replace('/,\s*$/', '', $sql);
-
-$sqlfields = $sql; // $sql fields to remove for count total
-
-$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
-//$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."anothertable as rc ON rc.parent = t.rowid";
-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); // Note that $action and $object may have been modified by hook
-$sql .= $hookmanager->resPrint;
-if ($object->ismultientitymanaged == 1) {
- $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
-} 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] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
- $search[$key] = '';
- }
- $mode_search = 2;
- }
- if (empty($object->fields[$key]['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->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
- }
- if (preg_match('/_dtend$/', $key)) {
- $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
- }
- }
- }
- }
-}
-if ($search_all) {
- $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
-}
-/*
-// If the internal user must only see his customers, force searching by him
-$search_sale = 0;
-if (!$user->hasRight('societe', 'client', 'voir')) {
- $search_sale = $user->id;
-}
-// Search on sale representative
-if ($search_sale && $search_sale != '-1') {
- if ($search_sale == -2) {
- $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
- } elseif ($search_sale > 0) {
- $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = ".((int) $search_sale).")";
- }
-}
-// Search on socid
-if ($socid) {
- $sql .= " AND t.fk_soc = ".((int) $socid);
-}
-*/
-//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
-// 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); // Note that $action and $object may have been modified by hook
-$sql .= $hookmanager->resPrint;
-
-/* If a group by is required
-$sql .= " GROUP BY ";
-foreach($object->fields as $key => $val) {
- $sql .= "t.".$db->sanitize($key).", ";
-}
-// 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.', ' : '');
- }
-}
-// Add groupby from hooks
-$parameters = array();
-$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
-$sql .= $hookmanager->resPrint;
-$sql = preg_replace('/,\s*$/', '', $sql);
-*/
-
-// Add HAVING from hooks
-/*
-$parameters = array();
-$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
-$sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
-*/
-
-// Count total nb of records
-$nbtotalofrecords = '';
-if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
- /* The fast and low memory method to get and count full list converts the sql into a sql count */
- $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) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
- $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_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?id='.((int) $id));
- exit;
-}
-
-
-// Output page
-// --------------------------------------------------------------------
-
-llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'mod-diffusionplans page-list bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for a horizontal scroll in the table instead of page
-
-// Example : Adding jquery code
-// print '';
-
-$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);
-}
-if ($groupby != '') {
- $param .= '&groupby='.urlencode($groupby);
-}
-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='.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]);
- }
-}
-// Add $param from extra fields
-include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
-// Add $param from hooks
-$parameters = array('param' => &$param);
-$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
-$param .= $hookmanager->resPrint;
-
-// List of mass actions available
-$arrayofmassactions = array(
- //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
- //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
- //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
- //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
-);
-if (!empty($permissiontodelete)) {
- $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
-}
-if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
- $arrayofmassactions = array();
-}
-$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
-
-print ''."\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('&', '&', $param);
-
- $filedir = $diroutputmassaction;
- $genallowed = $permissiontoread;
- $delallowed = $permissiontoadd;
-
- print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
-}
-
-// End of page
-llxFooter();
-$db->close();
From 831f01af3c54a2fda0701f3248fa34c685892a30 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 20:55:57 +0100
Subject: [PATCH 08/25] Enhance bordereaudoc list filters and metrics
---
bordereaudoc_list.php | 70 ++++++++++++++++++++++++++++-----
langs/en_US/diffusionplans.lang | 2 +
langs/fr_FR/diffusionplans.lang | 2 +
3 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/bordereaudoc_list.php b/bordereaudoc_list.php
index 4a10ded..2d9d8af 100644
--- a/bordereaudoc_list.php
+++ b/bordereaudoc_list.php
@@ -16,7 +16,7 @@
*/
/**
- * \file bordereaudoc_list.php
+ * \file bordereaudoc_list.php
* \ingroup diffusionplans
* \brief List page for Bordereaudoc objects.
*/
@@ -70,7 +70,7 @@
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = (int) GETPOST('page', 'int');
if ($page < 0) {
- $page = 0;
+$page = 0;
}
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$offset = $limit * $page;
@@ -79,6 +79,15 @@
$search_title = GETPOST('search_title', 'alpha');
$search_project = GETPOSTINT('search_project');
$search_status = GETPOSTINT('search_status', -1);
+$search_date_startday = GETPOSTINT('search_date_startday');
+$search_date_startmonth = GETPOSTINT('search_date_startmonth');
+$search_date_startyear = GETPOSTINT('search_date_startyear');
+$search_date_endday = GETPOSTINT('search_date_endday');
+$search_date_endmonth = GETPOSTINT('search_date_endmonth');
+$search_date_endyear = GETPOSTINT('search_date_endyear');
+
+$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear);
+$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
// Objects
$form = new Form($db);
@@ -98,9 +107,12 @@
Bordereaudoc::STATUS_CLOSED => $langs->trans('Closed')
);
-$sql = 'SELECT t.rowid, t.ref, t.title, t.fk_project, t.status, p.ref as project_ref, p.title as project_title';
+$sql = 'SELECT t.rowid, t.ref, t.title, t.fk_project, t.status, t.datec, t.tms, p.ref as project_ref, p.title as project_title,';
+$sql .= ' bc.cnt_contact as nb_contacts, bf.cnt_visible as nb_visible_files';
$sql .= ' FROM '.MAIN_DB_PREFIX.'bordereaudoc as t';
$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."projet as p ON p.rowid = t.fk_project";
+$sql .= ' LEFT JOIN (SELECT fk_bordereaudoc, COUNT(*) as cnt_contact FROM '.MAIN_DB_PREFIX."bordereaudoc_contact WHERE active = 1 AND entity IN (".getEntity('bordereaudoc').") GROUP BY fk_bordereaudoc) as bc ON bc.fk_bordereaudoc = t.rowid";
+$sql .= ' LEFT JOIN (SELECT fk_bordereaudoc, COUNT(*) as cnt_visible FROM '.MAIN_DB_PREFIX."bordereaudoc_file WHERE is_visible = 1 AND entity IN (".getEntity('bordereaudoc').") GROUP BY fk_bordereaudoc) as bf ON bf.fk_bordereaudoc = t.rowid";
$sql .= ' WHERE t.entity IN ('.getEntity('bordereaudoc').')';
if (!empty($search_ref)) {
$sql .= natural_search('t.ref', $search_ref);
@@ -114,8 +126,14 @@
if ($search_status >= 0) {
$sql .= ' AND t.status = '.((int) $search_status);
}
+if ($search_date_start > 0) {
+ $sql .= " AND t.datec >= '".$db->idate($search_date_start)."'";
+}
+if ($search_date_end > 0) {
+ $sql .= " AND t.datec <= '".$db->idate($search_date_end)."'";
+}
-$sql .= $db->order($sortfield, $sortorder);
+$sql .= $db->order($sortfield, $sortorder ? $sortorder : 'DESC');
$sql .= $db->plimit($limit + 1, $offset);
$resql = $db->query($sql);
@@ -126,7 +144,7 @@
$num = $db->num_rows($resql);
}
-$newcardbutton = '';
+ $newcardbutton = '';
if (!empty($user->rights->diffusionplans->bordereaudoc->write)) {
$newcardbutton = dolGetButtonTitle($langs->trans('NewBordereaudoc'), '', 'fa fa-plus-circle', dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?action=create');
}
@@ -144,6 +162,24 @@
if ($search_status >= 0) {
$param .= '&search_status='.(int) $search_status;
}
+if ($search_date_startday) {
+ $param .= '&search_date_startday='.(int) $search_date_startday;
+}
+if ($search_date_startmonth) {
+ $param .= '&search_date_startmonth='.(int) $search_date_startmonth;
+}
+if ($search_date_startyear) {
+ $param .= '&search_date_startyear='.(int) $search_date_startyear;
+}
+if ($search_date_endday) {
+ $param .= '&search_date_endday='.(int) $search_date_endday;
+}
+if ($search_date_endmonth) {
+ $param .= '&search_date_endmonth='.(int) $search_date_endmonth;
+}
+if ($search_date_endyear) {
+ $param .= '&search_date_endyear='.(int) $search_date_endyear;
+}
llxHeader('', $langs->trans('BordereaudocList'));
@@ -156,9 +192,13 @@
print '';
print '';
print_liste_field_titre($langs->trans('Ref'), $_SERVER['PHP_SELF'], 't.ref', '', $param, '', $sortfield, $sortorder);
-print_liste_field_titre($langs->trans('Project'), $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder);
print_liste_field_titre($langs->trans('Title'), $_SERVER['PHP_SELF'], 't.title', '', $param, '', $sortfield, $sortorder);
+print_liste_field_titre($langs->trans('Project'), $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder);
print_liste_field_titre($langs->trans('Status'), $_SERVER['PHP_SELF'], 't.status', '', $param, '', $sortfield, $sortorder, 'center');
+print_liste_field_titre($langs->trans('DateCreation'), $_SERVER['PHP_SELF'], 't.datec', '', $param, '', $sortfield, $sortorder, 'center');
+print_liste_field_titre($langs->trans('DateModificationShort'), $_SERVER['PHP_SELF'], 't.tms', '', $param, '', $sortfield, $sortorder, 'center');
+print_liste_field_titre($langs->trans('ContactsCount'), $_SERVER['PHP_SELF'], 'nb_contacts', '', $param, '', $sortfield, $sortorder, 'right');
+print_liste_field_titre($langs->trans('VisibleDocuments'), $_SERVER['PHP_SELF'], 'nb_visible_files', '', $param, '', $sortfield, $sortorder, 'right');
print_liste_field_titre('');
print ' ';
@@ -167,17 +207,25 @@
print ' ';
print '';
print '';
-print $form->select_projet($search_project, 'search_project', 1, '', 0, 0, 1, 0, 0, '', 1);
+print ' ';
print ' ';
print '';
-print ' ';
+print $form->select_projet($search_project, 'search_project', 1, '', 0, 0, 1, 0, 0, '', 1);
print ' ';
print '';
print $form->selectarray('search_status', $statusLabels, $search_status, 1);
print ' ';
+print '';
+print $form->selectDate($search_date_start, 'search_date_start', 0, 0, 1, '', 1, 0, 1);
+print ' ';
+print $form->selectDate($search_date_end, 'search_date_end', 0, 0, 1, '', 1, 0, 1);
+print ' ';
print '';
print $form->showFilterAndCheckAddButtons(0);
print ' ';
+print ' ';
+print ' ';
+print ' ';
print '';
$i = 0;
@@ -198,13 +246,17 @@
print '';
print ''.dol_escape_htmltag($obj->ref).' ';
print ' ';
+ print ''.dol_escape_htmltag($obj->title).' ';
print '';
if (!empty($obj->fk_project)) {
print $projectstatic->getNomUrl(1);
}
print ' ';
- print ''.dol_escape_htmltag($obj->title).' ';
print ''.(isset($statusLabels[$obj->status]) ? $statusLabels[$obj->status] : '').' ';
+ print ''.dol_print_date($db->jdate($obj->datec), 'day').' ';
+ print ''.dol_print_date($db->jdate($obj->tms), 'dayhour').' ';
+ print ''.(int) $obj->nb_contacts.' ';
+ print ''.(int) $obj->nb_visible_files.' ';
print '';
print ' ';
print '';
diff --git a/langs/en_US/diffusionplans.lang b/langs/en_US/diffusionplans.lang
index 7cce4fb..d749ee7 100644
--- a/langs/en_US/diffusionplans.lang
+++ b/langs/en_US/diffusionplans.lang
@@ -19,6 +19,7 @@ ConfirmClone = Confirm cloning
Contact = Contact
ContactType = Contact type
Contacts = Contacts
+ContactsCount = Contacts
CopyOf = Copy of
Currency = Currency
CustomerAccountancyCode = Customer accountancy code
@@ -67,6 +68,7 @@ ExtraFields = Extra fields
FeaturesSupported = Supported features
FieldEdition = Field edition
Files = Files
+VisibleDocuments = Listed documents
FilterOnInto = Filter on
FollowingSubstitutionKeysCanBeUsed = You can use the following substitution keys:
FullListOnOnlineDocumentation = See the online documentation for the complete list.
diff --git a/langs/fr_FR/diffusionplans.lang b/langs/fr_FR/diffusionplans.lang
index e7db9d5..b782d27 100644
--- a/langs/fr_FR/diffusionplans.lang
+++ b/langs/fr_FR/diffusionplans.lang
@@ -19,6 +19,7 @@ ConfirmClone = Confirmer le clonage
Contact = Contact
ContactType = Type de contact
Contacts = Contacts
+ContactsCount = Contacts
CopyOf = Copie de
Currency = Devise
CustomerAccountancyCode = Code comptable client
@@ -67,6 +68,7 @@ ExtraFields = Champs supplémentaires
FeaturesSupported = Fonctionnalités prises en charge
FieldEdition = Édition du champ
Files = Fichiers
+VisibleDocuments = Documents listés
FilterOnInto = Filtrer sur
FollowingSubstitutionKeysCanBeUsed = Vous pouvez utiliser les clés de substitution suivantes :
FullListOnOnlineDocumentation = Voir la documentation en ligne pour la liste complète.
From 67901ded5c16555117a7fda8296868088c078071 Mon Sep 17 00:00:00 2001
From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com>
Date: Mon, 1 Dec 2025 21:30:18 +0100
Subject: [PATCH 09/25] Add mass actions to bordereaudoc list
---
bordereaudoc_list.php | 95 ++++++++++++++++++++++++++++-----
langs/en_US/diffusionplans.lang | 1 +
langs/fr_FR/diffusionplans.lang | 1 +
3 files changed, 85 insertions(+), 12 deletions(-)
diff --git a/bordereaudoc_list.php b/bordereaudoc_list.php
index 2d9d8af..618f88a 100644
--- a/bordereaudoc_list.php
+++ b/bordereaudoc_list.php
@@ -70,7 +70,7 @@
$sortorder = GETPOST('sortorder', 'aZ09comma');
$page = (int) GETPOST('page', 'int');
if ($page < 0) {
-$page = 0;
+ $page = 0;
}
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$offset = $limit * $page;
@@ -89,9 +89,54 @@
$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear);
$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
+$action = GETPOST('action', 'aZ09');
+$massaction = GETPOST('massaction', 'alpha');
+$confirm = GETPOST('confirm', 'alpha');
+$toselect = GETPOST('toselect', 'array');
+
// Objects
$form = new Form($db);
$projectstatic = new Project($db);
+$object = new Bordereaudoc($db);
+
+$formconfirm = '';
+
+$arrayofmassactions = array();
+if (!empty($user->rights->diffusionplans->bordereaudoc->delete)) {
+ $arrayofmassactions['delete'] = $langs->trans('Delete');
+}
+
+if ($action === 'confirm_delete' && $confirm === 'yes' && $massaction === 'delete' && !empty($toselect)) {
+ $error = 0;
+ foreach ($toselect as $selectedId) {
+ if (empty($selectedId)) {
+ continue;
+ }
+ $resFetch = $object->fetch((int) $selectedId);
+ if ($resFetch > 0) {
+ if ((int) $object->status === Bordereaudoc::STATUS_DRAFT) {
+ $resDel = $object->delete($user);
+ if ($resDel < 0) {
+ $error++;
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
+ } else {
+ $error++;
+ setEventMessages($langs->trans('ErrorBordereaudocDeleteDraftOnly', $object->ref), null, 'errors');
+ }
+ }
+ }
+
+ if (!$error) {
+ setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
+ header('Location: '.$_SERVER['PHP_SELF']);
+ exit;
+ }
+ }
+
+if ($massaction === 'delete' && !empty($arrayofmassactions) && !empty($toselect)) {
+$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'], $langs->trans('Delete'), $langs->trans('ConfirmDelete'), 'confirm_delete', array('massaction' => 'delete', 'toselect' => $toselect));
+}
if (empty($sortfield)) {
$sortfield = 't.ref';
@@ -144,11 +189,16 @@
$num = $db->num_rows($resql);
}
- $newcardbutton = '';
+$newcardbutton = '';
if (!empty($user->rights->diffusionplans->bordereaudoc->write)) {
$newcardbutton = dolGetButtonTitle($langs->trans('NewBordereaudoc'), '', 'fa fa-plus-circle', dol_buildpath('/diffusionplans/bordereaudoc_card.php', 1).'?action=create');
}
+$massactionbutton = '';
+if (!empty($arrayofmassactions)) {
+ $massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions);
+}
+
$param = '';
if (!empty($search_ref)) {
$param .= '&search_ref='.urlencode($search_ref);
@@ -183,14 +233,27 @@
llxHeader('', $langs->trans('BordereaudocList'));
-print '