diff --git a/htdocs/bookcal/admin/setup.php b/htdocs/bookcal/admin/setup.php index e3addec83e3..ed9af6c6692 100644 --- a/htdocs/bookcal/admin/setup.php +++ b/htdocs/bookcal/admin/setup.php @@ -72,38 +72,10 @@ if (!class_exists('FormSetup')) { $formSetup = new FormSetup($db); -// Hôte -$item = $formSetup->newItem('NO_PARAM_JUST_TEXT'); -$item->fieldOverride = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST']; -$item->cssClass = 'minwidth500'; - -// Setup conf BOOKCAL_MYPARAM1 as a simple string input -$item = $formSetup->newItem('BOOKCAL_MYPARAM1'); -$item->defaultFieldValue = 'default value'; - -// Setup conf BOOKCAL_MYPARAM1 as a simple textarea input but we replace the text of field title -$item = $formSetup->newItem('BOOKCAL_MYPARAM2'); -$item->nameText = $item->getNameText().' more html text '; - -// Setup conf BOOKCAL_MYPARAM3 -$item = $formSetup->newItem('BOOKCAL_MYPARAM3'); -$item->setAsThirdpartyType(); - -// Setup conf BOOKCAL_MYPARAM4 : exemple of quick define write style -$formSetup->newItem('BOOKCAL_MYPARAM4')->setAsYesNo(); - -// Setup conf BOOKCAL_MYPARAM5 -$formSetup->newItem('BOOKCAL_MYPARAM5')->setAsEmailTemplate('thirdparty'); - -// Setup conf BOOKCAL_MYPARAM6 -$formSetup->newItem('BOOKCAL_MYPARAM6')->setAsSecureKey()->enabled = 0; // disabled - -// Setup conf BOOKCAL_MYPARAM7 -$formSetup->newItem('BOOKCAL_MYPARAM7')->setAsProduct(); - -$formSetup->newItem('Title')->setAsTitle(); - -// Setup conf BOOKCAL_MYPARAM8 +// Setup conf BOOKCAL_PUBLIC_INTERFACE_TOPIC +$item = $formSetup->newItem('BOOKCAL_PUBLIC_INTERFACE_TOPIC'); +$item->defaultFieldValue = 'MyBigCompany public interface for Bookcal'; +/*// Setup conf BOOKCAL_MYPARAM8 $item = $formSetup->newItem('BOOKCAL_MYPARAM8'); $TField = array( 'test01' => $langs->trans('test01'), @@ -127,7 +99,7 @@ $item->setAsColor(); $item->defaultFieldValue = '#FF0000'; $item->nameText = $item->getNameText().' more html text '; $item->fieldInputOverride = ''; -$item->helpText = $langs->transnoentities('AnHelpMessage'); +$item->helpText = $langs->transnoentities('AnHelpMessage');*/ //$item->fieldValue = ''; //$item->fieldAttr = array() ; // fields attribute only for compatible fields like input text //$item->fieldOverride = false; // set this var to override field output will override $fieldInputOverride and $fieldOutputOverride too @@ -290,7 +262,7 @@ if ($action == 'edit') { $moduledir = 'bookcal'; $myTmpObjects = array(); -$myTmpObjects['MyObject'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0); +$myTmpObjects['Booking'] = array('includerefgeneration'=>1, 'includedocgeneration'=>0); foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { diff --git a/htdocs/bookcal/availabilities_card.php b/htdocs/bookcal/availabilities_card.php index 6d21b777405..f1ebb871af7 100644 --- a/htdocs/bookcal/availabilities_card.php +++ b/htdocs/bookcal/availabilities_card.php @@ -292,9 +292,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } - if ($action == 'generate') { - print ' Link : '. DOL_DOCUMENT_ROOT.'/public/bookcal/booking.php?id='.$object->id . '' ; - } // Confirmation of action xxxx (You can use it for xxx = 'close', xxx = 'reopen', ...) if ($action == 'xxx') { @@ -489,9 +486,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Clone print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid)?'&socid='.$object->socid:'').'&action=clone&token='.newToken(), '', $permissiontoadd); - // Generate link - print dolGetButtonAction($langs->trans('generateLink'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=generate', '', $permissiontoadd); - /* if ($permissiontoadd) { if ($object->status == $object::STATUS_ENABLED) { diff --git a/htdocs/bookcal/bookcalindex.php b/htdocs/bookcal/bookcalindex.php index b76c8e9972d..bed921e91ea 100644 --- a/htdocs/bookcal/bookcalindex.php +++ b/htdocs/bookcal/bookcalindex.php @@ -27,6 +27,7 @@ // Load Dolibarr environment require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; // Load translation files required by the page $langs->loadLangs(array("agenda")); @@ -73,6 +74,7 @@ print '
'; // Draft MyObject if ($user->hasRight('bookcal', 'availabilities', 'read') && isModEnabled('bookcal')) { $langs->load("orders"); + $myobjectstatic = new Booking($db); $sql = "SELECT rowid, `ref`, fk_soc, fk_project, description, note_public, note_private, date_creation, tms, fk_user_creat, fk_user_modif, last_main_doc, import_key, model_pdf, status, firstname, lastname, email, `start`, duration"; $sql .= " FROM ". MAIN_DB_PREFIX . 'bookcal_booking'; @@ -92,7 +94,6 @@ if ($user->hasRight('bookcal', 'availabilities', 'read') && isModEnabled('bookca id ref name - date hour duration description @@ -105,7 +106,6 @@ if ($user->hasRight('bookcal', 'availabilities', 'read') && isModEnabled('bookca $myobjectstatic->id=$obj->rowid; $myobjectstatic->ref=$obj->ref; - $myobjectstatic->date = $obj->start; $myobjectstatic->firstname = $obj->firstname; $myobjectstatic->lastname = $obj->lastname; $myobjectstatic->start = $obj->start; @@ -116,7 +116,7 @@ if ($user->hasRight('bookcal', 'availabilities', 'read') && isModEnabled('bookca print '' . $myobjectstatic->id . ""; print '' . $myobjectstatic->ref . ""; print '' . $myobjectstatic->firstname . " " . $myobjectstatic->lastname . ""; - print '' . $myobjectstatic->start . ""; + print '' . dol_print_date($myobjectstatic->start, 'dayhourtext') . ""; print '' . $myobjectstatic->duration . ""; print '' . $myobjectstatic->description . ""; $i++; diff --git a/htdocs/bookcal/calendar_card.php b/htdocs/bookcal/calendar_card.php index caaefd3d90b..dd3c4cabcd7 100644 --- a/htdocs/bookcal/calendar_card.php +++ b/htdocs/bookcal/calendar_card.php @@ -353,6 +353,10 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } + if ($action == 'generate') { + print ' Link : Public page' ; + } + // Confirmation of action xxxx (You can use it for xxx = 'close', xxx = 'reopen', ...) if ($action == 'xxx') { $text = $langs->trans('ConfirmActionCalendar', $object->ref); @@ -546,6 +550,10 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid)?'&socid='.$object->socid:'').'&action=clone&token='.newToken(), '', $permissiontoadd); } + // Generate link + if ($object->status == Calendar::STATUS_VALIDATED) { + print dolGetButtonAction($langs->trans('generateLink'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=generate', '', $permissiontoadd); + } /* if ($permissiontoadd) { if ($object->status == $object::STATUS_ENABLED) { diff --git a/htdocs/core/ajax/bookcalAjax.php b/htdocs/core/ajax/bookcalAjax.php new file mode 100644 index 00000000000..80323b0fee9 --- /dev/null +++ b/htdocs/core/ajax/bookcalAjax.php @@ -0,0 +1,123 @@ +. + */ + +/** + * \file /htdocs/core/ajax/bookcalAjax.php + * \brief File to make Ajax action on Book cal + */ + +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); // Disables token renewal +} +if (!defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); +} +if (!defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (!defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +// Do not check anti CSRF attack test +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +// If there is no need to load and show top and left menu +if (!defined("NOLOGIN")) { + define("NOLOGIN", '1'); +} + +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + +$action = GETPOST('action', 'aZ09'); +$idavailability = GETPOST('id', 'int'); +$datetocheckbooking = GETPOST('datetocheck', 'int'); +$error = 0; + +// Security check +/*if (!defined("NOLOGIN")) { // No need of restrictedArea if not logged: Later the select will filter on public articles only if not logged. + restrictedArea($user, 'knowledgemanagement', 0, 'knowledgemanagement_knowledgerecord', 'knowledgerecord'); +}*/ + +$result = "{}"; + +/* + * Actions + */ + +top_httphead('application/json'); + +if ($action == 'verifyavailability') { + $response = array(); + if (empty($idavailability)) { + $error++; + $response["code"] = "MISSING_ID"; + $response["message"] = "Missing parameter id"; + header('HTTP/1.0 400 Bad Request'); + } + if (empty($datetocheckbooking)) { + $error++; + $response["code"] = "MISSING_DATE_AVAILABILITY"; + $response["message"] = "Missing parameter datetocheck"; + header('HTTP/1.0 400 Bad Request'); + } + if (!$error) { + $datetocheckbooking_end = dol_time_plus_duree($datetocheckbooking, 1, 'd'); + $sql = "SELECT b.start, b.rowid"; + $sql .= " FROM ".MAIN_DB_PREFIX."bookcal_booking as b"; + $sql .= " WHERE fk_bookcal_availability = ".((int) $idavailability); + $sql .= " AND b.start >= '".$db->idate($datetocheckbooking)."'"; + $sql .= " AND b.start < '".$db->idate($datetocheckbooking_end)."'"; + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + $response = array(); + $response["content"] = array(); + while ($i < $num) { + $obj = $db->fetch_object($resql); + $dateobject = $obj->start; + $dateobject = explode(" ", $dateobject)[1]; + $dateobject = explode(":", $dateobject); + + $dateobjectstring = $dateobject[0].$dateobject[1]; + + $response["content"][] = $dateobjectstring; + $i++; + } + if ($i == 0) { + $response["code"] = "NO_DATA_FOUND"; + } else { + $response["code"] = "SUCCESS"; + } + } else { + dol_print_error($db); + } + } + $result = json_encode($response); +} + +/* + * View + */ +//None + +echo json_encode($result); diff --git a/htdocs/core/modules/bookcal/mod_booking_advanced.php b/htdocs/core/modules/bookcal/mod_booking_advanced.php new file mode 100644 index 00000000000..51b60e1fd7a --- /dev/null +++ b/htdocs/core/modules/bookcal/mod_booking_advanced.php @@ -0,0 +1,146 @@ + + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/booking/mod_booking_advanced.php + * \ingroup bookcal + * \brief File containing class for advanced numbering model of Booking + */ + +dol_include_once('/core/modules/bookcal/modules_booking.php'); + + +/** + * Class to manage the Advanced numbering rule for Booking + */ +class mod_booking_advanced extends ModeleNumRefBooking +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string Error message + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'advanced'; + + + /** + * Returns the description of the numbering model + * + * @return string Descriptive text + */ + public function info() + { + global $conf, $langs, $db; + + $langs->load("bills"); + + $form = new Form($db); + + $texte = $langs->trans('GenericNumRefModelDesc')."
\n"; + $texte .= '
'; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("Booking"), $langs->transnoentities("Booking")); + $tooltip .= $langs->trans("GenericMaskCodes2"); + $tooltip .= $langs->trans("GenericMaskCodes3"); + $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("Booking"), $langs->transnoentities("Booking")); + $tooltip .= $langs->trans("GenericMaskCodes5"); + + // Parametrage du prefix + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $texte .= '
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + $texte .= '
'; + + return $texte; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $conf, $db, $langs, $mysoc; + + $object = new Booking($db); + $object->initAsSpecimen(); + + /*$old_code_client = $mysoc->code_client; + $old_code_type = $mysoc->typent_code; + $mysoc->code_client = 'CCCCCCCCCC'; + $mysoc->typent_code = 'TTTTTTTTTT';*/ + + $numExample = $this->getNextValue($object); + + /*$mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type;*/ + + if (!$numExample) { + $numExample = $langs->trans('NotConfigured'); + } + return $numExample; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + // We get cursor rule + $mask = getDolGlobalString('BOOKCAL_BOOKING_ADVANCED_MASK'); + + if (!$mask) { + $this->error = 'NotConfigured'; + return 0; + } + + $date = $object->date; + + $numFinal = get_next_value($db, $mask, 'bookcal_booking', 'ref', '', null, $date); + + return $numFinal; + } +} diff --git a/htdocs/core/modules/bookcal/mod_booking_standard.php b/htdocs/core/modules/bookcal/mod_booking_standard.php new file mode 100644 index 00000000000..eff6cb23cf6 --- /dev/null +++ b/htdocs/core/modules/bookcal/mod_booking_standard.php @@ -0,0 +1,161 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/bookcal/mod_booking_standard.php + * \ingroup bookcal + * \brief File of class to manage booking numbering rules standard + */ +dol_include_once('/core/modules/bookcal/modules_booking.php'); + + +/** + * Class to manage the Standard numbering rule for booking + */ +class mod_booking_standard extends ModeleNumRefBooking +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + public $prefix = 'BK'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'standard'; + + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info() + { + global $langs; + return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + } + + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + return $this->prefix."0501-0001"; + } + + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."bookcal_booking"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $row = $db->fetch_row($resql); + if ($row) { + $coyymm = substr($row[0], 0, 6); $max = $row[0]; + } + } + if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + // first we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."bookcal_booking"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $max = intval($obj->max); + } else { + $max = 0; + } + } else { + dol_syslog("mod_booking_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) { + $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + } else { + $num = sprintf("%04s", $max + 1); + } + + dol_syslog("mod_booking_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } +} diff --git a/htdocs/core/modules/bookcal/modules_booking.php b/htdocs/core/modules/bookcal/modules_booking.php new file mode 100644 index 00000000000..2070af4e404 --- /dev/null +++ b/htdocs/core/modules/bookcal/modules_booking.php @@ -0,0 +1,194 @@ + + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2014 Marcos García + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/mymodule/modules_myobject.php + * \ingroup mymodule + * \brief File that contains parent class for myobjects document models and parent class for myobjects numbering models + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // required for use by classes that inherit + + +/** + * Parent class for documents models + */ +abstract class ModelePDFBooking extends CommonDocGenerator +{ + + /** + * @var int page_largeur + */ + public $page_largeur; + + /** + * @var int page_hauteur + */ + public $page_hauteur; + + /** + * @var array format + */ + public $format; + + /** + * @var int marge_gauche + */ + public $marge_gauche; + + /** + * @var int marge_droite + */ + public $marge_droite; + + /** + * @var int marge_haute + */ + public $marge_haute; + + /** + * @var int marge_basse + */ + public $marge_basse; + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + public static function liste_modeles($db, $maxfilenamelength = 0) + { + // phpcs:enable + global $conf; + + $type = 'myobject'; + $list = array(); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $list = getListOfModels($db, $type, $maxfilenamelength); + + return $list; + } +} + + + +/** + * Parent class to manage numbering of MyObject + */ +abstract class ModeleNumRefBooking +{ + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled() + { + return true; + } + + /** + * Returns the default description of the numbering template + * + * @return string Descriptive text + */ + public function info() + { + global $langs; + $langs->load("mymodule@mymodule"); + return $langs->trans("NoDescription"); + } + + /** + * Returns an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $langs; + $langs->load("mymodule@mymodule"); + return $langs->trans("NoExample"); + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if conflict, true if ok + */ + public function canBeActivated($object) + { + return true; + } + + /** + * Returns next assigned value + * + * @param Object $object Object we need next value for + * @return string Valeur + */ + public function getNextValue($object) + { + global $langs; + return $langs->trans("NotAvailable"); + } + + /** + * Returns version of numbering module + * + * @return string Valeur + */ + public function getVersion() + { + global $langs; + $langs->load("admin"); + + if ($this->version == 'development') { + return $langs->trans("VersionDevelopment"); + } + if ($this->version == 'experimental') { + return $langs->trans("VersionExperimental"); + } + if ($this->version == 'dolibarr') { + return DOL_VERSION; + } + if ($this->version) { + return $this->version; + } + return $langs->trans("NotAvailable"); + } +} diff --git a/htdocs/core/modules/modBookCal.class.php b/htdocs/core/modules/modBookCal.class.php index 8163d1b696d..fbbc4180423 100644 --- a/htdocs/core/modules/modBookCal.class.php +++ b/htdocs/core/modules/modBookCal.class.php @@ -135,7 +135,7 @@ class modBookCal extends DolibarrModules $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) // The language file dedicated to your module - $this->langfiles = array("bookcal@bookcal"); + $this->langfiles = array("bookcal"); // Prerequisites $this->phpmin = array(7, 0); // Minimum version of PHP required by module @@ -305,14 +305,58 @@ class modBookCal extends DolibarrModules 'mainmenu'=>'bookcal', 'leftmenu'=>'', 'url'=>'/bookcal/bookcalindex.php', - 'langs'=>'bookcal@bookcal', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'bookcal', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>1000 + $r, 'enabled'=>'$conf->bookcal->enabled', // Define condition to show or hide menu entry. Use '$conf->bookcal->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->bookcal->availabilities->read' if you want your menu with a permission rules + 'perms'=>'$user->rights->bookcal->availabilities->read', // Use 'perms'=>'$user->rights->bookcal->availabilities->read' if you want your menu with a permission rules 'target'=>'', 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); /* END MODULEBUILDER TOPMENU */ + + /* BEGIN MODULEBUILDER LEFTMENU CALENDAR */ + $this->menu[$r++]=array( + // '' 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 + 'fk_menu'=>'fk_mainmenu=bookcal', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'List Calendar', + 'mainmenu'=>'bookcal', + 'leftmenu'=>'bookcal_calendar', + 'url'=>'/bookcal/calendar_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'bookcal', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->bookcal->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->bookcal->enabled', + // Use 'perms'=>'$user->rights->bookcal->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->bookcal->calendar->read', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + $this->menu[$r++]=array( + // '' 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 + 'fk_menu'=>'fk_mainmenu=bookcal,fk_leftmenu=bookcal_calendar', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'New Calendar', + 'mainmenu'=>'bookcal', + 'leftmenu'=>'bookcal_calendar', + 'url'=>'/bookcal/calendar_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'bookcal', + 'position'=>1100+$r, + // Define condition to show or hide menu entry. Use '$conf->bookcal->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'$conf->bookcal->enabled', + // Use 'perms'=>'$user->rights->bookcal->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->bookcal->calendar->read', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + ); + /* END MODULEBUILDER LEFTMENU CALENDAR */ + /* BEGIN MODULEBUILDER LEFTMENU AVAILABILITIES $this->menu[$r++]=array( 'fk_menu'=>'fk_mainmenu=bookcal', // '' 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 @@ -369,12 +413,12 @@ class modBookCal extends DolibarrModules 'leftmenu'=>'bookcal_availabilities', 'url'=>'/bookcal/availabilities_list.php', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'langs'=>'bookcal@bookcal', - 'position'=>1100+$r, + 'langs'=>'bookcal', + 'position'=>1200+$r, // Define condition to show or hide menu entry. Use '$conf->bookcal->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 'enabled'=>'$conf->bookcal->enabled', // Use 'perms'=>'$user->rights->bookcal->level1->level2' if you want your menu with a permission rules - 'perms'=>'1', + 'perms'=>'$user->rights->bookcal->availabilities->read', 'target'=>'', // 0=Menu for internal users, 1=external users, 2=both 'user'=>2, @@ -389,12 +433,12 @@ class modBookCal extends DolibarrModules 'leftmenu'=>'bookcal_availabilities', 'url'=>'/bookcal/availabilities_card.php?action=create', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - 'langs'=>'bookcal@bookcal', - 'position'=>1100+$r, + 'langs'=>'bookcal', + 'position'=>1200+$r, // Define condition to show or hide menu entry. Use '$conf->bookcal->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 'enabled'=>'$conf->bookcal->enabled', // Use 'perms'=>'$user->rights->bookcal->level1->level2' if you want your menu with a permission rules - 'perms'=>'1', + 'perms'=>'$user->rights->bookcal->availabilities->read', 'target'=>'', // 0=Menu for internal users, 1=external users, 2=both 'user'=>2 diff --git a/htdocs/langs/en_US/bookcal.lang b/htdocs/langs/en_US/bookcal.lang index 14c2bbce328..868bf5f2ef3 100644 --- a/htdocs/langs/en_US/bookcal.lang +++ b/htdocs/langs/en_US/bookcal.lang @@ -28,7 +28,7 @@ ModuleBookCalDesc = Manage a Calendar to book appointments BookCalSetup = BookCal setup Settings = Settings BookCalSetupPage = BookCal setup page -BOOKCAL_MYPARAM1 = My param 1 +BOOKCAL_PUBLIC_INTERFACE_TOPIC = Interface title BOOKCAL_MYPARAM1Tooltip = My param 1 tooltip BOOKCAL_MYPARAM2=My param 2 BOOKCAL_MYPARAM2Tooltip=My param 2 tooltip @@ -52,3 +52,7 @@ MyPageName = My page name # MyWidget = My widget MyWidgetDescription = My widget description + +AppointmentDuration = Appointment Duration : %s +BookingSuccessfullyBooked=Your booking as been saved +BookingReservationHourAfter=We confirm the reservation of your meeting at the date %s \ No newline at end of file diff --git a/htdocs/public/bookcal/booking.php b/htdocs/public/bookcal/booking.php new file mode 100644 index 00000000000..d478046d143 --- /dev/null +++ b/htdocs/public/bookcal/booking.php @@ -0,0 +1,529 @@ + + * Copyright (C) 2006-2017 Laurent Destailleur + * Copyright (C) 2009-2012 Regis Houssin + * Copyright (C) 2023 anthony Berton + * + * 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 htdocs/public/onlinesign/newonlinesign.php + * \ingroup core + * \brief File to offer a way to make an online signature for a particular Dolibarr entity + * Example of URL: https://localhost/public/bookcal/booking.php?ref=PR... + */ + +if (!defined('NOLOGIN')) { + define("NOLOGIN", 1); // This means this output page does not require to be logged. +} +if (!defined('NOCSRFCHECK')) { + define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. +} +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/calendar.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; + +$langs->loadLangs(array("main", "other", "dict", "agenda", "errors", "companies")); + +$action = GETPOST('action', 'aZ09'); +$id = GETPOST('id', 'int'); +$fk_calendar = GETPOST('fk_calendar', 'int'); + +$availability = new Availabilities($db); +$result = $availability->fetch($id); + +$year = GETPOST("year", "int") ?GETPOST("year", "int") : date("Y"); +$month = GETPOST("month", "int") ?GETPOST("month", "int") : date("m"); +$week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); +$day = GETPOST("day", "int") ?GETPOST("day", "int") : date("d"); +$dateselect = dol_mktime(0, 0, 0, GETPOST('dateselectmonth', 'int'), GETPOST('dateselectday', 'int'), GETPOST('dateselectyear', 'int'), 'tzuserrel'); +if ($dateselect > 0) { + $day = GETPOST('dateselectday', 'int'); + $month = GETPOST('dateselectmonth', 'int'); + $year = GETPOST('dateselectyear', 'int'); +} +$backtopage = GETPOST("backtopage", "alpha"); + +$now = dol_now(); +$nowarray = dol_getdate($now); +$nowyear = $nowarray['year']; +$nowmonth = $nowarray['mon']; +$nowday = $nowarray['mday']; + +$prev = dol_get_prev_month($month, $year); +$prev_year = $prev['year']; +$prev_month = $prev['month']; +$next = dol_get_next_month($month, $year); +$next_year = $next['year']; +$next_month = $next['month']; + +$max_day_in_prev_month = date("t", dol_mktime(0, 0, 0, $prev_month, 1, $prev_year, 'gmt')); // Nb of days in previous month +$max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year)); // Nb of days in next month +// tmpday is a negative or null cursor to know how many days before the 1st to show on month view (if tmpday=0, 1st is monday) +$tmpday = -date("w", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')) + 2; // date('w') is 0 fo sunday +$tmpday += ((isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1) - 1); +if ($tmpday >= 1) { + $tmpday -= 7; // If tmpday is 0 we start with sunday, if -6, we start with monday of previous week. +} +// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +$firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $max_day_in_prev_month + $tmpday, $prev_year, 'tzuserrel'); +$next_day = 7 - ($max_day_in_month + 1 - $tmpday) % 7; +if ($next_day < 6) { + $next_day += 7; +} +$lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel'); + +$datechosen = GETPOST('datechosen', 'alpha'); +$datetimechosen = GETPOST('datetimechosen', 'int'); +$isdatechosen = false; +$timebooking = GETPOST("timebooking"); +$datetimebooking = GETPOST("datetimebooking", 'int'); + +/** + * Show header for booking + * + * @param string $title Title + * @param string $head Head array + * @param int $disablejs More content into html header + * @param int $disablehead More content into html header + * @param array $arrayofjs Array of complementary js files + * @param array $arrayofcss Array of complementary css files + * @return void + */ +function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '') +{ + global $user, $conf, $langs, $mysoc; + + top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers + + print ''; + + // Define urllogo + if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO') || getDolGlobalString('BOOPKCAL_PUBLIC_INTERFACE_TOPIC')) { + // Print logo + if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO')) { + $urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png'; + + if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$mysoc->logo_small); + } elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$mysoc->logo); + } elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) { + $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg'; + } + } + } + + print '
'; + // Output html code for logo + if ($urllogo || getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { + print '
'; + print '
'; + if ($urllogo) { + print ''; + print ''; + print ''; + } + if (getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { + print '
'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : $langs->trans("BookCalSystem")).''; + } + print '
'; + if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) { + print ''; + } + print '
'; + } + + print '
'; + + print '
'; +} + + +/* + * Actions + */ + +if ($action == 'add') { + $error = 0; + $urlback = ''; + if (!is_object($user)) { + $user = new User($db); + } + + $booking = new Booking($db); + + $db->begin(); + if (!GETPOST("lastname")) { + $error++; + $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Lastname"))."
\n"; + } + if (!GETPOST("firstname")) { + $error++; + $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Firstname"))."
\n"; + } + if (!GETPOST("email")) { + $error++; + $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Email"))."
\n"; + } + + if (!$error) { + $booking->ref = $booking->getNextNumRef(); + $booking->lastname = GETPOST("lastname"); + $booking->firstname = GETPOST("firstname"); + $booking->email = GETPOST("email"); + $booking->description = GETPOST("description"); + $booking->duration = GETPOST("duration"); + $booking->start = GETPOST("datetimebooking", 'int'); + $booking->fk_bookcal_availability = GETPOST("id", 'int'); + + $result = $booking->create($user); + if ($result <= 0) { + $error++; + $errmsg = ($booking->error ? $booking->error.'
' : '').join('
', $booking->errors); + } + } + if (!$error) { + $db->commit(); + $action = 'afteradd'; + } else { + $db->rollback(); + $action = 'create'; + } +} + +/* + * View + */ +$form = new Form($db); + +llxHeaderVierge('BookingCalendar'); + +dol_htmloutput_errors($errmsg); + +if ($action == 'create') { + $backtopage = $_SERVER["PHP_SELF"].'?id='.$id.'&datechosen='.$datechosen.'&fk_calendar='.$fk_calendar; +} else { + $backtopage = DOL_URL_ROOT.'/public/bookcal/index.php?id='.$fk_calendar; +} +print '
'; +print '
'; +if ($action == 'afteradd') { + print '

'; + print $langs->trans("BookingSuccessfullyBooked"); + print '

'; + print $langs->trans("BookingReservationHourAfter", dol_print_date(GETPOST("datetimebooking", 'int'), "dayhourtext")); +} else { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + + print ''; + print ''; + } + print ''; + print ''; + print '
'; + print 'Cancel'; + print ''; + if ($action == 'create') { + print ''.$langs->trans("FieldsWithAreMandatory", '*').''; + } else { + print '
'; + print ''; + print ''; + + $nav = "  \n"; + $nav .= " ".dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%b %Y"); + $nav .= " \n"; + $nav .= "   \n"; + if (empty($conf->dol_optimize_smallscreen)) { + $nav .= "   '.$langs->trans("Today").' '; + } + $nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0); + $nav .= ''; + + print $nav; + print '
'; + } + print '
'; + print ''; + print '
'; + + print '

'.(!empty($availability->label) ? $availability->label : $availability->ref).'

'; + print ''.$langs->trans("AppointmentDuration", $availability->duration).''; + if ($action == 'create') { + print '
'; + if (empty($datetimebooking)) { + $timebookingarray = explode(":", $timebooking); + $datetimebooking = dol_time_plus_duree($datetimechosen, intval($timebookingarray[0]), "h"); + $datetimebooking = dol_time_plus_duree($datetimebooking, intval($timebookingarray[1]), "i"); + } + print ''.img_picto("", "calendar")." ".dol_print_date($datetimebooking, 'dayhourtext').''; + } + print '
'; + if ($action == "create") { + print '
'; + print ''."\n"; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + // Lastname + print ''."\n"; + // Firstname + print ''."\n"; + // EMail + print ''."\n"; + + // Comments + print ''; + print ''; + print ''; + print ''."\n"; + print '
'.$langs->trans("Lastname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Email").' *
'.$langs->trans("Message").'
'."\n"; + print '
'; + print ''; + print '
'; + print '
'; + } else { + print ''; + print ' '; + // Column title of weeks numbers + echo ' '; + $i = 0; + while ($i < 7) { + print ' '."\n"; + $i++; + } + echo ' '."\n"; + $todayarray = dol_getdate($now, 'fast'); + $todaytms = dol_mktime(0, 0, 0, $todayarray['mon'], $todayarray['mday'], $todayarray['year']); + $availabilities_start = $availability->start; + $availabilities_end = $availability->end; + + for ($iter_week = 0; $iter_week < 6; $iter_week++) { + echo " \n"; + // Get date of the current day, format 'yyyy-mm-dd' + if ($tmpday <= 0) { // If number of the current day is in previous month + $currdate0 = sprintf("%04d", $prev_year).sprintf("%02d", $prev_month).sprintf("%02d", $max_day_in_prev_month + $tmpday); + } elseif ($tmpday <= $max_day_in_month) { // If number of the current day is in current month + $currdate0 = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $tmpday); + } else // If number of the current day is in next month + { + $currdate0 = sprintf("%04d", $next_year).sprintf("%02d", $next_month).sprintf("%02d", $tmpday - $max_day_in_month); + } + // Get week number for the targeted date '$currdate0' + $numweek0 = date("W", strtotime(date($currdate0))); + // Show the week number, and define column width + echo ' '; + + for ($iter_day = 0; $iter_day < 7; $iter_day++) { + if ($tmpday <= 0) { + /* Show days before the beginning of the current month (previous month) */ + $style = 'cal_other_month cal_past'; + if ($iter_day == 6) { + $style .= ' cal_other_month_right'; + } + echo ' \n"; + } elseif ($tmpday <= $max_day_in_month) { + /* Show days of the current month */ + $curtime = dol_mktime(0, 0, 0, $month, $tmpday, $year); + $style = 'cal_current_month'; + if ($iter_day == 6) { + $style .= ' cal_current_month_right'; + } + $today = 0; + if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $month && $todayarray['year'] == $year) { + $today = 1; + } + if ($curtime > $todaytms && $availabilities_start <= $curtime && $availabilities_end >= $curtime) { + $style .= ' cal_available cursorpointer'; + } + if ($curtime < $todaytms) { + $style .= ' cal_past'; + } + $dateint = sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $tmpday); + if (!empty(explode('dayevent_', $datechosen)[1]) && explode('dayevent_', $datechosen)[1] == $dateint) { + $style .= ' cal_chosen'; + $isdatechosen = true; + } + echo ' \n"; + } else { + /* Show days after the current month (next month) */ + $style = 'cal_other_month'; + if ($iter_day == 6) { + $style .= ' cal_other_month_right'; + } + echo ' \n"; + } + $tmpday++; + } + echo " \n"; + } + print '
#'; + $numdayinweek = (($i + (isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1)) % 7); + if (!empty($conf->dol_optimize_smallscreen)) { + $labelshort = array(0=>'SundayMin', 1=>'MondayMin', 2=>'TuesdayMin', 3=>'WednesdayMin', 4=>'ThursdayMin', 5=>'FridayMin', 6=>'SaturdayMin'); + print $langs->trans($labelshort[$numdayinweek]); + } else { + print $langs->trans("Day".$numdayinweek); + } + print '
'.$numweek0.''; + show_day_events($max_day_in_prev_month + $tmpday, $prev_month, $prev_year); + echo " '; + show_day_events($tmpday, $month, $year, $today); + echo "'; + show_day_events($tmpday - $max_day_in_month, $next_month, $next_year); + echo "
'; + print '
'; + print ''; + + print '
'; + print '
'; + print '
'; + + print ''; +} + +llxFooter('', 'public'); + + +/** + * Show event of a particular day + * + * @param int $day Day + * @param int $month Month + * @param int $year Year + * @param int $today Today's day + * @return void + */ +function show_day_events($day, $month, $year, $today = 0) +{ + global $conf; + if ($conf->use_javascript_ajax) { // Enable the "Show more button..." + $conf->global->MAIN_JS_SWITCH_AGENDA = 1; + } + + $dateint = sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day); + $eventdatetime = dol_mktime(-1, -1, -1, $month, $day, $year); + //print 'show_day_events day='.$day.' month='.$month.' year='.$year.' dateint='.$dateint; + + print "\n"; + + $curtime = dol_mktime(0, 0, 0, $month, $day, $year); + // Line with title of day + print '
'."\n"; + print dol_print_date($curtime, '%d'); + print '
'; + if ($today) { + print img_picto('today', 'fontawesome_circle_fas_black_7px'); + } else { + print '
'; + } + print '
'; // table + print "\n"; +} diff --git a/htdocs/public/bookcal/index.php b/htdocs/public/bookcal/index.php new file mode 100644 index 00000000000..530f37fc91e --- /dev/null +++ b/htdocs/public/bookcal/index.php @@ -0,0 +1,205 @@ + + * Copyright (C) 2006-2017 Laurent Destailleur + * Copyright (C) 2009-2012 Regis Houssin + * Copyright (C) 2023 anthony Berton + * + * 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 htdocs/public/onlinesign/newonlinesign.php + * \ingroup core + * \brief File to offer a way to make an online signature for a particular Dolibarr entity + * Example of URL: https://localhost/public/bookcal/booking.php?ref=PR... + */ + +if (!defined('NOLOGIN')) { + define("NOLOGIN", 1); // This means this output page does not require to be logged. +} +if (!defined('NOCSRFCHECK')) { + define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. +} +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/calendar.class.php'; +require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; + +$langs->loadLangs(array("main", "other", "dict", "agenda", "errors", "bookcal")); + +$action = GETPOST('action', 'aZ09'); +$id = GETPOST('id', 'int'); + +$object = new Calendar($db); +$result = $object->fetch($id); + +$availabilities = new Availabilities($db); + +$year = GETPOST("year", "int") ?GETPOST("year", "int") : date("Y"); +$month = GETPOST("month", "int") ?GETPOST("month", "int") : date("m"); +$week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); +$day = GETPOST("day", "int") ?GETPOST("day", "int") : date("d"); +$dateselect = dol_mktime(0, 0, 0, GETPOST('dateselectmonth', 'int'), GETPOST('dateselectday', 'int'), GETPOST('dateselectyear', 'int'), 'tzuserrel'); +if ($dateselect > 0) { + $day = GETPOST('dateselectday', 'int'); + $month = GETPOST('dateselectmonth', 'int'); + $year = GETPOST('dateselectyear', 'int'); +} + +$now = dol_now(); +$nowarray = dol_getdate($now); +$nowyear = $nowarray['year']; +$nowmonth = $nowarray['mon']; +$nowday = $nowarray['mday']; + + +$prev = dol_get_prev_month($month, $year); +$prev_year = $prev['year']; +$prev_month = $prev['month']; +$next = dol_get_next_month($month, $year); +$next_year = $next['year']; +$next_month = $next['month']; + +$max_day_in_prev_month = date("t", dol_mktime(0, 0, 0, $prev_month, 1, $prev_year, 'gmt')); // Nb of days in previous month +$max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year)); // Nb of days in next month +// tmpday is a negative or null cursor to know how many days before the 1st to show on month view (if tmpday=0, 1st is monday) +$tmpday = -date("w", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')) + 2; // date('w') is 0 fo sunday +$tmpday += ((isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1) - 1); +if ($tmpday >= 1) { + $tmpday -= 7; // If tmpday is 0 we start with sunday, if -6, we start with monday of previous week. +} +// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +$firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $max_day_in_prev_month + $tmpday, $prev_year, 'tzuserrel'); +$next_day = 7 - ($max_day_in_month + 1 - $tmpday) % 7; +if ($next_day < 6) { + $next_day += 7; +} +$lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel'); + +$daychosen = GETPOST('daychosen', 'alpha'); +$isdaychosen = false; + +/** + * Show header for booking + * + * @param string $title Title + * @param string $head Head array + * @param int $disablejs More content into html header + * @param int $disablehead More content into html header + * @param array $arrayofjs Array of complementary js files + * @param array $arrayofcss Array of complementary css files + * @return void + */ +function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '') +{ + global $user, $conf, $langs, $mysoc; + + top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers + + print ''; + + // Define urllogo + if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO') || getDolGlobalString('BOOPKCAL_PUBLIC_INTERFACE_TOPIC')) { + // Print logo + if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO')) { + $urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png'; + + if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$mysoc->logo_small); + } elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$mysoc->logo); + } elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) { + $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg'; + } + } + } + + print '
'; + // Output html code for logo + if ($urllogo || getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { + print '
'; + print '
'; + if ($urllogo) { + print ''; + print ''; + print ''; + } + if (getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { + print '
'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : $langs->trans("BookCalSystem")).''; + } + print '
'; + if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) { + print ''; + } + print '
'; + } + + print '
'; + + print '
'; +} + + +/* + * Actions + */ + + // None + +/* + * View + */ +$form = new Form($db); + +llxHeaderVierge('BookingCalendar'); + + +print '
'; +print '
'; +print '

'.(!empty($object->label) ? $object->label : $object->ref).'

'; + +$sql = "SELECT b.rowid, b.ref, b.label, b.start, b.end, b.duration, b.startHour, b.endHour"; +$sql .= " FROM ".MAIN_DB_PREFIX."bookcal_availabilities as b"; +$sql .= " WHERE b.status = ".(int) $availabilities::STATUS_VALIDATED; +$sql .= " AND b.fk_bookcal_calendar = ".(int) $id; + +$resql = $db->query($sql); + +if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + while ($i < $num) { + $i++; + $obj = $db->fetch_object($resql); + print ''; + } +} +print '
'; +print '
'; + +print ''; + +llxFooter('', 'public'); diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index a46e3b329be..dc453e70d3b 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5500,7 +5500,8 @@ td.event-past span { opacity: 0.5; } - +.cal_available { background: #0060d450; } +.cal_chosen { background: #0060d4; } /* ============================================================================== */ /* Ajax - Combo list for autocompletion */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 328d41e8720..4f943e7977c 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -5503,6 +5503,8 @@ td.cal_other_month { opacity: 0.8; } +.cal_available { background: #0060d450; } +.cal_chosen { background: #0060d4; } /* ============================================================================== */ /* Ajax - Combo list for autocompletion */