dolibarr 23.0.3
newonlinesign.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2023 anthony Berton <anthony.berton@bb2a.fr>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
32if (!defined('NOLOGIN')) {
33 define("NOLOGIN", 1); // This means this output page does not require to be logged.
34}
35if (!defined('NOCSRFCHECK')) {
36 define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
37}
38if (!defined('NOIPCHECK')) {
39 define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
40}
41if (!defined('NOBROWSERNOTIF')) {
42 define('NOBROWSERNOTIF', '1');
43}
44
45// For MultiCompany module.
46// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
47// Because 2 entities can have the same ref.
48$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
49if (is_numeric($entity)) {
50 define("DOLENTITY", $entity);
51}
52
53// Load Dolibarr environment
54require '../../main.inc.php';
55require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
56require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
57require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
58require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
59require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
60require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
61
73// Load translation files
74$langs->loadLangs(array("main", "other", "dict", "bills", "companies", "errors", "members", "paybox", "stripe", "propal", "commercial"));
75
76// Security check
77// No check on module enabled. Done later according to $validpaymentmethod
78
79// Get parameters
80$action = GETPOST('action', 'aZ09');
81$cancel = GETPOST('cancel', 'alpha');
82$confirm = GETPOST('confirm', 'alpha');
83
84
85$refusepropal = GETPOST('refusepropal', 'alpha');
86$message = GETPOST('message', 'aZ09');
87
88// Input are:
89// type ('invoice','order','contractline'),
90// id (object id),
91// amount (required if id is empty),
92// tag (a free text, required if type is empty)
93// currency (iso code)
94
95$suffix = GETPOST("suffix", 'aZ09');
96$source = (string) GETPOST("source", 'alpha');
97$ref = $REF = GETPOST("ref", 'alpha');
98$urlok = '';
99$urlko = '';
100
101
102if ($source == '') {
103 $source = 'proposal';
104}
105if (!empty($refusepropal)) {
106 $action = "refusepropal";
107}
108
109// Define $urlwithroot
110//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
111//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
112$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
113
114
115// Complete urls for post treatment
116$SECUREKEY = GETPOST("securekey"); // Secure key
117
118if (!empty($source)) {
119 $urlok .= 'source='.urlencode($source).'&';
120 $urlko .= 'source='.urlencode($source).'&';
121}
122if (!empty($REF)) {
123 $urlok .= 'ref='.urlencode($REF).'&';
124 $urlko .= 'ref='.urlencode($REF).'&';
125}
126if (!empty($SECUREKEY)) {
127 $urlok .= 'securekey='.urlencode($SECUREKEY).'&';
128 $urlko .= 'securekey='.urlencode($SECUREKEY).'&';
129}
130if (!empty($entity)) {
131 $urlok .= 'entity='.urlencode((string) ($entity)).'&';
132 $urlko .= 'entity='.urlencode((string) ($entity)).'&';
133}
134$urlok = preg_replace('/&$/', '', $urlok); // Remove last &
135$urlko = preg_replace('/&$/', '', $urlko); // Remove last &
136
137$creditor = $mysoc->name;
138
139$type = $source;
140if (!$action) {
141 if ($source && !$ref) {
142 httponly_accessforbidden($langs->trans('ErrorBadParameters')." - ref missing", 400, 1);
143 }
144}
145
146// Check securitykey
147$securekeyseed = '';
148if ($source == 'proposal') {
149 $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
150} elseif ($source == 'contract') {
151 $securekeyseed = getDolGlobalString('CONTRACT_ONLINE_SIGNATURE_SECURITY_TOKEN');
152} elseif ($source == 'fichinter') {
153 $securekeyseed = getDolGlobalString('FICHINTER_ONLINE_SIGNATURE_SECURITY_TOKEN');
154} elseif ($source == 'societe_rib') {
155 $securekeyseed = getDolGlobalString('SOCIETE_RIB_ONLINE_SIGNATURE_SECURITY_TOKEN');
156}
157if (!dol_verifyHash($securekeyseed.$type.$ref.(isModEnabled('multicompany') ? $entity : ''), $SECUREKEY, '0')) {
158 httponly_accessforbidden('Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref), 403, 1);
159}
160
161if ($source == 'proposal') {
162 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
163 $object = new Propal($db);
164 $result = $object->fetch(0, $ref, '', $entity);
165} elseif ($source == 'contract') {
166 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
167 $object = new Contrat($db);
168 $result = $object->fetch(0, $ref);
169} elseif ($source == 'fichinter') {
170 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
171 $object = new Fichinter($db);
172 $result = $object->fetch(0, $ref);
173} elseif ($source == 'societe_rib') {
174 require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
175 $object = new CompanyBankAccount($db);
176 $result = $object->fetch(0, $ref);
177} elseif ($source == 'expedition') {
178 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
179 $object = new Expedition($db);
180 $result = $object->fetch(0, $ref);
181} else {
182 httponly_accessforbidden($langs->trans('ErrorBadParameters')." - Bad value for source. Value not supported.", 400, 1);
183}
184
185// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
186$hookmanager->initHooks(array('onlinesign'));
187
188$error = 0;
189
190
191/*
192 * Actions
193 */
194
195if ($action == 'confirm_refusepropal' && $confirm == 'yes') { // Test on pemrission not required here. Public form. Security checked on the securekey and on mitigation
196 $db->begin();
197
198 $sql = "UPDATE ".MAIN_DB_PREFIX."propal";
199 $sql .= " SET fk_statut = ".((int) $object::STATUS_NOTSIGNED).", note_private = '".$db->escape($object->note_private)."', date_signature = '".$db->idate(dol_now())."'";
200 $sql .= " WHERE rowid = ".((int) $object->id);
201
202 dol_syslog(__FILE__, LOG_DEBUG);
203 $resql = $db->query($sql);
204 if (!$resql) {
205 $error++;
206 }
207
208 if (!$error) {
209 $db->commit();
210
211 $message = 'refused';
212 setEventMessages("PropalRefused", null, 'warnings');
213 if (method_exists($object, 'call_trigger')) {
214 // Online customer is not a user, so we use the use that validates the documents
215 $user = new User($db);
216 $user->fetch($object->user_validation_id);
217 $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
218 $result = $object->call_trigger('PROPAL_CLOSE_REFUSED', $user);
219 if ($result < 0) {
220 $error++;
221 }
222 }
223 } else {
224 $db->rollback();
225 }
226
227 $object->fetch(0, $ref);
228}
229
230// $action == "dosign" is handled later...
231
232
233/*
234 * View
235 */
236
237$form = new Form($db);
238
239$head = '';
240if (getDolGlobalString('MAIN_SIGN_CSS_URL')) {
241 $head = '<link rel="stylesheet" type="text/css" href="' . getDolGlobalString('MAIN_SIGN_CSS_URL').'?lang='.$langs->defaultlang.'">'."\n";
242}
243
244$conf->dol_hide_topmenu = 1;
245$conf->dol_hide_leftmenu = 1;
246
247$title = $langs->trans("OnlineSignature");
248
249$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
250llxHeader($head, $title, '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1);
251
252htmlPrintOnlineHeader($mysoc, $langs, 1, '', 'ONLINE_SIGN_IMAGE_PUBLIC_INTERFACE', 'ONLINE_SIGN_LOGO_'.$suffix, 'ONLINE_SIGN_LOGO');
253
254if ($action == 'refusepropal') {
255 print $form->formconfirm($_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&securekey='.urlencode($SECUREKEY).(isModEnabled('multicompany') ? '&entity='.$entity : ''), $langs->trans('RefusePropal'), $langs->trans('ConfirmRefusePropal', $object->ref), 'confirm_refusepropal', '', '', 1);
256}
257
258// Check link validity for param 'source' to avoid use of the examples as value
259if (/* $source !== '' :never empty && */ in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', 'proposal_ref', ''))) {
260 $langs->load("errors");
261 dol_print_error_email('BADREFINONLINESIGNFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $source, $ref));
262 // End of page
263 llxFooter();
264 $db->close();
265 exit;
266}
267
268print '<span id="dolpaymentspan"></span>'."\n";
269print '<div class="center">'."\n";
270print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
271print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
272print '<input type="hidden" name="action" value="dosign">'."\n";
273print '<input type="hidden" name="tag" value="'.GETPOST("tag", 'alpha').'">'."\n";
274print '<input type="hidden" name="suffix" value="'.GETPOST("suffix", 'alpha').'">'."\n";
275print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
276print '<input type="hidden" name="entity" value="'.$entity.'" />';
277print '<input type="hidden" name="page_y" value="" />';
278print '<input type="hidden" name="source" value="'.$source.'" />';
279print '<input type="hidden" name="ref" value="'.$ref.'" />';
280print "\n";
281print '<!-- Form to sign -->'."\n";
282
283if ($source == 'proposal' && getDolGlobalString('PROPOSAL_IMAGE_PUBLIC_SIGN')) {
284 print '<div class="backimagepublicproposalsign">';
285 print '<img id="idPROPOSAL_IMAGE_PUBLIC_INTERFACE" src="' . getDolGlobalString('PROPOSAL_IMAGE_PUBLIC_SIGN').'">';
286 print '</div>';
287}
288
289print '<table id="dolpublictable" summary="Payment form" class="center">'."\n";
290
291// Output introduction text
292$text = '';
293if (getDolGlobalString('ONLINE_SIGN_NEWFORM_TEXT')) {
294 $reg = array();
295 if (preg_match('/^\‍((.*)\‍)$/', $conf->global->ONLINE_SIGN_NEWFORM_TEXT, $reg)) {
296 $text .= $langs->trans($reg[1])."<br>\n";
297 } else {
298 $text .= getDolGlobalString('ONLINE_SIGN_NEWFORM_TEXT') . "<br>\n";
299 }
300 $text = '<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
301}
302if (empty($text)) {
303 if ($source == 'proposal') {
304 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageProposal", $mysoc->name).'</strong></td></tr>'."\n";
305 $text .= '<tr><td class="textpublicpayment opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromProposal", $creditor).'<br><br></td></tr>'."\n";
306 } elseif ($source == 'contract') {
307 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageContract", $mysoc->name).'</strong></td></tr>'."\n";
308 $text .= '<tr><td class="textpublicpayment opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromContract", $creditor).'<br><br></td></tr>'."\n";
309 } elseif ($source == 'fichinter') {
310 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageFichinter", $mysoc->name).'</strong></td></tr>'."\n";
311 $text .= '<tr><td class="textpublicpayment opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromFichinter", $creditor).'<br><br></td></tr>'."\n";
312 } elseif ($source == 'expedition') {
313 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageExpedition", $mysoc->name).'</strong></td></tr>'."\n";
314 $text .= '<tr><td class="textpublicpayment opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromExpedition", $creditor).'<br><br></td></tr>'."\n";
315 } else {
316 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePage".dol_ucfirst($source), $mysoc->name).'</strong></td></tr>'."\n";
317 $text .= '<tr><td class="textpublicpayment opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFrom".dol_ucfirst($source), $creditor).'<br><br></td></tr>'."\n";
318 }
319}
320print $text;
321
322// Output payment summary form
323print '<tr><td align="center">';
324print '<table with="100%" id="tablepublicpayment">';
325if ($source == 'proposal') {
326 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignProposal").' :</td></tr>'."\n";
327} elseif ($source == 'contract') {
328 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignContract").' :</td></tr>'."\n";
329} elseif ($source == 'fichinter') {
330 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignFichinter").' :</td></tr>'."\n";
331} elseif ($source == 'expedition') {
332 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignExpedition").' :</td></tr>'."\n";
333} else {
334 print '<tr><td align="left" colspan="2" class="opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSign".dol_ucfirst($source)).' :</td></tr>'."\n";
335}
336$found = false;
337$error = 0;
338
339// Signature on commercial proposal
340if ($source == 'proposal') {
341 $found = true;
342 $langs->load("proposal");
343
344 $result = $object->fetch_thirdparty($object->socid);
345
346 // Creditor
347 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
348 print '</td><td class="CTableRow2">';
349 print img_picto('', 'company', 'class="pictofixedwidth"');
350 print '<b>'.$creditor.'</b>';
351 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
352 print '</td></tr>'."\n";
353
354 // Debitor
355 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
356 print '</td><td class="CTableRow2">';
357 print img_picto('', 'company', 'class="pictofixedwidth"');
358 print '<b>'.$object->thirdparty->name.'</b>';
359 print '</td></tr>'."\n";
360
361 // Amount
362
363 $amount = '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
364 $amount .= '</td><td class="CTableRow2">';
365 $amount .= '<b>'.price($object->total_ttc, 0, $langs, 1, -1, -1, getDolCurrency()).'</b>';
366 if ($object->multicurrency_code != getDolCurrency()) {
367 $amount .= ' ('.price($object->multicurrency_total_ttc, 0, $langs, 1, -1, -1, $object->multicurrency_code).')';
368 }
369 $amount .= '</td></tr>'."\n";
370
371 // Call Hook amountPropalSign
372 $parameters = array('source' => $source);
373 $reshook = $hookmanager->executeHooks('amountPropalSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
374 if (empty($reshook)) {
375 $amount .= $hookmanager->resPrint;
376 } elseif ($reshook > 0) {
377 $amount = $hookmanager->resPrint;
378 }
379
380 print $amount;
381
382 // Object
383 $text = '<b>'.$langs->trans("SignatureProposalRef", $object->ref).'</b>';
384 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
385 print '</td><td class="CTableRow2">'.$text;
386
387 $last_main_doc_file = $object->last_main_doc;
388
389 if ($object->status == $object::STATUS_VALIDATED) {
390 $object->last_main_doc = preg_replace('/_signed-(\d+)/', '', $object->last_main_doc); // We want to be sure to not work on the signed version
391
392 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
393 // It seems document has never been generated, or was generated and then deleted.
394 // So we try to regenerate it with its default template.
395 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
396 $object->generateDocument($defaulttemplate, $langs);
397 }
398
399 $directdownloadlink = $object->getLastMainDocLink('proposal');
400 if ($directdownloadlink) {
401 print '<br><a href="'.$directdownloadlink.'">';
402 print img_mime($object->last_main_doc, '');
403 print $langs->trans("DownloadDocument").'</a>';
404 }
405 } else {
406 if ($object->status == $object::STATUS_NOTSIGNED) {
407 $directdownloadlink = $object->getLastMainDocLink('proposal');
408 if ($directdownloadlink) {
409 print '<br><a href="'.$directdownloadlink.'">';
410 print img_mime($last_main_doc_file, '');
411 print $langs->trans("DownloadDocument").'</a>';
412 }
413 } elseif ($object->status == $object::STATUS_SIGNED || $object->status == $object::STATUS_BILLED) {
414 if (preg_match('/_signed-(\d+)/', $last_main_doc_file)) { // If the last main doc has been signed
415 $last_main_doc_file_not_signed = preg_replace('/_signed-(\d+)/', '', $last_main_doc_file);
416
417 $datefilesigned = dol_filemtime($last_main_doc_file);
418 $datefilenotsigned = dol_filemtime($last_main_doc_file_not_signed);
419
420 if (empty($datefilenotsigned) || $datefilesigned > $datefilenotsigned) { // If file signed is more recent
421 $directdownloadlink = $object->getLastMainDocLink('proposal');
422 if ($directdownloadlink) {
423 print '<br><a href="'.$directdownloadlink.'">';
424 print img_mime($object->last_main_doc, '');
425 print $langs->trans("DownloadDocument").'</a>';
426 }
427 }
428 }
429 }
430 }
431
432 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
433 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
434 print '</td></tr>'."\n";
435} elseif ($source == 'contract') { // Signature on contract
436 $found = true;
437 $langs->load("contract");
438
439 $result = $object->fetch_thirdparty($object->socid);
440
441 // Proposer
442 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
443 print '</td><td class="CTableRow2">';
444 print img_picto('', 'company', 'class="pictofixedwidth"');
445 print '<b>'.$creditor.'</b>';
446 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
447 print '</td></tr>'."\n";
448
449 // Target
450 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
451 print '</td><td class="CTableRow2">';
452 print img_picto('', 'company', 'class="pictofixedwidth"');
453 print '<b>'.$object->thirdparty->name.'</b>';
454 print '</td></tr>'."\n";
455
456 // Object
457 $text = '<b>'.$langs->trans("SignatureContractRef", $object->ref).'</b>';
458 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
459 print '</td><td class="CTableRow2">'.$text;
460
461 $last_main_doc_file = $object->last_main_doc;
462
463 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
464 // It seems document has never been generated, or was generated and then deleted.
465 // So we try to regenerate it with its default template.
466 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
467 $object->generateDocument($defaulttemplate, $langs);
468 }
469
470 $directdownloadlink = $object->getLastMainDocLink('contract');
471 if ($directdownloadlink) {
472 print '<br><a href="'.$directdownloadlink.'">';
473 print img_mime($object->last_main_doc, '');
474 if ($message == "signed") {
475 print $langs->trans("DownloadSignedDocument").'</a>';
476 } else {
477 print $langs->trans("DownloadDocument").'</a>';
478 }
479 }
480
481
482 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
483 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
484 print '</td></tr>'."\n";
485} elseif ($source == 'fichinter') {
486 // Signature on fichinter
487 $found = true;
488 $langs->load("interventions");
489
490 $result = $object->fetch_thirdparty($object->socid);
491
492 // Proposer
493 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
494 print '</td><td class="CTableRow2">';
495 print img_picto('', 'company', 'class="pictofixedwidth"');
496 print '<b>'.$creditor.'</b>';
497 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
498 print '</td></tr>'."\n";
499
500 // Target
501 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
502 print '</td><td class="CTableRow2">';
503 print img_picto('', 'company', 'class="pictofixedwidth"');
504 print '<b>'.$object->thirdparty->name.'</b>';
505 print '</td></tr>'."\n";
506
507 // Object
508 $text = '<b>'.$langs->trans("SignatureFichinterRef", $object->ref).'</b>';
509 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
510 print '</td><td class="CTableRow2">'.$text;
511
512 $last_main_doc_file = $object->last_main_doc;
513
514 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
515 // It seems document has never been generated, or was generated and then deleted.
516 // So we try to regenerate it with its default template.
517 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
518 $object->generateDocument($defaulttemplate, $langs);
519 }
520
521 $directdownloadlink = $object->getLastMainDocLink('fichinter');
522 if ($directdownloadlink) {
523 print '<br><a href="'.$directdownloadlink.'">';
524 print img_mime($object->last_main_doc, '');
525 if ($message == "signed") {
526 print $langs->trans("DownloadSignedDocument").'</a>';
527 } else {
528 print $langs->trans("DownloadDocument").'</a>';
529 }
530 }
531 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
532 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
533 print '</td></tr>'."\n";
534} elseif ($source == 'societe_rib') {
535 $found = true;
536 $langs->loadLangs(array("companies", "commercial", "withdrawals"));
537
538 $result = $object->fetch_thirdparty();
539
540 // Proposer
541 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("CreditorName");
542 print '</td><td class="CTableRow2">';
543 print img_picto('', 'company', 'class="pictofixedwidth"');
544 print '<b>' . $creditor . '</b>';
545 print '<input type="hidden" name="creditor" value="' . $creditor . '">';
546 print '</td></tr>' . "\n";
547
548 // Target
549 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("ThirdParty");
550 print '</td><td class="CTableRow2">';
551 print img_picto('', 'company', 'class="pictofixedwidth"');
552 print '<b>' . $object->thirdparty->name . '</b>';
553 print '</td></tr>' . "\n";
554
555 // Object
556 $text = '<b>' . $langs->trans("Signature" . dol_ucfirst($source) . "Ref", $object->ref) . '</b>';
557 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("Designation");
558 print '</td><td class="CTableRow2">' . $text;
559
560 $last_main_doc_file = $object->last_main_doc;
561 $diroutput = $conf->societe->multidir_output[$object->thirdparty->entity].'/'
562 .dol_sanitizeFileName((string) $object->thirdparty->id).'/';
563 if ((empty($last_main_doc_file) ||
564 !dol_is_file($diroutput
565 .$langs->transnoentitiesnoconv("SepaMandateShort").' '.$object->id."-".dol_sanitizeFileName($object->rum).".pdf"))
566 && $message != "signed") {
567 // It seems document has never been generated, or was generated and then deleted.
568 // So we try to regenerate it with its default template.
569 //$defaulttemplate = 'sepamandate';
570 $defaulttemplate = getDolGlobalString("BANKADDON_PDF");
571
572 $object->setDocModel($user, $defaulttemplate);
573 $moreparams = array(
574 'use_companybankid' => $object->id,
575 'force_dir_output' => $diroutput
576 );
577 $result = $object->thirdparty->generateDocument($defaulttemplate, $langs, 0, 0, 0, $moreparams);
578 $object->last_main_doc = $object->thirdparty->last_main_doc;
579 }
580 $directdownloadlink = $object->getLastMainDocLink('company');
581 if ($directdownloadlink) {
582 print '<br><a href="'.$directdownloadlink.'">';
583 print img_mime($object->last_main_doc, '');
584 if ($message == "signed") {
585 print $langs->trans("DownloadSignedDocument").'</a>';
586 } else {
587 print $langs->trans("DownloadDocument").'</a>';
588 }
589 }
590} elseif ($source == 'expedition') {
591 // Signature on expedition
592 $found = true;
593 $langs->load("interventions");
594
595 $result = $object->fetch_thirdparty($object->socid);
596
597 // Proposer
598 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
599 print '</td><td class="CTableRow2">';
600 print img_picto('', 'company', 'class="pictofixedwidth"');
601 print '<b>'.$creditor.'</b>';
602 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
603 print '</td></tr>'."\n";
604
605 // Target
606 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
607 print '</td><td class="CTableRow2">';
608 print img_picto('', 'company', 'class="pictofixedwidth"');
609 print '<b>'.$object->thirdparty->name.'</b>';
610 print '</td></tr>'."\n";
611
612 // Object
613 $text = '<b>'.$langs->trans("SignatureFichinterRef", $object->ref).'</b>';
614 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
615 print '</td><td class="CTableRow2">'.$text;
616
617 $last_main_doc_file = $object->last_main_doc;
618 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
619 // It seems document has never been generated, or was generated and then deleted.
620 // So we try to regenerate it with its default template.
621 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
622 $object->generateDocument($defaulttemplate, $langs);
623 }
624 $directdownloadlink = $object->getLastMainDocLink('', 0, 0);
625 if ($directdownloadlink) {
626 print '<br><a href="'.$directdownloadlink.'">';
627 print img_mime($object->last_main_doc, '');
628 if ($message == "signed") {
629 print $langs->trans("DownloadSignedDocument").'</a>';
630 } else {
631 print $langs->trans("DownloadDocument").'</a>';
632 }
633 }
634 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
635 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
636 print '</td></tr>'."\n";
637} else {
638 $found = true;
639 $langs->load('companies');
640
641 if (!empty($object->socid) || !empty($object->fk_soc)) {
642 $result = $object->fetch_thirdparty();
643 }
644
645 // Proposer
646 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
647 print '</td><td class="CTableRow2">';
648 print img_picto('', 'company', 'class="pictofixedwidth"');
649 print '<b>'.$creditor.'</b>';
650 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
651 print '</td></tr>'."\n";
652
653 // Target
654 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
655 print '</td><td class="CTableRow2">';
656 print img_picto('', 'company', 'class="pictofixedwidth"');
657 print '<b>'.$object->thirdparty->name.'</b>';
658 print '</td></tr>'."\n";
659
660 // Object
661 $text = '<b>'.$langs->trans("Signature".dol_ucfirst($source)."Ref", $object->ref).'</b>';
662 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
663 print '</td><td class="CTableRow2">'.$text;
664
665 $last_main_doc_file = $object->last_main_doc;
666
667 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
668 // It seems document has never been generated, or was generated and then deleted.
669 // So we try to regenerate it with its default template.
670 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
671 $object->generateDocument($defaulttemplate, $langs);
672 }
673
674 $directdownloadlink = $object->getLastMainDocLink($source);
675 if ($directdownloadlink) {
676 print '<br><a href="'.$directdownloadlink.'">';
677 print img_mime($object->last_main_doc, '');
678 if ($message == "signed") {
679 print $langs->trans("DownloadSignedDocument").'</a>';
680 } else {
681 print $langs->trans("DownloadDocument").'</a>';
682 }
683 }
684}
685
686// Call Hook addFormSign
687$parameters = array('source' => $source);
688$reshook = $hookmanager->executeHooks('addFormSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
689
690if (!$found && !$mesg) {
691 $mesg = $langs->transnoentitiesnoconv("ErrorBadParameters");
692}
693
694if ($mesg) {
695 print '<tr><td class="center" colspan="2"><br><div class="warning">'.dol_escape_htmltag($mesg).'</div></td></tr>'."\n";
696}
697
698print '</table>'."\n";
699print "\n";
700
701if ($action != 'dosign') {
702 if ($found && !$error) {
703 // We are in a management option and no error
704 } else {
705 dol_print_error_email('ERRORNEWONLINESIGN');
706 }
707} else {
708 // Print
709}
710
711print '</td></tr>'."\n";
712print '<tr><td class="center">';
713
714
715if ($action == "dosign" && empty($cancel)) {
716 // Show the field to sign
717 print '<div class="tablepublicpayment">';
718 print '<input type="text" class="paddingleftonly marginleftonly paddingrightonly marginrightonly marginbottomonly borderbottom" id="name" placeholder="'.$langs->trans("Lastname").'" autofocus>';
719 print '<div id="signature" style="border:solid;"></div>';
720 print '</div>';
721 print '<input type="button" class="small noborderbottom cursorpointer buttonreset" id="clearsignature" value="'.$langs->trans("ClearSignature").'">';
722
723 // Do not use class="reposition" here: It breaks the submit and there is a message on top to say it's ok, so going back top is better.
724 print '<div>';
725 print '<input type="button" class="button marginleftonly marginrightonly" id="signbutton" value="'.$langs->trans("Sign").'">';
726 print '<input type="submit" class="button butActionDelete marginleftonly marginrightonly" name="cancel" value="'.$langs->trans("Cancel").'">';
727 print '</div>';
728
729 // Define $urlwithroot
730 $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
731 $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
732 //$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
733 // TODO Replace DOL_URL_ROOT with $urlwithroot ?
734
735 // Add js code managed into the div #signature
736 $urltogo = $_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&source='.urlencode($source).'&message=signed&securekey='.urlencode($SECUREKEY).(isModEnabled('multicompany') ? '&entity='.(int) $entity : '');
737 print '<script language="JavaScript" type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jSignature/jSignature.js"></script>
738 <script type="text/javascript">
739 $(document).ready(function() {
740 $("#signature").jSignature({ color:"#000", lineWidth:0, '.(empty($conf->dol_optimize_smallscreen) ? '' : 'width: 280, ').'height: 180});
741
742 $("#signature").on("change",function(){
743 $("#clearsignature").css("display","");
744 $("#signbutton").attr("disabled",false);
745 if(!$._data($("#signbutton")[0], "events")){
746 $("#signbutton").on("click",function(){
747 console.log("We click on button sign");
748 document.body.style.cursor = \'wait\';
749 var signature = $("#signature").jSignature("getData", "image");
750 var name = document.getElementById("name").value;
751 $.ajax({
752 type: "POST",
753 url: \''.DOL_URL_ROOT.'/core/ajax/onlineSign.php\',
754 dataType: "text",
755 data: {
756 "action" : \'importSignature\',
757 "token" : \''.newToken().'\',
758 "signaturebase64" : signature,
759 "onlinesignname" : name,
760 "ref" : \''.dol_escape_js($REF).'\',
761 "securekey" : \''.dol_escape_js($SECUREKEY).'\',
762 "mode" : \''.dol_escape_js($source).'\',
763 "entity" : \''.dol_escape_js((string) $entity).'\',
764 },
765 success: function(response) {
766 if (response.trim() === "success") {
767 console.log("Success on saving signature");
768 window.location.replace(\''.dol_escape_js($urltogo).'\');
769 } else {
770 document.body.style.cursor = \'auto\';
771 console.error(response);
772 alert("Error on calling the core/ajax/onlineSign.php. See console log.");
773 }
774 },
775 error: function(response) {
776 document.body.style.cursor = \'auto\';
777 console.error(response);
778 alert("Error on calling the core/ajax/onlineSign.php. "+response.responseText);
779 }
780 });
781 });
782 }
783 });
784
785 $("#clearsignature").on("click",function(){
786 $("#signature").jSignature("clear");
787 $("#signbutton").attr("disabled",true);
788 // document.getElementById("onlinesignname").value = "";
789 });
790
791 $("#signbutton").attr("disabled",true);
792 });
793 </script>';
794} else {
795 if ($source == 'proposal') {
796 if ($object->status == $object::STATUS_SIGNED) {
797 print '<br>';
798 if ($message == 'signed') {
799 print img_picto('', 'check', '', 0, 0, 0, '', 'size2x').'<br>';
800 print '<span class="ok">'.$langs->trans("PropalSigned").'</span>';
801 } else {
802 print img_picto('', 'check', '', 0, 0, 0, '', 'size2x').'<br>';
803 print '<span class="ok">'.$langs->trans("PropalAlreadySigned").'</span>';
804 }
805 } elseif ($object->status == $object::STATUS_NOTSIGNED) {
806 print '<br>';
807 if ($message == 'refused') {
808 print img_picto('', 'cross', '', 0, 0, 0, '', 'size2x').'<br>';
809 print '<span class="ok">'.$langs->trans("PropalRefused").'</span>';
810 } else {
811 print img_picto('', 'cross', '', 0, 0, 0, '', 'size2x').'<br>';
812 print '<span class="warning">'.$langs->trans("PropalAlreadyRefused").'</span>';
813 }
814 } else {
815 print '<input type="submit" class="butAction small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignPropal").'">';
816 print '<input name="refusepropal" type="submit" class="butActionDelete small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("RefusePropal").'">';
817 }
818 } elseif ($source == 'contract') {
819 if ($message == 'signed') {
820 print '<span class="ok">'.$langs->trans("ContractSigned").'</span>';
821 } else {
822 print '<input type="submit" class="butAction small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignContract").'">';
823 }
824 } elseif ($source == 'fichinter') {
825 if ($message == 'signed') {
826 print '<span class="ok">'.$langs->trans("FichinterSigned").'</span>';
827 } else {
828 print '<input type="submit" class="butAction small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignFichinter").'">';
829 }
830 } elseif ($source == 'expedition') {
831 if ($message == 'signed' || $object->signed_status == Expedition::$SIGNED_STATUSES['STATUS_SIGNED_SENDER']) {
832 print '<span class="ok">'.$langs->trans("ExpeditionSigned").'</span>';
833 } else {
834 print '<input type="submit" class="butAction small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignExpedition").'">';
835 }
836 } else {
837 if ($message == 'signed') {
838 print '<span class="ok">'.$langs->trans(dol_ucfirst($source)."Signed").'</span>';
839 } else {
840 print '<input type="submit" class="butAction small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("Sign".dol_ucfirst($source)).'">';
841 }
842 }
843}
844print '</td></tr>'."\n";
845print '</table>'."\n";
846
847print '</form>'."\n";
848print '</div>'."\n";
849print '<br>';
850
851
853
854llxFooter('', 'public');
855
856$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
global $dolibarr_main_url_root
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
$object ref
Definition info.php:90
Class to manage bank accounts description of third parties.
Class to manage generation of HTML components Only common components must be here.
Class to manage proposals.
Class to manage Dolibarr users.
htmlPrintOnlineHeader($mysoc, $langs, $showlogo=1, $alttext='', $subimageconst='', $altlogo1='', $altlogo2='')
Show the header of a company in HTML public pages.
htmlPrintOnlineFooter($fromcompany, $langs, $addformmessage=0, $suffix='', $object=null)
Show footer of company in HTML public pages.
global $mysoc
dol_filemtime($pathoffile)
Return time of a file.
dol_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dol_ucfirst($string, $encoding="UTF-8")
Convert first character of the first word of a string to upper.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error_email($prefixcode, $errormessage='', $errormessages=array(), $morecss='error', $email='')
Show a public email and error code to contact if technical error.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...