dolibarr 24.0.0-beta
cashcontrol_card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2013 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@capnetworks.com>
5 * Copyright (C) 2013 Charles-Fr BENKE <charles.fr@benke.fr>
6 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
7 * Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
8 * Copyright (C) 2018 Andreu Bisquerra <jove@bisquerra.com>
9 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
32// Load Dolibarr environment
33require '../../main.inc.php';
42require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
43require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
44require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
45require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
46require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
48
49$langs->loadLangs(array("install", "cashdesk", "admin", "banks", "blockedlog"));
50
51$action = GETPOST('action', 'aZ09');
52$backtopage = GETPOST('backtopage', 'aZ09');
53
54$id = GETPOSTINT('id');
55$ref = GETPOST('ref', 'alpha');
56$label = GETPOST("label");
57
58$now = dol_now();
59
60$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
61$sortfield = GETPOST('sortfield', 'aZ09comma');
62$sortorder = GETPOST('sortorder', 'aZ09comma');
63$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
64if (empty($page) || $page == -1) {
65 $page = 0;
66} // If $page is not defined, or '' or -1
67$offset = $limit * $page;
68$pageprev = $page - 1;
69$pagenext = $page + 1;
70if (!$sortfield) {
71 $sortfield = 'rowid';
72}
73if (!$sortorder) {
74 $sortorder = 'ASC';
75}
76$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'thirdpartylist';
77
78if ($contextpage == 'takepos') {
79 $optioncss = 'print';
80}
81
82$arrayofpaymentmode = array('cash' => 'Cash', 'cheque' => 'Cheque', 'card' => 'CreditCard');
83
84$arrayofposavailable = array();
85if (isModEnabled('cashdesk')) {
86 $arrayofposavailable['cashdesk'] = $langs->trans('CashDesk').' (cashdesk)';
87}
88if (isModEnabled('takepos')) {
89 $arrayofposavailable['takepos'] = $langs->trans('TakePOS').' (takepos)';
90}
91// TODO Add hook here to allow other POS to add themself
92
94$extrafields = new ExtraFields($db);
95
96// fetch optionals attributes and labels
97$extrafields->fetch_name_optionals_label($object->table_element);
98
99// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
100$hookmanager->initHooks(array('cashcontrolcard', 'globalcard'));
101
102// Load object
103include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
104
105// Security check
106if ($user->socid > 0) { // Protection if external user
107 //$socid = $user->socid;
109}
110if (!$user->hasRight("cashdesk", "run") && !$user->hasRight("takepos", "run")) {
112}
113
114$permissiontoadd = $user->hasRight("takepos", "run");
115$permissiontodelete = $user->hasRight("takepos", "run") || ($permissiontoadd && $object->status == 0);
116$permissiontoeditextra = $permissiontoadd;
117if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
118 // For action 'update_extras', is there a specific permission set for the attribute to update
119 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
120}
121$permissiontoreopen = $user->hasRight("takepos", "run");
122
123
124$sqlfilteronopdate = '';
125
126// Must be after the fetch
127$datestart = null;
128$dateend = null;
129$syear = (GETPOSTISSET('closeyear') ? GETPOSTINT('closeyear') : dol_print_date($now, "%Y", 'tzuserrel'));
130$smonth = (GETPOSTISSET('closemonth') ? GETPOSTINT('closemonth') : dol_print_date($now, "%m", 'tzuserrel'));
131$sday = (GETPOSTISSET('closeday') ? GETPOSTINT('closeday') : dol_print_date($now, "%d", 'tzuserrel'));
132// TODO Add a global option to define the end hours when doing a cash control
133$shour = 0;
134$smin = 0;
135$ssec = 0;
136
137if ($object->id > 0) {
138 // When object is known, we must define first the end date (stored in database with different components) and deduct the start date
139 if (empty($object->day_close) && !empty($object->month_close)) { // Full day
140 $dateend = dol_mktime((int) $object->hour_close, (int) $object->min_close, (int) $object->sec_close, $object->month_close, 1, $object->year_close, 'gmt');
141 $dateend = dol_time_plus_duree($dateend, +1, 'm', 0);
142 $dateend = dol_time_plus_duree($dateend, -1, 'd', 0);
143
144 $datestart = dol_time_plus_duree($dateend, -1, 'm', 0);
145 } elseif (empty($object->day_close) && empty($object->month_close)) { // Full year
146 $dateend = dol_mktime((int) $object->hour_close, (int) $object->min_close, (int) $object->sec_close, 12, 31, $object->year_close, 'gmt');
147 $datestart = dol_time_plus_duree($dateend, -1, 'y', 0);
148 } else {
149 $dateend = dol_mktime((int) $object->hour_close, (int) $object->min_close, (int) $object->sec_close, $object->month_close, $object->day_close, $object->year_close, 'gmt');
150 $datestart = dol_time_plus_duree($dateend, -1, 'd', 0);
151 }
152 $datestart += 1; // Add 1 second
153} else {
154 if ($syear && !$smonth) {
155 $datestart = dol_get_first_day($syear, 1, 'tzuserrel');
156 $dateend = dol_get_last_day($syear, 12, 'tzuserrel');
157 } elseif ($syear && $smonth && !$sday) {
158 $datestart = dol_get_first_day($syear, $smonth, 'tzuserrel');
159 $dateend = dol_get_last_day($syear, $smonth, 'tzuserrel');
160 } elseif ($syear && $smonth && $sday) {
161 $datestart = dol_mktime($shour, $smin, $ssec, $smonth, $sday, $syear, 'tzuserrel');
162 $dateend = dol_mktime(23, 59, 59, $smonth, $sday, $syear, 'tzuserrel');
163 } else {
164 setEventMessages($langs->trans('YearNotDefined'), null, 'errors');
165 }
166}
167$sqlfilteronopdate .= " AND dateo < '".$db->idate((int) $datestart)."'";
168//var_dump(dol_print_date($datestart, 'dayhour', 'gmt'), dol_print_date($dateend, 'dayhour', 'gmt'));
169
170
171// Define dates and terminal
172$posmodule = '';
173$terminalid = '';
174$terminaltouse = '';
175if ($action == "create" || $action == "start" || $action == 'valid' || $action == 'close') {
176 if ($action == 'valid' || $action == 'close') {
177 $posmodule = $object->posmodule;
178 $terminalid = $object->posnumber;
179 $terminaltouse = $terminalid;
180
181 $syear = $object->year_close;
182 $smonth = $object->month_close;
183 $sday = $object->day_close;
184 } elseif (GETPOST('posnumber', 'alpha') != '' && GETPOST('posnumber', 'alpha') != '-1') {
185 $posmodule = GETPOST('posmodule', 'alpha');
186 $terminalid = GETPOST('posnumber', 'alpha');
187 $terminaltouse = $terminalid;
188
189 if ($terminaltouse == '1' && $posmodule == 'cashdesk') { // for compatibility with an old module
190 $terminaltouse = '';
191 }
192 }
193}
194
195
196/*
197 * Actions
198 */
199
200$error = 0;
201
202if (empty($backtopage)) {
203 $backtopage = DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_card.php?id='.(!empty($id) && $id > 0 ? $id : '__ID__');
204}
205$backurlforlist = DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_list.php';
206$triggermodname = 'CACHCONTROL_MODIFY'; // Name of trigger action code to execute when we modify record
207
208if (!getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CASH') && !getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CASH1')) {
209 setEventMessages($langs->trans("CashDesk")." - ".$langs->trans("NotConfigured"), null, 'errors');
210}
211
212
213if (GETPOST('cancel', 'alpha')) {
214 if ($action == 'valid') { // Test on permission not required here
215 $action = 'view';
216 } else {
217 $action = 'create';
218 }
219}
220
221if ($action == "reopen" && $permissiontoreopen) {
222 $result = $object->setStatut($object::STATUS_DRAFT, null, '', 'CASHFENCE_MODIFY');
223 if ($result < 0) {
224 setEventMessages($object->error, $object->errors, 'errors');
225 }
226
227 $action = 'view';
228}
229
230if ($action == "start" && $permissiontoadd) {
231 if (!GETPOST('posmodule', 'alpha') || GETPOST('posmodule', 'alpha') == '-1') {
232 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Module")), null, 'errors');
233 $action = 'create';
234 $error++;
235 }
236 if (GETPOST('posnumber', 'alpha') == '') {
237 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CashDesk")), null, 'errors');
238 $action = 'create';
239 $error++;
240 }
241 if (!GETPOST('closeyear', 'alpha') || GETPOST('closeyear', 'alpha') == '-1') {
242 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Year")), null, 'errors');
243 $action = 'create';
244 $error++;
245 }
246} elseif ($action == "add" && $permissiontoadd) {
247 if (GETPOST('opening', 'alpha') == '') {
248 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("InitialBankBalance")), null, 'errors');
249 $action = 'start';
250 $error++;
251 }
252 foreach ($arrayofpaymentmode as $key => $val) {
253 $object->$key = (float) price2num(GETPOST($key.'_amount', 'alpha'));
254 }
255
256 if (!$error) {
257 if (GETPOSTINT('closeday')) {
258 $dateclosegmt = dol_mktime(GETPOSTISSET('closehour') ? GETPOSTINT('closehour') : 23, GETPOSTISSET('closemin') ? GETPOSTINT('closemin') : 59, GETPOSTISSET('closesec') ? GETPOSTINT('closesec') : 59, GETPOSTINT('closemonth') ? GETPOSTINT('closemonth') : 12, GETPOSTINT('closeday'), GETPOSTINT('closeyear'), 'tzuserrel');
259 } else {
260 $dateclosegmt = dol_mktime(GETPOSTISSET('closehour') ? GETPOSTINT('closehour') : 23, GETPOSTISSET('closemin') ? GETPOSTINT('closemin') : 59, GETPOSTISSET('closesec') ? GETPOSTINT('closesec') : 59, GETPOSTINT('closemonth') ? GETPOSTINT('closemonth') : 12, 15, GETPOSTINT('closeyear'), 'tzuserrel');
261 }
262 dol_syslog('The closing date will be '.dol_print_date($dateclosegmt, 'standard', 'gmt').' UTC');
263
264 $tmparray = dol_getdate($dateclosegmt, false, 'gmt');
265
266 $object->day_close = GETPOSTINT('closeday') ? $tmparray['mday'] : null;
267 $object->month_close = GETPOSTINT('closemonth') ? $tmparray['mon'] : null;
268 $object->year_close = $tmparray['year'];
269
270 $object->hour_close = $tmparray['hours'];
271 $object->min_close = $tmparray['minutes'];
272 $object->sec_close = $tmparray['seconds'];
273
274 $object->opening = (float) price2num(GETPOST('opening', 'alpha'));
275 $object->posmodule = GETPOST('posmodule', 'alpha');
276 $object->posnumber = GETPOST('posnumber', 'alpha');
277
278 $db->begin();
279
280 $id = $object->create($user);
281
282 if ($id > 0) {
283 $db->commit();
284 $action = "view";
285 } else {
286 $db->rollback();
287 $action = "view";
288 }
289 }
290 if ($contextpage == 'takepos') {
291 print "
292 <script>
293 parent.location.href='../../takepos/index.php?place='+parent.place;
294 </script>";
295 exit;
296 }
297}
298
299if ($action == "valid" && $permissiontoadd) { // validate = close
300 $object->fetch($id);
301
302 $db->begin();
303
304 // Save the calculated amount
305 // It will also be saved automatically into llx_blockedlog by the trigger in valid().
306 $object->cash = (float) price2num(GETPOST('cash_calculated', 'alpha'));
307 $object->card = (float) price2num(GETPOST('card_calculated', 'alpha'));
308 $object->cheque = (float) price2num(GETPOST('cheque_calculated', 'alpha'));
309
310 // Save the real amount in llx_pos_cash_fence.
311 $object->cash_declared = (float) price2num(GETPOST('cash_amount', 'alpha'));
312 $object->card_declared = (float) price2num(GETPOST('card_amount', 'alpha'));
313 $object->cheque_declared = (float) price2num(GETPOST('cheque_amount', 'alpha'));
314
315 // Add also perpetual amount into cash_lifetime, card_lifetime, cheque_lifetime
316 $cash_lifetime = $card_lifetime = $cheque_lifetime = 0;
317
318 //$dates = $datestart;
319 $datee = $dateend;
320 $datefilter = 'p.datep';
321 $modulesourcefilter = 'f.module_source';
322 $amountfield = 'pf.amount';
323 $possource = 'f.pos_source';
324 $fieldentity = 'p.entity';
325 $joinleft = 'LEFT ';
326 if (isALNERunningVersion() && $mysoc->country_code == 'FR') {
327 $datefilter = 'bl.date_creation'; // By using this as a filter, it is like the LEFT JOIN is an INNER JOIN
328 $modulesourcefilter = 'bl.module_source';
329 $amountfield = 'bl.amounts';
330 $possource = 'bl.pos_source';
331 $fieldentity = 'bl.entity';
332 $joinleft = '';
333 }
334
335 $lifetimeamount = array();
336 $lifetimenb = array();
337
338 // Calculate $theoricalamountforterminal at end of period
339 // Sum of payment + Initial amount in bank
340 foreach ($arrayofpaymentmode as $key => $val) {
341 // NOTE: Must be same request than into report.php, except it does an aggregate and do the request 3 times, once per payment type.
342
343 /*$sql = "SELECT p.rowid, p.ref as pref, p.datep as datep, cp.code,";
344 $sql .= " f.rowid as facid, f.ref, f.datef as datef, pf.amount as amount,";
345 $sql .= " b.fk_account as bankid,";
346 $sql .= " bl.signature"; */
347 $sql = "SELECT SUM(".$db->sanitize($amountfield).") as total, COUNT(*) as nb";
348 $sql .= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."facture as f,";
349 $sql .= " ".MAIN_DB_PREFIX."paiement as p";
350 $sql .= " ".$db->sanitize($joinleft)." JOIN ".MAIN_DB_PREFIX."blockedlog as bl ON bl.action = 'PAYMENT_CUSTOMER_CREATE'";
351 $sql .= " AND bl.element = 'payment' AND bl.fk_object = p.rowid AND bl.entity = ".((int) $conf->entity).",";
352 $sql .= " ".MAIN_DB_PREFIX."c_paiement as cp";
353 $sql .= " WHERE pf.fk_facture = f.rowid AND p.rowid = pf.fk_paiement AND cp.id = p.fk_paiement";
354 $sql .= " AND ".$db->sanitize($modulesourcefilter)." = '".$db->escape($posmodule)."'";
355 $sql .= " AND ".$db->sanitize($possource)." = '".$db->escape($terminalid)."'";
356 $sql .= " AND ".$db->sanitize($fieldentity)." = ".((int) $conf->entity); // Never share entities for features related to accountancy
357 $sql .= " AND ".$db->sanitize($datefilter)." <= '".$db->idate((int) $datee)."'";
358 if ($key == 'cash') {
359 $sql .= " AND cp.code = 'LIQ'";
360 } elseif ($key == 'cheque') {
361 $sql .= " AND cp.code = 'CHQ'";
362 } elseif ($key == 'card') {
363 $sql .= " AND cp.code = 'CB'";
364 } else {
365 dol_print_error(null, 'Value for key = '.$key.' not supported');
366 exit;
367 }
368 //print $sql."<br>\n";
369
370 $resql = $db->query($sql);
371 if ($resql) {
372 $lifetimeamount[$terminalid][$key] = 0;
373 $lifetimenb[$terminalid][$key] = 0;
374
375 $obj = $db->fetch_object($resql);
376 if ($obj) {
377 $lifetimeamount[$terminalid][$key] = price2num($lifetimeamount[$terminalid][$key] + $obj->total);
378 $lifetimenb[$terminalid][$key] = $obj->nb;
379 }
380 } else {
382 }
383 }
384
385 $cash_lifetime = $lifetimeamount[$terminalid]['cash'];
386 $card_lifetime = $lifetimeamount[$terminalid]['card'];
387 $cheque_lifetime = $lifetimeamount[$terminalid]['cheque'];
388
389 $object->cash_lifetime = $cash_lifetime;
390 $object->card_lifetime = $card_lifetime;
391 $object->cheque_lifetime = $cheque_lifetime;
392
393
394 // Get the date of first record for the lifetime calculation
395 $sql = "SELECT action, module_source, object_format, date_creation";
396 $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog";
397 $sql .= " WHERE entity = ".((int) $conf->entity);
398 $sql .= " AND action IN ('PAYMENT_CUSTOMER_CREATE')"; // Only this event
399 $sql .= " AND module_source = '".$db->escape($posmodule)."'";
400 //$sql .= " AND pos_source = '".$db->escape($terminalid)."'";
401 $sql .= $db->order("date_creation", "ASC");
402 $sql .= $db->plimit(1);
403
404 $firstrecorddate = 0;
405 $resql = $db->query($sql);
406 if ($resql) {
407 $obj = $db->fetch_object($resql);
408 if ($obj) {
409 $firstrecorddate = $db->jdate($obj->date_creation);
410 }
411 }
412 if ($firstrecorddate) {
413 $object->lifetime_start = $firstrecorddate;
414 }
415
416 $result = $object->update($user);
417
418 $result2 = $object->close($user); // This also save data into the Unalterable Log table by the trigger CASHCONTROL_CLOSE.
419
420
421 // TODO
422 // Add an entry into bank to fix difference between amount and declared and if user ask it with a checkbox ?
423
424
425 if ($result <= 0 || $result2 <= 0) {
426 setEventMessages($object->error, $object->errors, 'errors');
427 $db->rollback();
428 } else {
429 setEventMessages($langs->trans("CashFenceDone"), null);
430 $db->commit();
431 }
432
433 if ($contextpage == 'takepos') {
434 print "
435 <script>
436 location.href='cashcontrol_card.php?id=".$id."&contextpage=takepos';
437 </script>";
438 exit;
439 }
440 $action = "view";
441}
442
443// Action to delete
444if ($action == 'confirm_delete' && !empty($permissiontodelete)) {
445 $object->fetch($id);
446
447 if (!($object->id > 0)) {
448 dol_print_error(null, 'Error, object must be fetched before being deleted');
449 exit;
450 }
451
452 $result = $object->delete($user);
453 if ($result > 0) {
454 // Delete OK
455 setEventMessages("RecordDeleted", null, 'mesgs');
456 header("Location: ".$backurlforlist);
457 exit;
458 } else {
459 if (!empty($object->errors)) {
460 setEventMessages(null, $object->errors, 'errors');
461 } else {
462 setEventMessages($object->error, null, 'errors');
463 }
464 }
465}
466
467if ($action == 'update_extras' && $permissiontoeditextra) {
468 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
469
470 $attribute_name = GETPOST('attribute', 'aZ09');
471
472 // Fill array 'array_options' with data from add form
473 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
474 if ($ret < 0) {
475 $error++;
476 }
477
478 if (!$error) {
479 // Actions on extra fields
480 $result = $object->updateExtraField($attribute_name, 'CASHCONTROL_MODIFY');
481 if ($result < 0) {
482 setEventMessages($object->error, $object->errors, 'errors');
483 $error++;
484 }
485 }
486
487 if ($error) {
488 $action = 'edit_extras';
489 }
490}
491
492
493/*
494 * View
495 */
496
497$form = new Form($db);
498
499$initialbalanceforterminal = array();
500$theoricalamountforterminal = array();
501$theoricalnbofinvoiceforterminal = array();
502
503
504llxHeader('', $langs->trans("CashControl"));
505
506
507// Calculate initial amount estimation and final amount
508if ($action == "create" || $action == "start" || $action == 'close') {
509 if ($action == 'close') {
510 $posmodule = $object->posmodule;
511 $terminalid = $object->posnumber;
512 $terminaltouse = $terminalid;
513
514 $syear = $object->year_close;
515 $smonth = $object->month_close;
516 $sday = $object->day_close;
517 } elseif (GETPOST('posnumber', 'alpha') != '' && GETPOST('posnumber', 'alpha') != '-1') {
518 $posmodule = GETPOST('posmodule', 'alpha');
519 $terminalid = GETPOST('posnumber', 'alpha');
520 $terminaltouse = $terminalid;
521
522 if ($terminaltouse == '1' && $posmodule == 'cashdesk') {
523 $terminaltouse = '';
524 }
525
526 if ($posmodule == 'cashdesk' && $terminaltouse != '' && $terminaltouse != '1') {
527 $terminaltouse = '';
528 setEventMessages($langs->trans("OnlyTerminal1IsAvailableForCashDeskModule"), null, 'errors');
529 $error++;
530 }
531 }
532
533 if (isset($terminalid) && $terminalid != '' && isset($posmodule)) {
534 // Calculate $initialbalanceforterminal for terminal 0
535 foreach ($arrayofpaymentmode as $key => $val) {
536 if ($key != 'cash') {
537 $initialbalanceforterminal[$terminalid][$key] = 0;
538 continue;
539 }
540
541 // Get the bank account dedicated to this point of sale module/terminal
542 $vartouse = 'CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse;
543 $bankid = getDolGlobalInt($vartouse);
544
545 // Get the amount in bank before the period date to pre-fill the suggested "initial amount".
546 // The user is still free to prefill with the correct value. This is just to save time to user.
547 if ($bankid > 0) {
548 $sql = "SELECT SUM(amount) as total FROM ".MAIN_DB_PREFIX."bank";
549 $sql .= " WHERE fk_account = ".((int) $bankid);
550 $sql .= $sqlfilteronopdate;
551
552 $resql = $db->query($sql);
553 if ($resql) {
554 $obj = $db->fetch_object($resql);
555 if ($obj) {
556 $initialbalanceforterminal[$terminalid][$key] = $obj->total;
557 }
558 } else {
560 }
561 } else {
562 setEventMessages($langs->trans("SetupOfTerminalNotComplete", $terminaltouse), null, 'errors');
563 $error++;
564 }
565 }
566
567 $dates = $datestart;
568 $datee = $dateend;
569 $datefilter = 'p.datep';
570 $modulesourcefilter = 'f.module_source';
571 $amountfield = 'pf.amount';
572 $joinleft = 'LEFT ';
573 if (isALNERunningVersion() && $mysoc->country_code == 'FR') {
574 $datefilter = 'bl.date_creation'; // By using this as a filter, it is like the LEFT JOIN is an INNER JOIN
575 $modulesourcefilter = 'bl.module_source';
576 $amountfield = 'bl.amounts';
577 $joinleft = '';
578 }
579
580 // Calculate $theoricalamountforterminal at end of period
581 // Sum of payment + Initial amount in bank
582 foreach ($arrayofpaymentmode as $key => $val) {
583 // NOTE: Must be same request than into report.php, except it does an aggregate and do the request 3 times, once per payment type.
584
585 // TODO
586 /*$sql = "SELECT p.rowid, p.datep as datep, cp.code,";
587 $sql .= " f.rowid as facid, f.ref, f.datef as datef, pf.amount as amount,";
588 $sql .= " b.fk_account as bankid,";
589 $sql .= " bl.signature"; */
590 $sql = "SELECT SUM(".$db->sanitize($amountfield).") as total, COUNT(*) as nb";
591 $sql .= " FROM ".MAIN_DB_PREFIX."paiement_facture as pf, ".MAIN_DB_PREFIX."facture as f,";
592 $sql .= " ".MAIN_DB_PREFIX."paiement as p";
593 //$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."blockedlog as bl ON bl.ref_object = p.ref AND bl.entity = ".((int) $conf->entity).",";
594 $sql .= " ".$db->sanitize($joinleft)." JOIN ".MAIN_DB_PREFIX."blockedlog as bl ON bl.action = 'PAYMENT_CUSTOMER_CREATE'";
595 $sql .= " AND bl.element = 'payment' AND bl.fk_object = p.rowid AND bl.entity = ".((int) $conf->entity).",";
596 //$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank as b ON p.fk_bank = b.rowid,";
597 $sql .= " ".MAIN_DB_PREFIX."c_paiement as cp";
598 $sql .= " WHERE pf.fk_facture = f.rowid AND p.rowid = pf.fk_paiement AND cp.id = p.fk_paiement";
599 $sql .= " AND ".$db->sanitize($modulesourcefilter)." = '".$db->escape($posmodule)."'";
600 $sql .= " AND f.pos_source = '".$db->escape($terminalid)."'";
601 $sql .= " AND p.entity = ".((int) $conf->entity); // Never share entities for features related to accountancy
602 $sql .= " AND ".$db->sanitize($datefilter)." BETWEEN '".$db->idate((int) $dates)."' AND '".$db->idate((int) $datee)."'";
603 if ($key == 'cash') {
604 $sql .= " AND cp.code = 'LIQ'";
605 } elseif ($key == 'cheque') {
606 $sql .= " AND cp.code = 'CHQ'";
607 } elseif ($key == 'card') {
608 $sql .= " AND cp.code = 'CB'";
609 } else {
610 dol_print_error(null, 'Value for key = '.$key.' not supported');
611 exit;
612 }
613
614 $resql = $db->query($sql);
615 if ($resql) {
616 $obj = $db->fetch_object($resql);
617 if ($obj) {
618 // $theoricalamountforterminal and $theoricalnbofinvoiceforterminal will be used to get the amount for period (cash_calculated, cheque_calculated and card_calculated)
619 $theoricalamountforterminal[$terminalid][$key] = $obj->total;
620 $theoricalnbofinvoiceforterminal[$terminalid][$key] = $obj->nb;
621 }
622 } else {
624 }
625 }
626 }
627}
628
629if ($action == "create" || $action == "start") {
630 print load_fiche_titre($langs->trans("CashControl")." - ".$langs->trans("New"), '', 'cash-register');
631
632 if ($action == 'start') {
633 if (empty(GETPOSTINT('closeday'))) {
634 $endperiod = dol_get_last_day(GETPOSTINT('closeyear'), GETPOSTINT('closemonth') ? GETPOSTINT('closemonth') : 12, 'gmt');
635 if ($endperiod >= dol_now()) {
636 setEventMessages($langs->trans("CashControlEndDateMustBeBeforeNow"), null, 'errors');
637 $action = 'create';
638 }
639 } else {
640 $endperiod = dol_get_first_hour(GETPOSTDATE('close', 'getpostend'));
641 if ($endperiod >= dol_now() && $mysoc->country_code == 'FR') { // For other countries we may need to make 2 cash control in the same day (one at opening and one at closing)
642 setEventMessages($langs->trans("CashControlEndDayMustNotBeInPast"), null, 'errors');
643 $action = 'create';
644 }
645 }
646 }
647
648 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
649 print '<input type="hidden" name="token" value="'.newToken().'">';
650 if ($contextpage == 'takepos') {
651 print '<input type="hidden" name="contextpage" value="takepos">';
652 }
653 if ($action == 'start' && GETPOSTINT('posnumber') != '' && GETPOSTINT('posnumber') != '' && GETPOSTINT('posnumber') != '-1') {
654 print '<input type="hidden" name="action" value="add">';
655 } elseif ($action == 'close') {
656 print '<input type="hidden" name="action" value="valid">';
657 print '<input type="hidden" name="id" value="'.$id.'">';
658 } else {
659 print '<input type="hidden" name="action" value="start">';
660 }
661
662 print '<!-- Table to start cash control -->'."\n";
663 print '<div class="div-table-responsive-no-min">'."\n";
664 print '<table class="noborder centpercent">'."\n";
665 print '<tr class="liste_titre">';
666 print '<td>'.$langs->trans("Module").'</td>';
667 print '<td>'.$langs->trans("Terminal").'</td>';
668 print '<td>'.$langs->trans("Year").'</td>';
669 print '<td>'.$langs->trans("Month").'</td>';
670 print '<td>'.$langs->trans("Day").'</td>';
671 print '<td></td>';
672 print "</tr>\n";
673
674 $disabled = 0;
675 $prefix = 'close';
676
677 print '<tr class="oddeven nohover">';
678 print '<td>'.$form->selectarray('posmodule', $arrayofposavailable, GETPOST('posmodule', 'alpha'), (count($arrayofposavailable) > 1 ? 1 : 0)).'</td>';
679 print '<td>';
680
681 $arrayofpos = array();
682 $numterminals = max(1, getDolGlobalString('TAKEPOS_NUM_TERMINALS'));
683 for ($i = 1; $i <= $numterminals; $i++) {
684 $nameofterminal = getDolGlobalString("TAKEPOS_TERMINAL_NAME_".$i);
685 $arrayofpos[$i] = array('id' => $i, 'label' => (($nameofterminal != "TAKEPOS_TERMINAL_NAME_".$i) ? '#'.$i.' '.$nameofterminal : $i), 'data-html' => (($nameofterminal != "TAKEPOS_TERMINAL_NAME_".$i) ? '#'.$i.' - '.$nameofterminal : $i));
686 }
687 $selectedposnumber = 0;
688 $showempty = 1;
689 if (getDolGlobalString('TAKEPOS_NUM_TERMINALS') == '1') {
690 $selectedposnumber = 1;
691 $showempty = 0;
692 }
693 print $form->selectarray('posnumber', $arrayofpos, GETPOSTISSET('posnumber') ? GETPOSTINT('posnumber') : $selectedposnumber, $showempty);
694 //print '<input name="posnumber" type="text" class="maxwidth50" value="'.(GETPOSTISSET('posnumber')?GETPOST('posnumber', 'alpha'):'0').'">';
695 print '</td>';
696
697 // Year
698 print '<td>';
699 $retstring = '<select'.($disabled ? ' disabled' : '').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'year" name="'.$prefix.'year">';
700 for ($year = $syear - 10; $year < $syear + 10; $year++) {
701 $retstring .= '<option value="'.$year.'"'.($year == $syear ? ' selected' : '').'>'.$year.'</option>';
702 }
703 $retstring .= "</select>\n";
704 print $retstring;
705 print '</td>';
706
707 // Month
708 print '<td>';
709 $retstring = '<select'.($disabled ? ' disabled' : '').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'month" name="'.$prefix.'month">';
710 $retstring .= '<option value="0"></option>';
711 for ($month = 1; $month <= 12; $month++) {
712 $retstring .= '<option value="'.$month.'"'.($month == $smonth ? ' selected' : '').'>';
713 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
714 $retstring .= "</option>";
715 }
716 $retstring .= "</select>";
717 print $retstring;
718 print ' '.$form->textwithpicto('', $langs->trans("KeepEmptyForAYearlyControl"));
719 print '</td>';
720
721 // Day
722 print '<td>';
723 $retstring = '<select'.($disabled ? ' disabled' : '').' class="flat valignmiddle maxwidth50imp" id="'.$prefix.'day" name="'.$prefix.'day">';
724 $retstring .= '<option value="0" selected>&nbsp;</option>';
725 for ($day = 1; $day <= 31; $day++) {
726 $retstring .= '<option value="'.$day.'"'.($day == $sday ? ' selected' : '').'>'.$day.'</option>';
727 }
728 $retstring .= "</select>";
729 print $retstring;
730 print ' '.$form->textwithpicto('', $langs->trans("KeepEmptyForAMonthlyControl"));
731 print '</td>';
732
733 // Button Start
734 print '<td>';
735 if ($action == 'start' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '-1') {
736 print '';
737 } else {
738 print '<input type="submit" name="add" class="button" value="'.$langs->trans("Start").'">';
739 }
740 print '</td>';
741 print '</table>';
742 print '</div>';
743
744
745 // Table to see/enter balance
746 if ($action == 'start' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '-1') {
747 $posmodule = GETPOST('posmodule', 'alpha');
748 $terminalid = GETPOST('posnumber', 'alpha');
749
750 print '<br>';
751
752 print '<div class="div-table-responsive-no-min">';
753 print '<table class="noborder centpercent">';
754
755 print '<tr class="liste_titre">';
756 print '<td></td>';
757 print '<td class="center">'.$langs->trans("InitialBankBalance");
758 print '<br>';
759 print '<span class="small opacitymedium">'.$langs->trans("at").' '.dol_print_date($datestart, 'standard', 'gmt').' UTC</span>';
760 //print '<br>'.$langs->trans("TheoricalAmount").'<br>'.$langs->trans("RealAmount");
761 print '</td>';
762
763 /*
764 print '<td align="center" class="hide0" colspan="'.count($arrayofpaymentmode).'">';
765 print $langs->trans("AmountAtEndOfPeriod");
766 print '</td>';
767 */
768 print '<td></td>';
769 print '</tr>';
770
771 print '<tr class="liste_titre">';
772 print '<td></td>';
773 print '<td class="center">'.$langs->trans("Cash");
774 //print '<br>'.$langs->trans("TheoricalAmount").'<br>'.$langs->trans("RealAmount");
775 print '</td>';
776 /*
777 $i = 0;
778 foreach ($arrayofpaymentmode as $key => $val)
779 {
780 print '<td align="center"'.($i == 0 ? ' class="hide0"' : '').'>'.$langs->trans($val);
781 //print '<br>'.$langs->trans("TheoricalAmount").'<br>'.$langs->trans("RealAmount");
782 print '</td>';
783 $i++;
784 }*/
785 print '<td></td>';
786 print '</tr>';
787
788 /*print '<tr>';
789 // Initial amount
790 print '<td>'.$langs->trans("NbOfInvoices").'</td>';
791 print '<td class="center">';
792 print '</td>';
793 // Amount per payment type
794 $i = 0;
795 foreach ($arrayofpaymentmode as $key => $val)
796 {
797 print '<td align="center"'.($i == 0 ? ' class="hide0"' : '').'>';
798 print $theoricalnbofinvoiceforterminal[$terminalid][$key];
799 print '</td>';
800 $i++;
801 }
802 // Save
803 print '<td align="center"></td>';
804 print '</tr>';
805 */
806
807 print '<tr>';
808 // Initial amount
809 print '<td>';
810 print $form->textwithpicto($langs->trans("TheoricalAmount"), $langs->trans("TheoricalAmountAtOpening"));
811 print '</td>';
812 print '<td class="center">';
813 print price($initialbalanceforterminal[$terminalid]['cash']).'<br>';
814 print '</td>';
815 // Amount per payment type
816 /*$i = 0;
817 foreach ($arrayofpaymentmode as $key => $val)
818 {
819 print '<td align="center"'.($i == 0 ? ' class="hide0"' : '').'>';
820 print price($theoricalamountforterminal[$terminalid][$key]).'<br>';
821 print '</td>';
822 $i++;
823 }*/
824 // Save
825 print '<td></td>';
826 print '</tr>';
827
828 print '<tr>';
829 print '<td>'.$langs->trans("RealAmount").'</td>';
830 // Initial amount
831 print '<td class="center">';
832 print '<input ';
833 if ($action == 'close') {
834 print 'disabled '; // To close cash user can't set opening cash
835 }
836 print 'name="opening" type="text" class="maxwidth100 center" value="';
837 if ($action == 'close') {
838 $object->fetch($id);
839 print $object->opening;
840 } else {
841 print(GETPOSTISSET('opening') ? price2num(GETPOST('opening', 'alpha')) : price($initialbalanceforterminal[$terminalid]['cash']));
842 }
843 print '">';
844 print '</td>';
845 // Amount per payment type
846 /*$i = 0;
847 foreach ($arrayofpaymentmode as $key => $val)
848 {
849 print '<td align="center"'.($i == 0 ? ' class="hide0"' : '').'>';
850 print '<input ';
851 if ($action == 'start') print 'disabled '; // To start cash user only can set opening cash
852 print 'name="'.$key.'_amount" type="text"'.($key == 'cash' ? ' autofocus' : '').' class="maxwidth100 center" value="'.GETPOST($key.'_amount', 'alpha').'">';
853 print '</td>';
854 $i++;
855 }*/
856 // Save
857 print '<td class="center">';
858 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
859 if ($action == 'start') {
860 print '<input type="submit" name="add" class="button button-save" value="'.$langs->trans("Start").'">';
861 } elseif ($action == 'close') {
862 print '<input type="submit" name="valid" class="button" value="'.$langs->trans("Validate").'">';
863 }
864 print '</td>';
865 print '</tr>';
866
867 print '</table>';
868 print '</div>';
869 }
870
871 print '</form>';
872}
873
874// View
875if (empty($action) || $action == "view" || $action == "close") {
876 $result = $object->fetch($id);
877
878 if ($result <= 0) {
879 print $langs->trans("ErrorRecordNotFound");
880 } else {
881 $head = array();
882 $head[0][0] = DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_card.php?id='.$object->id;
883 $head[0][1] = $langs->trans("CashControl");
884 $head[0][2] = 'cashcontrol';
885
886 print dol_get_fiche_head($head, 'cashcontrol', $langs->trans("CashControl"), -1, 'account');
887
888 $linkback = '<a href="'.DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
889
890 $morehtmlref = '<div class="refidno">';
891 $morehtmlref .= '</div>';
892
893
894 dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'rowid', $morehtmlref);
895
896 print '<div class="fichecenter">';
897 print '<div class="fichehalfleft">';
898 print '<div class="underbanner clearboth"></div>';
899 print '<table class="border tableforfield centpercent">';
900
901 print '<tr><td class="titlefield nowrap">';
902 print $langs->trans("Ref");
903 print '</td><td>';
904 print $id;
905 print '</td></tr>';
906
907 print '<tr><td valign="middle">'.$langs->trans("Module").'</td><td>';
908 print $object->posmodule;
909 print "</td></tr>";
910
911 print '<tr><td valign="middle">'.$langs->trans("Terminal").'</td><td>';
912 print $object->posnumber;
913 print "</td></tr>";
914
915 print '<tr><td class="titlefield nowrap">';
916 print $langs->trans("DateCreationShort");
917 print '</td><td colspan="3">';
918 print dol_print_date($object->date_creation, 'dayhour');
919 print '</td></tr>';
920
921 print '<tr><td class="nowrap">';
922 print $langs->trans("Period");
923 print '</td><td>';
924 $period = $object->year_close;
925 $period .= ($object->month_close ? "-".sprintf("%02d", $object->month_close) : "");
926 $period .= ($object->day_close ? "-".sprintf("%02d", $object->day_close) : "");
927 print $period;
928
929 //print ' &nbsp; &nbsp; ';
930 $htmltooltip = '';
931 $htmltooltip .= dol_print_date($datestart, 'standard', 'tzuserrel').' - ';
932 $htmltooltip .= dol_print_date($dateend, 'standard', 'tzuserrel');
933 $htmltooltip .= '<br><span class="small opacitymedium">UTC : ';
934 $htmltooltip .= dol_print_date($datestart, 'standard', 'gmt').' - ';
935 $htmltooltip .= dol_print_date($dateend, 'standard', 'gmt');
936 $htmltooltip .= '</span>';
937 print $form->textwithpicto('', $htmltooltip);
938 print '</td></tr>';
939
940 // Other attributes
941 $parameters = array('colspan' => ' colspan="2"', 'cols' => '2');
942 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
943 print $hookmanager->resPrint;
944 if (empty($reshook)) {
945 print $object->showOptionals($extrafields, 'create', $parameters);
946 }
947
948 if ($object->lifetime_start) {
949 print '<tr><td class="titlefield nowrap">';
950 print $langs->trans("LifetimeAmount", $langs->transnoentities("AllPaymentModes"));
951 print '</td><td colspan="3">';
952 print '<span class="amount">'.price($object->card_lifetime + $object->cheque_lifetime + $object->cash_lifetime, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
953 print ' &nbsp; <span class="opacitymedium">'.$langs->trans("since").' '.dol_print_date($object->lifetime_start, 'dayhour').' ('.$langs->trans("AllTerminals").')</span>';
954 print '</td></tr>';
955 }
956
957 print '</table>';
958 print '</div>';
959
960 print '<div class="fichehalfright">';
961 print '<div class="underbanner clearboth"></div>';
962
963 print '<table class="noborder paymenttable centpercent">';
964
965 if ($object->status == $object::STATUS_CLOSED) {
966 print '<tr class="liste_titre"><td class="liste_titre">'.$langs->trans("Summary").'</td>';
967 print '<td class="liste_titre right">'.$langs->trans("InitialBankBalance").'</td>';
968 print '<td class="liste_titre right">'.$langs->trans("Sales").'</td>';
969 print '<td class="liste_titre right">'.$langs->trans("EndBankBalance").'</td>';
970 print "</tr>";
971
972 foreach ($arrayofpaymentmode as $key => $val) {
973 $newkey = $key.'_declared';
974 if (!property_exists($object, $key)) {
975 continue;
976 }
977
978 $realamountforpaymentmode = $object->$key;
979 $declaredamountforpaymentmode = $object->$newkey;
980
981 print '<tr>';
982 print '<td class="">'.$langs->trans($val).'</td>';
983 print '<td class="right">';
984 if ($key == 'cash') {
985 print '<span class="amount">'.price($object->opening, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
986 }
987 print '</td>';
988 print '<td class="right">';
989 if ($realamountforpaymentmode) {
990 print '<span class="amount">'.($realamountforpaymentmode >= 0 ? '+' : '').price($realamountforpaymentmode, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
991 }
992 print '</td>';
993 print '<td class="right">';
994 $calcamount = (($key == 'cash' ? $object->opening : 0) + $realamountforpaymentmode);
995 print '<span class="amount">'.price($calcamount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
996 //print '</span>';
997 //print '<span class="amount';
998 if ($calcamount != $declaredamountforpaymentmode) {
999 //print ' error';
1000 print img_picto($langs->trans("Declared").': '.$declaredamountforpaymentmode, 'warning');
1001 }
1002 //print '">';
1003
1004
1005 print '</td>';
1006 print '</tr>';
1007 }
1008 }
1009
1010 print "</table>\n";
1011
1012 print '</div></div>';
1013 print '<div class="clearboth"></div>';
1014
1015 print dol_get_fiche_end();
1016
1017 if ($action != 'close') {
1018 print '<div class="tabsAction">';
1019
1020 // Print ticket
1021 print '<div class="inline-block divButAction"><a target="_blank" rel="noopener noreferrer" class="butAction" href="report.php?id='.((int) $id).'">'.$langs->trans('PrintReport').'</a></div>';
1022
1023 // Print ticket (no detail)
1024 print '<div class="inline-block divButAction"><a target="_blank" rel="noopener noreferrer" class="butAction" href="report.php?id='.((int) $id).'&summaryonly=1">'.$langs->trans('PrintReportNoDetail').'</a></div>';
1025
1026 // Close or logical deletion
1027 if ($object->status == CashControl::STATUS_DRAFT) {
1028 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.((int) $id).'&action=close&token='.newToken().'&contextpage='.$contextpage.'">'.$langs->trans('Close').'</a></div>';
1029
1030 print '<div class="inline-block divButAction"><a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.((int) $id).'&action=confirm_delete&token='.newToken().'">'.$langs->trans('Delete').'</a></div>';
1031 } else {
1032 if (!isALNERunningVersion()) {
1033 if ($permissiontoreopen) {
1034 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.((int) $id).'&action=reopen&token='.newToken().'">'.$langs->trans('ReOpen').'</a></div>';
1035 } else {
1036 print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.dolPrintHTMLForAttribute($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('ReOpen').'</a></div>';
1037 }
1038 }
1039 }
1040
1041 print '</div>';
1042
1043 if ($contextpage != 'takepos') {
1044 // Add ifram of report
1045 print '<center><iframe src="'.DOL_URL_ROOT.'/compta/cashcontrol/report.php?id='.$id.'" width="60%" height="800"></iframe></center>';
1046 }
1047 } else {
1048 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" name="formclose">';
1049 print '<input type="hidden" name="token" value="'.newToken().'">';
1050 if ($contextpage == 'takepos') {
1051 print '<input type="hidden" name="contextpage" value="takepos">';
1052 }
1053 if ($action == 'start' && GETPOSTINT('posnumber') != '' && GETPOSTINT('posnumber') != '' && GETPOSTINT('posnumber') != '-1') {
1054 print '<input type="hidden" name="action" value="add">';
1055 } elseif ($action == 'close') {
1056 print '<input type="hidden" name="action" value="valid">';
1057 print '<input type="hidden" name="id" value="'.$id.'">';
1058 } else {
1059 print '<input type="hidden" name="action" value="start">';
1060 }
1061
1062 // Table to see/enter balance
1063 if (($action == 'start' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '' && GETPOST('posnumber') != '-1') || $action == 'close') {
1064 $posmodule = $object->posmodule;
1065 $terminalid = $object->posnumber;
1066
1067 print '<br>';
1068
1069 print '<!-- section to enter declareda mount -->';
1070 print '<div class="div-table-responsive-no-min">';
1071 print '<table class="noborder centpercent">';
1072
1073 print '<tr class="liste_titre">';
1074 print '<td></td>';
1075 print '<td class="center">'.$langs->trans("InitialBankBalance");
1076 print '<br>';
1077 print '<span class="small opacitymedium">'.$langs->trans("at").' '.dol_print_date($datestart, 'standard', 'gmt').' UTC</span>';
1078 print '</td>';
1079
1080 print '<td align="center" class="hide0" colspan="'.count($arrayofpaymentmode).'">';
1081 print $langs->trans("AmountAtEndOfPeriod");
1082 print '<br>';
1083 print '<span class="small opacitymedium">'.$langs->trans("at").' '.dol_print_date($dateend, 'standard', 'gmt').' UTC</span>';
1084 print '</td>';
1085 print '<td></td>';
1086 print '</tr>';
1087
1088 print '<tr class="liste_titre">';
1089 print '<td></td>';
1090 print '<td class="center">'.$langs->trans("Cash");
1091 //print '<br>'.$langs->trans("TheoricalAmount").'<br>'.$langs->trans("RealAmount");
1092 print '</td>';
1093 $i = 0;
1094 foreach ($arrayofpaymentmode as $key => $val) {
1095 print '<td class="center'.($i == 0 ? ' hide0' : '').'">'.$langs->trans($val);
1096 //print '<br>'.$langs->trans("TheoricalAmount").'<br>'.$langs->trans("RealAmount");
1097 print '</td>';
1098 $i++;
1099 }
1100 print '<td></td>';
1101 print '</tr>';
1102
1103 print '<tr>';
1104 // Initial amount
1105 print '<td>'.$langs->trans("NbOfPayments").'</td>';
1106 print '<td class="center">';
1107 print '</td>';
1108 // Amount per payment type
1109 $i = 0;
1110 foreach ($arrayofpaymentmode as $key => $val) {
1111 print '<td class="center'.($i == 0 ? ' hide0' : '').'">';
1112 print $theoricalnbofinvoiceforterminal[$terminalid][$key];
1113 print '</td>';
1114 $i++;
1115 }
1116 // Save
1117 print '<td align="center"></td>';
1118 print '</tr>';
1119
1120 print '<tr>';
1121 // Initial amount
1122 print '<td>'.$langs->trans("TheoricalAmount").'</td>';
1123 print '<td class="center">';
1124 print price($initialbalanceforterminal[$terminalid]['cash']).'<br>';
1125 print '</td>';
1126
1127 // Amount calculated per payment type (field cash_calculated, cheque_calculated, card_calculated)
1128 $i = 0;
1129 foreach ($arrayofpaymentmode as $key => $val) {
1130 print '<td class="smallheight center'.($i == 0 ? ' hide0' : '').'">';
1131 if ($key == 'cash') {
1132 print price($object->opening + $theoricalamountforterminal[$terminalid][$key]).'<br>';
1133 print '<span class="opacitymedium small">('.price($object->opening).' + '.price($theoricalamountforterminal[$terminalid][$key]).')</span>';
1134 } else {
1135 print price($theoricalamountforterminal[$terminalid][$key]).'<br>';
1136 }
1137 print '<input type="hidden" name="'.$key.'_calculated" value="'.$theoricalamountforterminal[$terminalid][$key].'">';
1138 print '</td>';
1139 $i++;
1140 }
1141
1142 // Save
1143 print '<td align="center"></td>';
1144 print '</tr>';
1145
1146
1147 print '<tr>';
1148 print '<td>'.$langs->trans("RealAmount").'</td>';
1149
1150 // Initial amount
1151 print '<td class="center">';
1152 print '<input ';
1153 if ($action == 'close') {
1154 print 'disabled '; // To close cash user can't set opening cash
1155 }
1156 print 'name="opening" type="text" class="maxwidth100 center" value="';
1157 if ($action == 'close') {
1158 $object->fetch($id);
1159 print $object->opening;
1160 } else {
1161 print(GETPOSTISSET('opening') ? price2num(GETPOST('opening', 'alpha')) : price($initialbalanceforterminal[$terminalid]['cash']));
1162 }
1163 print '">';
1164 print '</td>';
1165
1166 // Amount per payment type
1167 $i = 0;
1168 foreach ($arrayofpaymentmode as $key => $val) {
1169 print '<td class="center '.($i == 0 ? ' hide0' : '').'">';
1170 print '<input ';
1171 if ($action == 'start') {
1172 print 'disabled '; // To start cash user only can set opening cash
1173 }
1174 print 'name="'.$key.'_amount" type="text"'.($key == 'cash' ? ' autofocus' : '').' class="maxwidth100 center" value="'.GETPOST($key.'_amount', 'alpha').'">';
1175 print '</td>';
1176 $i++;
1177 }
1178
1179 // Save
1180 print '<td class="center">';
1181 print '<input type="submit" name="cancel" class="button button-cancel" value="'.$langs->trans("Cancel").'">';
1182 if ($action == 'start') {
1183 print '<input type="submit" name="add" class="button button-save" value="'.$langs->trans("Save").'">';
1184 } elseif ($action == 'close') {
1185 print '<input type="submit" name="valid" class="button" value="'.$langs->trans("Close").'">';
1186 }
1187 print '</td>';
1188 print '</tr>';
1189
1190 print '</table>';
1191 print '</div>';
1192 }
1193
1194 print '</form>';
1195 }
1196 }
1197}
1198
1199// End of page
1200llxFooter();
1201$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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
isALNERunningVersion($blockedlogtestalreadydone=0, $blockedlogmodulealreadydone=0)
Return if the application is executed with the LNE requirements on.
Class to manage cash fence.
Class to manage standard extra fields.
Class to manage generation of HTML components Only common components must be here.
global $mysoc
dol_get_first_hour($date, $gm='tzserver')
Return GMT time for first hour of a given GMT date (it removes hours, min and second part)
Definition date.lib.php:664
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:604
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:623
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
GETPOSTDATE($prefix, $hourTime='', $gm='auto', $saverestore='')
Helper function that combines values of a dolibarr DatePicker (such as Form\selectDate) for year,...
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)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
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_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.