Fix Bookcal module add booking (#25570)

* first push : booking can be done

* add verification of booking aleardy booked

* add page after booking

---------

Co-authored-by: Hystepik <lucas.marcouiller@gmail.com>
This commit is contained in:
Lucas Marcouiller 2023-08-08 21:44:23 +02:00 committed by GitHub
parent 59eb53295a
commit 6c5704924e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1437 additions and 54 deletions

View File

@ -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) {

View File

@ -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 '<i> Link : </i> <strong> '. DOL_DOCUMENT_ROOT.'/public/bookcal/booking.php?id='.$object->id . '</strong>' ;
}
// 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) {

View File

@ -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 '<div class="fichecenter"><div class="fichethirdleft">';
// 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
<th colspan="3">id</th>
<th colspan="3">ref</th>
<th colspan="3">name</th>
<th colspan="3">date</th>
<th colspan="3">hour</th>
<th colspan="3">duration</th>
<th colspan="3">description</th>
@ -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 '<td colspan="3" class="nowrap">' . $myobjectstatic->id . "</td>";
print '<td colspan="3" class="nowrap">' . $myobjectstatic->ref . "</td>";
print '<td colspan="3" class="nowrap">' . $myobjectstatic->firstname . " " . $myobjectstatic->lastname . "</td>";
print '<td colspan="3" class="nowrap">' . $myobjectstatic->start . "</td>";
print '<td colspan="3" class="nowrap">' . dol_print_date($myobjectstatic->start, 'dayhourtext') . "</td>";
print '<td colspan="3" class="nowrap">' . $myobjectstatic->duration . "</td>";
print '<td colspan="3" class="nowrap">' . $myobjectstatic->description . "</td>";
$i++;

View File

@ -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 '<i> Link : </i> <strong> <a href="'. DOL_URL_ROOT.'/public/bookcal/index.php?id='.$object->id . '">Public page</a></strong>' ;
}
// 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) {

View File

@ -0,0 +1,123 @@
<?php
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file /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);

View File

@ -0,0 +1,146 @@
<?php
/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2007 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2008 Raphael Bertrand (Resultic) <raphael.bertrand@resultic.fr>
* Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* 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')."<br>\n";
$texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
$texte .= '<input type="hidden" name="token" value="'.newToken().'">';
$texte .= '<input type="hidden" name="action" value="updateMask">';
$texte .= '<input type="hidden" name="maskconst" value="BOOKCAL_BOOKING_ADVANCED_MASK">';
$texte .= '<table class="nobordernopadding centpercent">';
$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 .= '<tr><td>'.$langs->trans("Mask").':</td>';
$texte .= '<td class="right">'.$form->textwithpicto('<input type="text" class="flat minwidth175" name="maskvalue" value="'.getDolGlobalString('BOOKCAL_BOOKING_ADVANCED_MASK').'">', $tooltip, 1, 1).'</td>';
$texte .= '<td class="left" rowspan="2">&nbsp; <input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'" name="Button"></td>';
$texte .= '</tr>';
$texte .= '</table>';
$texte .= '</form>';
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;
}
}

View File

@ -0,0 +1,161 @@
<?php
/* Copyright (C) 2005-2010 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* 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;
}
}

View File

@ -0,0 +1,194 @@
<?php
/* Copyright (C) 2003-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
* Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* 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");
}
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,529 @@
<?php
/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2023 anthony Berton <anthony.berton@bb2a.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \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 '<body id="mainbody" class="publicnewmemberform">';
// 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&amp;entity='.$conf->entity.'&amp;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&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$mysoc->logo);
} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
}
}
}
print '<div class="center">';
// Output html code for logo
if ($urllogo || getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) {
print '<div class="backgreypublicpayment">';
print '<div class="logopublicpayment">';
if ($urllogo) {
print '<a href="'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : dol_buildpath('/public/ticket/index.php?entity='.$conf->entity, 1)).'">';
print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
print '>';
print '</a>';
}
if (getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) {
print '<div class="clearboth"></div><strong>'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : $langs->trans("BookCalSystem")).'</strong>';
}
print '</div>';
if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) {
print '<div class="poweredbypublicpayment opacitymedium right hideonsmartphone"><a class="poweredbyhref" href="https://www.dolibarr.org?utm_medium=website&utm_source=poweredby" target="dolibarr" rel="noopener">'.$langs->trans("PoweredBy").'<br><img src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
}
print '</div>';
}
print '</div>';
print '<div class="divmainbodylarge">';
}
/*
* 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"))."<br>\n";
}
if (!GETPOST("firstname")) {
$error++;
$errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Firstname"))."<br>\n";
}
if (!GETPOST("email")) {
$error++;
$errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Email"))."<br>\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.'<br>' : '').join('<br>', $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 '<div class="bookcalpublicarea centpercent center" style="min-width:30%;position:absolute;width:fit-content;height:70%;top:60%;left: 50%;transform: translate(-50%, -50%);">';
print '<div class="bookcalform boxtable" style="border:thin solid gray;padding:5px;min-height:50%">';
if ($action == 'afteradd') {
print '<h2>';
print $langs->trans("BookingSuccessfullyBooked");
print '</h2>';
print $langs->trans("BookingReservationHourAfter", dol_print_date(GETPOST("datetimebooking", 'int'), "dayhourtext"));
} else {
print '<table>';
print '<tr>';
print '<td>';
print '<a href="'.$backtopage.'">Cancel</a>';
print '</td>';
print '<td>';
if ($action == 'create') {
print '<span class="opacitymedium">'.$langs->trans("FieldsWithAreMandatory", '*').'</span>';
} else {
print '<form name="formsearch" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '<input type="hidden" name="fk_calendar" value="'.$fk_calendar.'">';
$nav = "<a href=\"?id=".$id."&year=".$prev_year."&month=".$prev_month.$param."&fk_calendar=".$fk_calendar."\"><i class=\"fa fa-chevron-left\"></i></a> &nbsp;\n";
$nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%b %Y");
$nav .= " </span>\n";
$nav .= " &nbsp; <a href=\"?id=".$id."&year=".$next_year."&month=".$next_month.$param."&fk_calendar=".$fk_calendar."\"><i class=\"fa fa-chevron-right\"></i></a>\n";
if (empty($conf->dol_optimize_smallscreen)) {
$nav .= " &nbsp; <a href=\"?id=".$id."&year=".$nowyear."&amp;month=".$nowmonth."&amp;day=".$nowday.$param.'&amp;fk_calendar='.$fk_calendar.'" class="datenowlink">'.$langs->trans("Today").'</a> ';
}
$nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0);
$nav .= '<button type="submit" class="liste_titre button_search valignmiddle" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
print $nav;
print '</form>';
}
print '</td>';
print '<td>';
print '<div class="center hidden bookingtab" style="height:50%">';
print '<span id="bookingtabspandate"></span>';
print '</div>';
print '</td>';
print '</tr>';
print '<tr>';
print '<td>';
print '<h2>'.(!empty($availability->label) ? $availability->label : $availability->ref).'</h2>';
print '<span>'.$langs->trans("AppointmentDuration", $availability->duration).'</span>';
if ($action == 'create') {
print '<br>';
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 '<span>'.img_picto("", "calendar")."&nbsp;".dol_print_date($datetimebooking, 'dayhourtext').'</span>';
}
print '</td>';
print '<td>';
if ($action == "create") {
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<table class="border" summary="form to subscribe" id="tablesubscribe">'."\n";
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="add">';
print '<input type="hidden" name="datetimebooking" value="'.$datetimebooking.'">';
print '<input type="hidden" name="datechosen" value="'.$datechosen.'">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '<input type="hidden" name="fk_calendar" value="'.$fk_calendar.'">';
print '<input type="hidden" name="duration" value="'.$availability->duration.'">';
// Lastname
print '<tr><td>'.$langs->trans("Lastname").' <span class="star">*</span></td><td><input type="text" name="lastname" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('lastname')).'"></td></tr>'."\n";
// Firstname
print '<tr><td>'.$langs->trans("Firstname").' <span class="star">*</span></td><td><input type="text" name="firstname" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('firstname')).'"></td></tr>'."\n";
// EMail
print '<tr><td>'.$langs->trans("Email").' <span class="star">*</span></td><td><input type="text" name="email" maxlength="255" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('email')).'"></td></tr>'."\n";
// Comments
print '<tr>';
print '<td class="tdtop">'.$langs->trans("Message").'</td>';
print '<td class="tdtop"><textarea name="description" id="description" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_2.'">'.dol_escape_htmltag(GETPOST('description', 'restricthtml'), 0, 1).'</textarea></td>';
print '</tr>'."\n";
print '</table>'."\n";
print '<div class="center">';
print '<input type="submit" value="'.$langs->trans("Submit").'" id="submitsave" class="button">';
print '</div>';
print '</form>';
} else {
print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month">';
print ' <tr class="liste_titre">';
// Column title of weeks numbers
echo ' <td class="center">#</td>';
$i = 0;
while ($i < 7) {
print ' <td class="center bold uppercase tdfordaytitle'.($i == 0 ? ' borderleft' : '').'">';
$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 ' </td>'."\n";
$i++;
}
echo ' </tr>'."\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 " <tr>\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 ' <td class="center weeknumber opacitymedium" width="2%">'.$numweek0.'</td>';
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 ' <td class="'.$style.' nowrap tdtop" width="14%">';
show_day_events($max_day_in_prev_month + $tmpday, $prev_month, $prev_year);
echo " </td>\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 ' <td class="'.$style.' nowrap tdtop" width="14%">';
show_day_events($tmpday, $month, $year, $today);
echo "</td>\n";
} else {
/* Show days after the current month (next month) */
$style = 'cal_other_month';
if ($iter_day == 6) {
$style .= ' cal_other_month_right';
}
echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
show_day_events($tmpday - $max_day_in_month, $next_month, $next_year);
echo "</td>\n";
}
$tmpday++;
}
echo " </tr>\n";
}
print '</table>';
print '</td>';
print '<td>';
print '<div class="center hidden bookingtab" style="height:50%">';
print '<div style="margin-top:8px;max-height:330px" class="div-table-responsive-no-min">';
print '<form name="formbooking" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="create">';
print '<input type="hidden" id="datechosen" name="datechosen" value="">';
print '<input type="hidden" id="datetimechosen" name="datetimechosen" value="">';
print '<input type="hidden" id="fk_calendar" name="fk_calendar" value="'.$fk_calendar.'">';
$hoursavailabilities_start = $availability->startHour;
$hoursavailabilities_end = $availability->endHour;
$hoursavailabilities_duration = $availability->duration;
for ($i=$hoursavailabilities_start; $i < $hoursavailabilities_end; $i++) {
for ($j=0; $j < 60 ; $j += $hoursavailabilities_duration) {
$timestring = ($i < 10 ? '0'.$i : $i).':'.($j < 10 ? '0'.$j : $j);
$timestringid = ($i < 10 ? '0'.$i : $i).''.($j < 10 ? '0'.$j : $j);
print '<span id="'.$timestringid.'" class="btnformbooking"><input type="submit" class="button" name="timebooking" value="'.$timestring.'"><br></span>';
}
}
print '</form>';
print '</div>';
print '</div>';
print '</td>';
}
print '</td>';
print '</tr>';
print '</table>';
print '</div>';
print '</div>';
print '<script>';
print '
function hideTimeBooking(time){
console.log("#"+time);
$("#"+time).hide();
}';
print '$(document).ready(function() {
$(".cal_available").on("click", function(){
$(".cal_chosen").removeClass("cal_chosen");
$(this).addClass("cal_chosen");
$.ajax({
type: "POST",
url: "'.DOL_URL_ROOT.'/core/ajax/bookcalAjax.php",
data: {
action: "verifyavailability",
id: '.$id.',
datetocheck: $(this).children("div").data("datetime"),
token: "'.currentToken().'",
}
}).done(function (data) {
data = JSON.parse(data);
$(".btnformbooking").show();
console.log("We show all booking");
if(data["code"] == "SUCCESS"){
timearray = data["content"];
timearray.forEach((time) => hideTimeBooking(time));
console.log("We hide all taken time for booking");
} else {
if(data["code"] == "NO_DATA_FOUND"){
console.log("No booking to hide");
} else {
console.log(data["message"]);
}
}
});
$(".bookingtab").removeClass("hidden");
$("#bookingtabspandate").text($(this).children("div").data("date"));
$("#datechosen").val($(this).children("div").attr("id"));
$("#datetimechosen").val($(this).children("div").data("datetime"));
});
$("btnformbooking")
'.($datechosen ? '$(".cal_chosen").trigger( "click" )' : '').'
});';
print '</script>';
}
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 '<div id="dayevent_'.$dateint.'" class="dayevent tagtable centpercent nobordernopadding" data-datetime="'.$eventdatetime.'" data-date="'.dol_print_date($eventdatetime, "daytext").'">'."\n";
print dol_print_date($curtime, '%d');
print '<br>';
if ($today) {
print img_picto('today', 'fontawesome_circle_fas_black_7px');
} else {
print '<br>';
}
print '</div>'; // table
print "\n";
}

View File

@ -0,0 +1,205 @@
<?php
/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2023 anthony Berton <anthony.berton@bb2a.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \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 '<body id="mainbody" class="publicnewmemberform">';
// 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&amp;entity='.$conf->entity.'&amp;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&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$mysoc->logo);
} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
}
}
}
print '<div class="center">';
// Output html code for logo
if ($urllogo || getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) {
print '<div class="backgreypublicpayment">';
print '<div class="logopublicpayment">';
if ($urllogo) {
print '<a href="'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : dol_buildpath('/public/ticket/index.php?entity='.$conf->entity, 1)).'">';
print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
print '>';
print '</a>';
}
if (getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) {
print '<div class="clearboth"></div><strong>'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : $langs->trans("BookCalSystem")).'</strong>';
}
print '</div>';
if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) {
print '<div class="poweredbypublicpayment opacitymedium right hideonsmartphone"><a class="poweredbyhref" href="https://www.dolibarr.org?utm_medium=website&utm_source=poweredby" target="dolibarr" rel="noopener">'.$langs->trans("PoweredBy").'<br><img src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
}
print '</div>';
}
print '</div>';
print '<div class="divmainbodylarge">';
}
/*
* Actions
*/
// None
/*
* View
*/
$form = new Form($db);
llxHeaderVierge('BookingCalendar');
print '<div class="bookcalpublicarea centpercent" style="position:absolute;top:50%;transform: translateY(-50%)">';
print '<div class="bookcalform center" style="width:70%;padding:5px;max-height:360px">';
print '<h2>'.(!empty($object->label) ? $object->label : $object->ref).'</h2>';
$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 '<a href="'.DOL_URL_ROOT.'/public/bookcal/booking.php?id='.$obj->rowid.'&fk_calendar='.$id.'"><button type="button">'.(!empty($obj->label) ? $obj->label : $obj->ref).'</button>';
}
}
print '</div>';
print '</div>';
print '<script>';
print '</script>';
llxFooter('', 'public');

View File

@ -5500,7 +5500,8 @@ td.event-past span {
opacity: 0.5;
}
.cal_available { background: #0060d450; }
.cal_chosen { background: #0060d4; }
/* ============================================================================== */
/* Ajax - Combo list for autocompletion */

View File

@ -5503,6 +5503,8 @@ td.cal_other_month {
opacity: 0.8;
}
.cal_available { background: #0060d450; }
.cal_chosen { background: #0060d4; }
/* ============================================================================== */
/* Ajax - Combo list for autocompletion */