dolibarr 19.0.4
invoice.php
Go to the documentation of this file.
1<?php
27// if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Not disabled cause need to load personalized language
28// if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Not disabled cause need to load personalized language
29// if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
30// if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
31
32if (!defined('NOTOKENRENEWAL')) {
33 define('NOTOKENRENEWAL', '1');
34}
35if (!defined('NOREQUIREMENU')) {
36 define('NOREQUIREMENU', '1');
37}
38if (!defined('NOREQUIREHTML')) {
39 define('NOREQUIREHTML', '1');
40}
41if (!defined('NOREQUIREAJAX')) {
42 define('NOREQUIREAJAX', '1');
43}
44
45// Load Dolibarr environment
46if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
47 require '../main.inc.php';
48}
49require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
50require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
51require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
52require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
53require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
54
55$hookmanager->initHooks(array('takeposinvoice'));
56
57$langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks", "banks"));
58
59$action = GETPOST('action', 'aZ09');
60$idproduct = GETPOST('idproduct', 'int');
61$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
62$placeid = 0; // $placeid is ID of invoice
63$mobilepage = GETPOST('mobilepage', 'alpha');
64
65// Terminal is stored into $_SESSION["takeposterminal"];
66
67if (!$user->hasRight('takepos', 'run') && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
68 accessforbidden('No permission to use the TakePOS');
69}
70
71if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
72 // DIRECT LINK TO THIS PAGE FROM MOBILE AND NO TERMINAL SELECTED
73 if ($_SESSION["takeposterminal"] == "") {
74 if (getDolGlobalString('TAKEPOS_NUM_TERMINALS') == "1") {
75 $_SESSION["takeposterminal"] = 1;
76 } else {
77 header("Location: ".DOL_URL_ROOT."/takepos/index.php");
78 exit;
79 }
80 }
81}
82
83// When session has expired (selected terminal has been lost from session), redirect to the terminal selection.
84if (empty($_SESSION["takeposterminal"])) {
85 if (getDolGlobalInt('TAKEPOS_NUM_TERMINALS') == 1) {
86 $_SESSION["takeposterminal"] = 1; // Use terminal 1 if there is only 1 terminal
87 } elseif (!empty($_COOKIE["takeposterminal"])) {
88 $_SESSION["takeposterminal"] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_COOKIE["takeposterminal"]); // Restore takeposterminal from previous session
89 } else {
90 print <<<SCRIPT
91<script language="javascript">
92 $( document ).ready(function() {
93 ModalBox('ModalTerminal');
94 });
95</script>
96SCRIPT;
97 exit;
98 }
99}
100
107function fail($message)
108{
109 header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error', true, 500);
110 die($message);
111}
112
113
114
115$number = GETPOST('number', 'alpha');
116$idline = GETPOST('idline', 'int');
117$selectedline = GETPOST('selectedline', 'int');
118$desc = GETPOST('desc', 'alphanohtml');
119$pay = GETPOST('pay', 'aZ09');
120$amountofpayment = price2num(GETPOST('amount', 'alpha'));
121
122$invoiceid = GETPOST('invoiceid', 'int');
123
124$paycode = $pay;
125if ($pay == 'cash') {
126 $paycode = 'LIQ'; // For backward compatibility
127}
128if ($pay == 'card') {
129 $paycode = 'CB'; // For backward compatibility
130}
131if ($pay == 'cheque') {
132 $paycode = 'CHQ'; // For backward compatibility
133}
134
135// Retrieve paiementid
136$paiementid = 0;
137if ($paycode) {
138 $sql = "SELECT id FROM ".MAIN_DB_PREFIX."c_paiement";
139 $sql .= " WHERE entity IN (".getEntity('c_paiement').")";
140 $sql .= " AND code = '".$db->escape($paycode)."'";
141 $resql = $db->query($sql);
142 if ($resql) {
143 $obj = $db->fetch_object($resql);
144 if ($obj) {
145 $paiementid = $obj->id;
146 }
147 }
148}
149
150$invoice = new Facture($db);
151if ($invoiceid > 0) {
152 $ret = $invoice->fetch($invoiceid);
153} else {
154 $ret = $invoice->fetch('', '(PROV-POS'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '') .'-'.$place.')');
155}
156if ($ret > 0) {
157 $placeid = $invoice->id;
158}
159
160$constforcompanyid = 'CASHDESK_ID_THIRDPARTY'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
161
162$soc = new Societe($db);
163if ($invoice->socid > 0) {
164 $soc->fetch($invoice->socid);
165} else {
166 $soc->fetch(getDolGlobalString($constforcompanyid));
167}
168
169// Change the currency of invoice if it was modified
170if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"])) {
171 if ($invoice->multicurrency_code != $_SESSION["takeposcustomercurrency"]) {
172 $invoice->setMulticurrencyCode($_SESSION["takeposcustomercurrency"]);
173 }
174}
175
176$term = empty($_SESSION["takeposterminal"]) ? 1 : $_SESSION["takeposterminal"];
177
178
179/*
180 * Actions
181 */
182
183$parameters=array();
184$reshook=$hookmanager->executeHooks('doActions', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
185if ($reshook < 0) {
186 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
187}
188
189if (empty($reshook)) {
190 // Action to record a payment on a TakePOS invoice
191 if ($action == 'valid' && $user->hasRight('facture', 'creer')) {
192 $bankaccount = 0;
193 $error = 0;
194
195 if (getDolGlobalString('TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT')) {
196 $bankaccount = GETPOST('accountid', 'int');
197 } else {
198 if ($pay == 'LIQ') {
199 $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]); // For backward compatibility
200 } elseif ($pay == "CHQ") {
201 $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]); // For backward compatibility
202 } else {
203 $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"];
204 $bankaccount = getDolGlobalString($accountname);
205 }
206 }
207
208 if ($bankaccount <= 0 && $pay != "delayed" && isModEnabled("banque")) {
209 $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount"));
210 $error++;
211 }
212
213 $now = dol_now();
214 $res = 0;
215
216 $invoice = new Facture($db);
217 $invoice->fetch($placeid);
218
219 $db->begin();
220
221 if ($invoice->total_ttc < 0) {
222 $invoice->type = $invoice::TYPE_CREDIT_NOTE;
223
224 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture";
225 $sql .= " WHERE entity IN (".getEntity('invoice').")";
226 $sql .= " AND fk_soc = ".((int) $invoice->socid);
227 $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE;
228 $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED;
229 $sql .= " ORDER BY rowid DESC";
230
231 $resql = $db->query($sql);
232 if ($resql) {
233 $obj = $db->fetch_object($resql);
234 $fk_source = $obj->rowid;
235 if ($fk_source == null) {
236 fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
237 }
238 } else {
239 fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
240 }
241 $invoice->fk_facture_source = $fk_source;
242 $invoice->update($user);
243 }
244
245 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
246 if ($error) {
247 dol_htmloutput_errors($errormsg, null, 1);
248 } elseif ($invoice->status != Facture::STATUS_DRAFT) {
249 //If invoice is validated but it is not fully paid is not error and make the payment
250 if ($invoice->getRemainToPay() > 0) {
251 $res = 1;
252 } else {
253 dol_syslog("Sale already validated");
254 dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1);
255 }
256 } elseif (count($invoice->lines) == 0) {
257 $error++;
258 dol_syslog('Sale without lines');
259 dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1);
260 } elseif (isModEnabled('stock') && !isModEnabled('productbatch') && getDolGlobalString($constantforkey) != "1") {
261 // Validation of invoice with change into stock when produt/lot module is not enabled and stock change not disabled.
262 // The case for isModEnabled('productbatch') is processed few lines later.
263 $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
264
265 if (isModEnabled('productbatch') && !getDolGlobalInt('CASHDESK_FORCE_DECREASE_STOCK')) {
266 $conf->global->STOCK_CALCULATE_ON_BILL = 0; // To not change the stock (this will be done later)
267 } else {
268 // Deprecated: CASHDESK_FORCE_DECREASE_STOCK is now always false. No more required/used.
269 $conf->global->STOCK_CALCULATE_ON_BILL = 1; // To force the change of stock
270 }
271
272 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
273 dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".getDolGlobalString($constantforkey));
274
275 $batch_rule = 0;
276 if (isModEnabled('productbatch') && getDolGlobalString('CASHDESK_FORCE_DECREASE_STOCK')) {
277 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
279 }
280 $res = $invoice->validate($user, '', getDolGlobalInt($constantforkey), 0, $batch_rule);
281
282 $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
283 } else {
284 // Validation of invoice with no change into stock
285 $res = $invoice->validate($user);
286 if ($res < 0) {
287 $error++;
288 $langs->load("admin");
289 dol_htmloutput_errors($invoice->error == 'NotConfigured' ? $langs->trans("NotConfigured").' (TakePos numbering module)' : $invoice->error, $invoice->errors, 1);
290 }
291 }
292
293 // Add the payment
294 if (!$error && $res >= 0) {
295 $remaintopay = $invoice->getRemainToPay();
296 if ($remaintopay > 0) {
297 $payment = new Paiement($db);
298 $payment->datepaye = $now;
299 $payment->fk_account = $bankaccount;
300 $payment->amounts[$invoice->id] = $amountofpayment;
301 if ($pay == 'LIQ') {
302 $payment->pos_change = price2num(GETPOST('excess', 'alpha'));
303 }
304
305 // If user has not used change control, add total invoice payment
306 // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay
307 if ($amountofpayment <= 0 || $amountofpayment > $remaintopay) {
308 $payment->amounts[$invoice->id] = $remaintopay;
309 }
310
311 $payment->paiementid = $paiementid;
312 $payment->num_payment = $invoice->ref;
313
314 if ($pay != "delayed") {
315 $result = $payment->create($user); // This set $payment->amount
316 if ($result < 0) {
317 $error++;
318 dol_htmloutput_errors($payment->error, $payment->errors, 1);
319 } else {
320 $res = $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', '');
321 if ($res < 0) {
322 $error++;
323 dol_htmloutput_errors($langs->trans('ErrorNoPaymentDefined'), $payment->errors, 1);
324 }
325 }
326 $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded
327 } elseif (getDolGlobalInt("TAKEPOS_DELAYED_TERMS")) {
328 $invoice->setPaymentTerms(getDolGlobalInt("TAKEPOS_DELAYED_TERMS"));
329 }
330 }
331
332 if ($remaintopay == 0) {
333 dol_syslog("Invoice is paid, so we set it to status Paid");
334 $result = $invoice->setPaid($user);
335 if ($result > 0) {
336 $invoice->paye = 1;
337 }
338 // set payment method
339 $invoice->setPaymentMethods($paiementid);
340 } else {
341 dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay);
342 }
343 } else {
344 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
345 }
346
347 // Update stock for batch products
348 if (!$error && $res >= 0) {
349 if (isModEnabled('stock') && isModEnabled('productbatch')) { // The case !isModEnabled('productbatch') was processed few lines before.
350 require_once DOL_DOCUMENT_ROOT . "/product/stock/class/mouvementstock.class.php";
351 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
352 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
353 $labeltakeposmovement = 'TakePOS - '.$langs->trans("Invoice").' '.$invoice->ref;
354
355 foreach ($invoice->lines as $line) {
356 $warehouseid = ($line->fk_warehouse ? $line->fk_warehouse : getDolGlobalInt($constantforkey));
357
358 // var_dump('fk_product='.$line->fk_product.' batch='.$line->batch.' warehouse='.$line->fk_warehouse.' qty='.$line->qty);
359 if ($line->batch != '' && $warehouseid > 0) {
360 $prod_batch = new Productbatch($db);
361 $prod_batch->find(0, '', '', $line->batch, $warehouseid);
362 $mouvP = new MouvementStock($db);
363 $mouvP->origin = $invoice;
364 $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', $prod_batch->batch, $prod_batch->id, $inventorycode);
365 if ($res < 0) {
366 setEventMessages($mouvP->error, $mouvP->errors, 'errors');
367 $error++;
368 }
369 } else {
370 $mouvP = new MouvementStock($db);
371 $mouvP->origin = $invoice;
372 $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', '', 0, $inventorycode);
373 if ($res < 0) {
374 setEventMessages($mouvP->error, $mouvP->errors, 'errors');
375 $error++;
376 }
377 }
378 }
379 }
380 }
381
382 if (!$error && $res >= 0) {
383 $db->commit();
384 } else {
385 $db->rollback();
386 }
387 }
388 if ($action == 'creditnote' && $user->hasRight('facture', 'creer')) {
389 $db->begin();
390
391 $creditnote = new Facture($db);
392 $creditnote->socid = $invoice->socid;
393 $creditnote->date = dol_now();
394 $creditnote->module_source = 'takepos';
395 $creditnote->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
396 $creditnote->type = Facture::TYPE_CREDIT_NOTE;
397 $creditnote->fk_facture_source = $placeid;
398 //$creditnote->remise_absolue = $invoice->remise_absolue;
399 //$creditnote->remise_percent = $invoice->remise_percent;
400 $creditnote->create($user);
401
402 foreach ($invoice->lines as $line) {
403 // Extrafields
404 if (method_exists($line, 'fetch_optionals')) {
405 // load extrafields
406 $line->fetch_optionals();
407 }
408 // Reset fk_parent_line for no child products and special product
409 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
410 $fk_parent_line = 0;
411 }
412
413 if (getDolGlobalInt('INVOICE_USE_SITUATION')) {
414 if (!empty($invoice->situation_counter)) {
415 $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
416 $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from
417 if (!empty($invoice->tab_previous_situation_invoice)) {
418 // search the last standard invoice in cycle and the possible credit note between this last and invoice
419 // TODO Move this out of loop of $invoice->lines
420 $tab_jumped_credit_notes = array();
421 $lineIndex = count($invoice->tab_previous_situation_invoice) - 1;
422 $searchPreviousInvoice = true;
423 while ($searchPreviousInvoice) {
424 if ($invoice->tab_previous_situation_invoice[$lineIndex]->situation_cycle_ref || $lineIndex < 1) {
425 $searchPreviousInvoice = false; // find, exit;
426 break;
427 } else {
428 if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) {
429 $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id;
430 }
431 $lineIndex--; // go to previous invoice in cycle
432 }
433 }
434
435 $maxPrevSituationPercent = 0;
436 foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) {
437 if ($prevLine->id == $source_fk_prev_id) {
438 $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent);
439
440 //$line->subprice = $line->subprice - $prevLine->subprice;
441 $line->total_ht = $line->total_ht - $prevLine->total_ht;
442 $line->total_tva = $line->total_tva - $prevLine->total_tva;
443 $line->total_ttc = $line->total_ttc - $prevLine->total_ttc;
444 $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1;
445 $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2;
446
447 $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice;
448 $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht;
449 $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva;
450 $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc;
451 }
452 }
453
454 // prorata
455 $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
456
457 //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'<br>';
458
459 // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta)
460 $maxPrevSituationPercent = 0;
461 foreach ($tab_jumped_credit_notes as $index => $creditnoteid) {
462 foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) {
463 if ($prevLine->fk_prev_id == $source_fk_prev_id) {
464 $maxPrevSituationPercent = $prevLine->situation_percent;
465
466 $line->total_ht -= $prevLine->total_ht;
467 $line->total_tva -= $prevLine->total_tva;
468 $line->total_ttc -= $prevLine->total_ttc;
469 $line->total_localtax1 -= $prevLine->total_localtax1;
470 $line->total_localtax2 -= $prevLine->total_localtax2;
471
472 $line->multicurrency_subprice -= $prevLine->multicurrency_subprice;
473 $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht;
474 $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
475 $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
476 }
477 }
478 }
479
480 // prorata
481 $line->situation_percent += $maxPrevSituationPercent;
482
483 //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'<br>';
484 }
485 }
486 }
487
488 $line->fk_facture = $creditnote->id;
489 $line->fk_parent_line = $fk_parent_line;
490
491 $line->subprice = -$line->subprice; // invert price for object
492 $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here
493 $line->total_ht = -$line->total_ht;
494 $line->total_tva = -$line->total_tva;
495 $line->total_ttc = -$line->total_ttc;
496 $line->total_localtax1 = -$line->total_localtax1;
497 $line->total_localtax2 = -$line->total_localtax2;
498
499 $line->multicurrency_subprice = -$line->multicurrency_subprice;
500 $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
501 $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
502 $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
503
504 $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked
505
506 $creditnote->lines[] = $line; // insert new line in current object
507
508 // Defined the new fk_parent_line
509 if ($result > 0 && $line->product_type == 9) {
510 $fk_parent_line = $result;
511 }
512 }
513 $creditnote->update_price(1);
514
515 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
516 if (isModEnabled('stock') && getDolGlobalString($constantforkey) != "1") {
517 $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
518 $conf->global->STOCK_CALCULATE_ON_BILL = 1;
519 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
520 dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".getDolGlobalString($constantforkey));
521 $batch_rule = 0;
522 if (isModEnabled('productbatch') && getDolGlobalString('CASHDESK_FORCE_DECREASE_STOCK')) {
523 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
525 }
526 $res = $creditnote->validate($user, '', getDolGlobalString($constantforkey), 0, $batch_rule);
527 $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
528 } else {
529 $res = $creditnote->validate($user);
530 }
531
532 if (!$error && $res >= 0) {
533 $db->commit();
534 } else {
535 $db->rollback();
536 }
537 }
538
539 if (($action == 'history' || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
540 if ($action == 'creditnote') {
541 $placeid = $creditnote->id;
542 } else {
543 $placeid = (int) GETPOST('placeid', 'int');
544 }
545 $invoice = new Facture($db);
546 $invoice->fetch($placeid);
547 }
548
549 // If we add a line and no invoice yet, we create the invoice
550 if (($action == "addline" || $action == "freezone") && $placeid == 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
551 $invoice->socid = getDolGlobalString($constforcompanyid);
552
553 $dolnowtzuserrel = dol_now('tzuserrel'); // If user is 02 january 22:00, we want to store '02 january'
554 $monthuser = dol_print_date($dolnowtzuserrel, '%m', 'gmt');
555 $dayuser = dol_print_date($dolnowtzuserrel, '%d', 'gmt');
556 $yearuser = dol_print_date($dolnowtzuserrel, '%Y', 'gmt');
557 $dateinvoice = dol_mktime(0, 0, 0, (int) $monthuser, (int) $dayuser, (int) $yearuser, 'tzserver'); // If we enter the 02 january, we need to save the 02 january for server
558
559 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
560 $invoice->date = $dateinvoice; // Invoice::create() needs a date with no hours
561
562 $invoice->module_source = 'takepos';
563 $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
564 $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
565
566 if ($invoice->socid <= 0) {
567 $langs->load('errors');
568 dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1);
569 } else {
570 $db->begin();
571
572 // Create invoice
573 $placeid = $invoice->create($user);
574 if ($placeid < 0) {
575 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
576 }
577 $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid = ".((int) $placeid);
578 $resql = $db->query($sql);
579 if (!$resql) {
580 $error++;
581 }
582
583 if (!$error) {
584 $db->commit();
585 } else {
586 $db->rollback();
587 }
588 }
589 }
590
591 // If we add a line by click on product (invoice exists here because it was created juste before if it didn't exists)
592 if ($action == "addline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
593 $prod = new Product($db);
594 $prod->fetch($idproduct);
595
596 $customer = new Societe($db);
597 $customer->fetch($invoice->socid);
598
599 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
600
601 $qty = GETPOSTISSET('qty') ? GETPOST('qty', 'int') : 1;
602 $price = $datapriceofproduct['pu_ht'];
603 $price_ttc = $datapriceofproduct['pu_ttc'];
604 //$price_min = $datapriceofproduct['price_min'];
605 $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
606 $tva_tx = $datapriceofproduct['tva_tx'];
607 $tva_npr = $datapriceofproduct['tva_npr'];
608
609 // Local Taxes
610 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
611 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
612
613
614 if (isModEnabled('productbatch') && isModEnabled('stock')) {
615 $batch = GETPOST('batch', 'alpha');
616
617 if (!empty($batch)) { // We have just clicked on the batch number
618 $action = "setbatch";
619 } elseif ($prod->status_batch > 0) {
620 // If product need a lot/serial, we show the list of lot/serial available for the product...
621
622 // Set nb of suggested with nb of batch into the warehouse of the terminal
623 $nbofsuggested = 0;
624 $prod->load_stock('warehouseopen');
625
626 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
627 $warehouseid = getDolGlobalInt($constantforkey);
628
629 //var_dump($prod->stock_warehouse);
630 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
631 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
632 // Not on the forced warehous, so we ignore this warehous
633 continue;
634 }
635 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
636 if (is_object($prod->stock_warehouse[$tmpwarehouseid]) && count($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
637 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) {
638 $nbofsuggested++;
639 }
640 }
641 }
642 }
643 //var_dump($prod->stock_warehouse);
644
645 echo "<script>\n";
646 echo "function addbatch(batch, warehouseid) {\n";
647 echo "console.log('We add batch '+batch+' from warehouse id '+warehouseid);\n";
648 echo '$("#poslines").load("invoice.php?action=addline&batch="+batch+"&warehouseid="+warehouseid+"&place='.$place.'&idproduct='.$idproduct.'&token='.newToken().'", function() {});'."\n";
649 echo "}\n";
650 echo "</script>\n";
651
652 $suggestednb = 1;
653 echo "<center>".$langs->trans("SearchIntoBatch").": <b> $nbofsuggested </b></center><br><table>";
654 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
655 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
656 // Not on the forced warehous, so we ignore this warehous
657 continue;
658 }
659 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
660 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) { // $dbatch is instance of Productbatch
661 $batchStock = + $dbatch->qty; // To get a numeric
662 $quantityToBeDelivered = 1;
663 $deliverableQty = min($quantityToBeDelivered, $batchStock);
664 print '<tr>';
665 print '<!-- subj='.$suggestednb.'/'.$nbofsuggested.' -->';
666 print '<!-- Show details of lot -->';
667 print '<td class="left">';
668 $detail = '';
669 $detail .= '<span class="opacitymedium">'.$langs->trans("LotSerial").':</span> '.$dbatch->batch;
670 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
671 //$detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
672 }
673 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
674 //$detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
675 }
676 $detail .= '</td><td>';
677 $detail .= '<span class="opacitymedium">'.$langs->trans("Qty").':</span> '.$dbatch->qty;
678 $detail .= '</td><td>';
679 $detail .= ' <button class="marginleftonly" onclick="addbatch(\''.dol_escape_js($dbatch->batch).'\', '.$tmpwarehouseid.')">'.$langs->trans("Select")."</button>";
680 $detail .= '<br>';
681 print $detail;
682
683 $quantityToBeDelivered -= $deliverableQty;
684 if ($quantityToBeDelivered < 0) {
685 $quantityToBeDelivered = 0;
686 }
687 $suggestednb++;
688 print '</td></tr>';
689 }
690 }
691 }
692 print "</table>";
693
694 print '</body></html>';
695 exit;
696 }
697 }
698
699
700 if (getDolGlobalString('TAKEPOS_SUPPLEMENTS')) {
701 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
702 $cat = new Categorie($db);
703 $categories = $cat->containing($idproduct, 'product');
704 $found = (array_search(getDolGlobalInt('TAKEPOS_SUPPLEMENTS_CATEGORY'), array_column($categories, 'id')));
705 if ($found !== false) { // If this product is a supplement
706 $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid = ".((int) $selectedline);
707 $resql = $db->query($sql);
708 $row = $db->fetch_array($resql);
709 if ($row[0] == null) {
710 $parent_line = $selectedline;
711 } else {
712 $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product
713 }
714 }
715 }
716
717 $idoflineadded = 0;
718 $err = 0;
719 // Group if enabled. Skip group if line already sent to the printer
720 if (getDolGlobalString('TAKEPOS_GROUP_SAME_PRODUCT')) {
721 foreach ($invoice->lines as $line) {
722 if ($line->product_ref == $prod->ref) {
723 if ($line->special_code==4) {
724 continue;
725 } // If this line is sended to printer create new line
726 // check if qty in stock
727 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && (($line->qty + $qty) > $prod->stock_reel)) {
728 $invoice->error = $langs->trans('NotEnoughInStock');
729 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
730 $err++;
731 break;
732 }
733 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + $qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
734 if ($result < 0) {
735 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
736 } else {
737 $idoflineadded = $line->id;
738 }
739 break;
740 }
741 }
742 }
743 if ($idoflineadded <= 0 && empty($err)) {
744 $invoice->fetch_thirdparty();
745 $array_options = array();
746
747 $line = array('description' => $prod->description, 'price' => $price, 'tva_tx' => $tva_tx, 'localtax1_tx' => $localtax1_tx, 'localtax2_tx' => $localtax2_tx, 'remise_percent' => $customer->remise_percent, 'price_ttc' => $price_ttc, 'array_options' => $array_options);
748
749 /* setup of margin calculation */
750 if (isset($conf->global->MARGIN_TYPE)) {
751 if (getDolGlobalString('MARGIN_TYPE') == 'pmp' && !empty($prod->pmp)) {
752 $line['fk_fournprice'] = null;
753 $line['pa_ht'] = $prod->pmp;
754 } elseif (getDolGlobalString('MARGIN_TYPE') == 'costprice' && !empty($prod->cost_price)) {
755 $line['fk_fournprice'] = null;
756 $line['pa_ht'] = $prod->cost_price;
757 } else {
758 // default is fournprice
759 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
760 $pf = new ProductFournisseur($db);
761 if ($pf->find_min_price_product_fournisseur($idproduct, $qty) > 0) {
762 $line['fk_fournprice'] = $pf->product_fourn_price_id;
763 $line['pa_ht'] = $pf->fourn_unitprice_with_discount;
764 if (getDolGlobalString('PRODUCT_CHARGES') && $pf->fourn_charges > 0) {
765 $line['pa_ht'] += $pf->fourn_charges / $pf->fourn_qty;
766 }
767 }
768 }
769 }
770
771 // complete line by hook
772 $parameters = array('prod' => $prod, 'line' => $line);
773 $reshook=$hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); // Note that $action and $line may have been modified by some hooks
774 if ($reshook < 0) {
775 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
776 }
777
778
779 if (empty($reshook)) {
780 if (!empty($hookmanager->resArray)) {
781 $line = $hookmanager->resArray;
782 }
783
784 // check if qty in stock
785 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && $qty > $prod->stock_reel) {
786 $invoice->error = $langs->trans('NotEnoughInStock');
787 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
788 $err++;
789 }
790
791 if (empty($err)) {
792 $idoflineadded = $invoice->addline($line['description'], $line['price'], $qty, $line['tva_tx'], $line['localtax1_tx'], $line['localtax2_tx'], $idproduct, $line['remise_percent'], '', 0, 0, 0, '', $price_base_type, $line['price_ttc'], $prod->type, -1, 0, '', 0, (empty($parent_line) ? '' : $parent_line), (empty($line['fk_fournprice']) ? 0 : $line['fk_fournprice']), (empty($line['pa_ht']) ? '' : $line['pa_ht']), '', $line['array_options'], 100, '', null, 0);
793 }
794 }
795
796 if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
797 $CUSTOMER_DISPLAY_line1 = $prod->label;
798 $CUSTOMER_DISPLAY_line2 = price($price_ttc);
799 }
800 }
801
802 $invoice->fetch($placeid);
803 }
804
805 // If we add a line by submitting freezone form (invoice exists here because it was created juste before if it didn't exists)
806 if ($action == "freezone" && $user->hasRight('takepos', 'run')) {
807 $customer = new Societe($db);
808 $customer->fetch($invoice->socid);
809
810 $tva_tx = GETPOST('tva_tx', 'alpha');
811 if ($tva_tx != '') {
812 if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
813 $tva_tx = price2num($tva_tx);
814 }
815 } else {
816 $tva_tx = get_default_tva($mysoc, $customer);
817 }
818
819 // Local Taxes
820 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
821 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
822
823 $res = $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', getDolGlobalInt('TAKEPOS_DISCOUNT_TTC') ? ($number >= 0 ? 'HT' : 'TTC') : (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') ? 'HT' : 'TTC'), $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
824 if ($res < 0) {
825 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
826 }
827 $invoice->fetch($placeid);
828 }
829
830 if ($action == "addnote" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
831 $desc = GETPOST('addnote', 'alpha');
832 if ($idline==0) {
833 $invoice->update_note($desc, '_public');
834 } else {
835 foreach ($invoice->lines as $line) {
836 if ($line->id == $idline) {
837 $result = $invoice->updateline($line->id, $desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
838 }
839 }
840 }
841 $invoice->fetch($placeid);
842 }
843
844 if ($action == "deleteline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
845 /*
846 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
847 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
848 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
849 $permissiontoupdateline = true;
850 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
851 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
852 }
853 }*/
854
855 if ($idline > 0 && $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
856 $invoice->deleteline($idline);
857 $invoice->fetch($placeid);
858 } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line.
859 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC";
860 $resql = $db->query($sql);
861 $row = $db->fetch_array($resql);
862 $deletelineid = $row[0];
863 $invoice->deleteline($deletelineid);
864 $invoice->fetch($placeid);
865 }
866
867 if (count($invoice->lines) == 0) {
868 $invoice->delete($user);
869
870 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
871 header("Location: ".DOL_URL_ROOT."/takepos/public/auto_order.php");
872 } else {
873 header("Location: ".DOL_URL_ROOT."/takepos/invoice.php");
874 }
875 exit;
876 }
877 }
878
879 // Action to delete or discard an invoice
880 if ($action == "delete" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
881 // $placeid is the invoice id (it differs from place) and is defined if the place is set and the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at begining of page works.
882 if ($placeid > 0) {
883 $result = $invoice->fetch($placeid);
884
885 if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) {
886 $db->begin();
887
888 // We delete the lines
889 $resdeletelines = 1;
890 foreach ($invoice->lines as $line) {
891 $tmpres = $invoice->deleteline($line->id);
892 if ($tmpres < 0) {
893 $resdeletelines = 0;
894 break;
895 }
896 }
897
898 $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
899 $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
900 $sql .= " SET fk_soc = ".((int) getDolGlobalString($varforconst)).", ";
901 $sql .= " datec = '".$db->idate(dol_now())."'";
902 $sql .= " WHERE entity IN (".getEntity('invoice').")";
903 $sql .= " AND ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
904 $resql1 = $db->query($sql);
905
906 if ($resdeletelines && $resql1) {
907 $db->commit();
908 } else {
909 $db->rollback();
910 }
911
912 $invoice->fetch($placeid);
913 }
914 }
915 }
916
917 if ($action == "updateqty") { // Test on permission is done later
918 foreach ($invoice->lines as $line) {
919 if ($line->id == $idline) {
920 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
921 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
922 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
923 $permissiontoupdateline = true;
924 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
925 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
926 }
927 }
928 if (!$permissiontoupdateline) {
929 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateqty', null, 1);
930 } else {
931 $vatratecode = $line->tva_tx;
932 if ($line->vat_src_code) {
933 $vatratecode .= ' ('.$line->vat_src_code.')';
934 }
935
936 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
937 }
938 }
939 }
940
941 $invoice->fetch($placeid);
942 }
943
944 if ($action == "updateprice") { // Test on permission is done later
945 $customer = new Societe($db);
946 $customer->fetch($invoice->socid);
947
948 foreach ($invoice->lines as $line) {
949 if ($line->id == $idline) {
950 $prod = new Product($db);
951 $prod->fetch($line->fk_product);
952 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
953 $price_min = $datapriceofproduct['price_min'];
954 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && empty($user->rights->produit->ignore_price_min_advance)) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
955 $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
956 //Check min price
957 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) {
958 $langs->load("products");
959 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
960 //echo $langs->trans("CantBeLessThanMinPrice");
961 } else {
962 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
963 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
964 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
965 $permissiontoupdateline = true;
966 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
967 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
968 }
969 }
970
971 $vatratecode = $line->tva_tx;
972 if ($line->vat_src_code) {
973 $vatratecode .= ' ('.$line->vat_src_code.')';
974 }
975
976 if (!$permissiontoupdateline) {
977 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateprice', null, 1);
978 } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) {
979 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
980 } else {
981 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $line->localtax1_tx, $line->localtax2_tx, 'TTC', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
982 }
983 }
984 }
985 }
986
987 // Reload data
988 $invoice->fetch($placeid);
989 }
990
991 if ($action == "updatereduction") { // Test on permission is done later
992 $customer = new Societe($db);
993 $customer->fetch($invoice->socid);
994
995 foreach ($invoice->lines as $line) {
996 if ($line->id == $idline) {
997 dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%');
998
999 $prod = new Product($db);
1000 $prod->fetch($line->fk_product);
1001
1002 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
1003 $price_min = $datapriceofproduct['price_min'];
1004 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && empty($user->rights->produit->ignore_price_min_advance)) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
1005
1006 $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
1007
1008 // Check min price
1009 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) {
1010 $langs->load("products");
1011 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
1012 } else {
1013 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1014 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1015 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1016 $permissiontoupdateline = true;
1017 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1018 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
1019 }
1020 }
1021 if (!$permissiontoupdateline) {
1022 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
1023 } else {
1024 $vatratecode = $line->tva_tx;
1025 if ($line->vat_src_code) {
1026 $vatratecode .= ' ('.$line->vat_src_code.')';
1027 }
1028 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $vatratecode, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
1029 }
1030 }
1031 }
1032 }
1033
1034 // Reload data
1035 $invoice->fetch($placeid);
1036 } elseif ($action == 'update_reduction_global' && $user->hasRight('takepos', 'editlines')) {
1037 foreach ($invoice->lines as $line) {
1038 $vatratecode = $line->tva_tx;
1039 if ($line->vat_src_code) {
1040 $vatratecode .= ' ('.$line->vat_src_code.')';
1041 }
1042 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $vatratecode, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
1043 }
1044
1045 $invoice->fetch($placeid);
1046 }
1047
1048 if ($action=="setbatch" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1049 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1050 $warehouseid = getDolGlobalInt($constantforkey); // TODO Get the wrehouse id from GETPOSTINT('warehouseid');
1051 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet SET batch = '".$db->escape($batch)."', fk_warehouse = ".((int) $warehouseid);
1052 $sql .= " WHERE rowid=".((int) $idoflineadded);
1053 $db->query($sql);
1054 }
1055
1056 if ($action == "order" && $placeid != 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1057 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1058 if ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1059 require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
1060 $printer = new dolReceiptPrinter($db);
1061 }
1062
1063 $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1064 $resql = $db->query($sql);
1065 $row = $db->fetch_object($resql);
1066 $headerorder = '<html><br><b>'.$langs->trans('Place').' '.$row->label.'<br><table width="65%"><thead><tr><th class="left">'.$langs->trans("Label").'</th><th class="right">'.$langs->trans("Qty").'</th></tr></thead><tbody>';
1067 $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
1068 $order_receipt_printer1 = "";
1069 $order_receipt_printer2 = "";
1070 $order_receipt_printer3 = "";
1071 $catsprinter1 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_1'));
1072 $catsprinter2 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_2'));
1073 $catsprinter3 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_3'));
1074 $linestoprint = 0;
1075 foreach ($invoice->lines as $line) {
1076 if ($line->special_code == "4") {
1077 continue;
1078 }
1079 $c = new Categorie($db);
1080 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1081 $result = array_intersect($catsprinter1, $existing);
1082 $count = count($result);
1083 if (!$line->fk_product) {
1084 $count++; // Print Free-text item (Unassigned printer) to Printer 1
1085 }
1086 if ($count > 0) {
1087 $linestoprint++;
1088 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
1089 $db->query($sql);
1090 $order_receipt_printer1 .= '<tr><td class="left">';
1091 if ($line->fk_product) {
1092 $order_receipt_printer1 .= $line->product_label;
1093 } else {
1094 $order_receipt_printer1 .= $line->description;
1095 }
1096 $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
1097 if (!empty($line->array_options['options_order_notes'])) {
1098 $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
1099 }
1100 $order_receipt_printer1 .= '</td></tr>';
1101 }
1102 }
1103 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1104 $invoice->fetch($placeid); //Reload object before send to printer
1105 $printer->orderprinter = 1;
1106 echo "<script>";
1107 echo "var orderprinter1esc='";
1108 $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER1_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 1
1109 echo "';</script>";
1110 }
1111 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
1112 $db->query($sql);
1113 $invoice->fetch($placeid); //Reload object after set lines as printed
1114 $linestoprint = 0;
1115
1116 foreach ($invoice->lines as $line) {
1117 if ($line->special_code == "4") {
1118 continue;
1119 }
1120 $c = new Categorie($db);
1121 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1122 $result = array_intersect($catsprinter2, $existing);
1123 $count = count($result);
1124 if ($count > 0) {
1125 $linestoprint++;
1126 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
1127 $db->query($sql);
1128 $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1129 if (!empty($line->array_options['options_order_notes'])) {
1130 $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
1131 }
1132 $order_receipt_printer2 .= '</td></tr>';
1133 }
1134 }
1135 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1136 $invoice->fetch($placeid); //Reload object before send to printer
1137 $printer->orderprinter = 2;
1138 echo "<script>";
1139 echo "var orderprinter2esc='";
1140 $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER2_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 2
1141 echo "';</script>";
1142 }
1143 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
1144 $db->query($sql);
1145 $invoice->fetch($placeid); //Reload object after set lines as printed
1146 $linestoprint = 0;
1147
1148 foreach ($invoice->lines as $line) {
1149 if ($line->special_code == "4") {
1150 continue;
1151 }
1152 $c = new Categorie($db);
1153 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1154 $result = array_intersect($catsprinter3, $existing);
1155 $count = count($result);
1156 if ($count > 0) {
1157 $linestoprint++;
1158 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
1159 $db->query($sql);
1160 $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1161 if (!empty($line->array_options['options_order_notes'])) {
1162 $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
1163 }
1164 $order_receipt_printer3 .= '</td></tr>';
1165 }
1166 }
1167 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1168 $invoice->fetch($placeid); //Reload object before send to printer
1169 $printer->orderprinter = 3;
1170 echo "<script>";
1171 echo "var orderprinter3esc='";
1172 $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER3_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 3
1173 echo "';</script>";
1174 }
1175 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
1176 $db->query($sql);
1177 $invoice->fetch($placeid); //Reload object after set lines as printed
1178 }
1179
1180 $sectionwithinvoicelink = '';
1181 if (($action == "valid" || $action == "history" || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
1182 $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
1183 $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
1184 $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
1185 $remaintopay = $invoice->getRemainToPay();
1186 if ($remaintopay > 0) {
1187 $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
1188 } else {
1189 if ($invoice->paye) {
1190 $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">'.$langs->trans("Paid").'</span>';
1191 } else {
1192 $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
1193 }
1194 }
1195
1196 $sectionwithinvoicelink .= '</span><br>';
1197 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1198 $sectionwithinvoicelink .= ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
1199 } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1200 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1201 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1202 } else {
1203 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1204 }
1205 } elseif ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
1206 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1207 } else {
1208 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1209 if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
1210 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox('.$placeid.', \'without_details\')">'.$langs->trans('PrintWithoutDetails').'</button>';
1211 }
1212 if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
1213 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1)">'.$langs->trans('GiftReceipt').'</button>';
1214 }
1215 }
1216 if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && getDolGlobalInt('TAKEPOS_EMAIL_TEMPLATE_INVOICE') > 0) {
1217 $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.')">'.$langs->trans('SendTicket').'</button>';
1218 }
1219
1220 if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
1221 $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
1222 }
1223 }
1224}
1225
1226
1227/*
1228 * View
1229 */
1230
1231$form = new Form($db);
1232
1233// llxHeader
1234if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1235 $title = 'TakePOS - Dolibarr '.DOL_VERSION;
1236 if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
1237 $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
1238 }
1239 $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
1240 <meta name="apple-mobile-web-app-capable" content="yes">
1241 <meta name="mobile-web-app-capable" content="yes">
1242 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
1243 $arrayofcss = array(
1244 '/takepos/css/pos.css.php',
1245 );
1246 $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
1247 $disablejs = 0;
1248 $disablehead = 0;
1249 top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1250
1251 print '<body>'."\n";
1252} else {
1253 top_httphead('text/html', 1);
1254}
1255
1256?>
1257<!-- invoice.php -->
1258<script type="text/javascript">
1259var selectedline=0;
1260var selectedtext="";
1261<?php if ($action=="valid") {
1262 echo "var place=0;";
1263}?> // Set to default place after close sale
1264var placeid=<?php echo($placeid > 0 ? $placeid : 0); ?>;
1265$(document).ready(function() {
1266 var idoflineadded = <?php echo(empty($idoflineadded) ? 0 : $idoflineadded); ?>;
1267
1268 $('.posinvoiceline').click(function(){
1269 console.log("Click done on "+this.id);
1270 $('.posinvoiceline').removeClass("selected");
1271 $(this).addClass("selected");
1272 if (!this.id) {
1273 return;
1274 }
1275 if (selectedline == this.id) {
1276 return; // If is already selected
1277 } else {
1278 selectedline = this.id;
1279 }
1280 selectedtext=$('#'+selectedline).find("td:first").html();
1281 <?php
1282 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1283 print '$("#phonediv1").load("'.DOL_URL_ROOT.'/takepos/public/auto_order.php?action=editline&token='.newToken().'&placeid="+placeid+"&selectedline="+selectedline, function() {
1284 });';
1285 }
1286 ?>
1287 });
1288
1289 /* Autoselect the line */
1290 if (idoflineadded > 0)
1291 {
1292 console.log("Auto select "+idoflineadded);
1293 $('.posinvoiceline#'+idoflineadded).click();
1294 }
1295<?php
1296
1297if ($action == "order" && !empty($order_receipt_printer1)) {
1298 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1299 ?>
1300 $.ajax({
1301 type: "POST",
1302 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
1303 data: 'invoice='+orderprinter1esc
1304 });
1305 <?php
1306 } else {
1307 ?>
1308 $.ajax({
1309 type: "POST",
1310 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1311 data: '<?php
1312 print $headerorder.$order_receipt_printer1.$footerorder; ?>'
1313 });
1314 <?php
1315 }
1316}
1317
1318if ($action == "order" && !empty($order_receipt_printer2)) {
1319 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1320 ?>
1321 $.ajax({
1322 type: "POST",
1323 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
1324 data: 'invoice='+orderprinter2esc
1325 });
1326 <?php
1327 } else {
1328 ?>
1329 $.ajax({
1330 type: "POST",
1331 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
1332 data: '<?php
1333 print $headerorder.$order_receipt_printer2.$footerorder; ?>'
1334 });
1335 <?php
1336 }
1337}
1338
1339if ($action == "order" && !empty($order_receipt_printer3)) {
1340 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1341 ?>
1342 $.ajax({
1343 type: "POST",
1344 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
1345 data: 'invoice='+orderprinter3esc
1346 });
1347 <?php
1348 }
1349}
1350
1351// Set focus to search field
1352if ($action == "search" || $action == "valid") {
1353 ?>
1354 parent.setFocusOnSearchField();
1355 <?php
1356}
1357
1358
1359if ($action == "temp" && !empty($ticket_printer1)) {
1360 ?>
1361 $.ajax({
1362 type: "POST",
1363 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1364 data: '<?php
1365 print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
1366 });
1367 <?php
1368}
1369
1370if ($action == "search") {
1371 ?>
1372 $('#search').focus();
1373 <?php
1374}
1375
1376?>
1377
1378});
1379
1380function SendTicket(id)
1381{
1382 console.log("Open box to select the Print/Send form");
1383 $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1384 return true;
1385}
1386
1387function PrintBox(id, action) {
1388 console.log("Open box before printing");
1389 $.colorbox({href:"printbox.php?facid="+id+"&action="+action+"&token=<?php echo newToken(); ?>", width:"80%", height:"200px", transition:"none", iframe:"true", title:"<?php echo $langs->trans("PrintWithoutDetails"); ?>"});
1390 return true;
1391}
1392
1393function Print(id, gift){
1394 console.log("Call Print() to generate the receipt.");
1395 $.colorbox({href:"receipt.php?facid="+id+"&gift="+gift, width:"40%", height:"90%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("PrintTicket")); ?>'});
1396 return true;
1397}
1398
1399function TakeposPrinting(id){
1400 var receipt;
1401 console.log("TakeposPrinting" + id);
1402 $.get("receipt.php?facid="+id, function(data, status) {
1403 receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1404 $.ajax({
1405 type: "POST",
1406 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1407 data: receipt
1408 });
1409 });
1410 return true;
1411}
1412
1413function TakeposConnector(id){
1414 console.log("TakeposConnector" + id);
1415 $.get("<?php echo DOL_URL_ROOT; ?>/takepos/ajax/ajax.php?action=printinvoiceticket&token=<?php echo newToken(); ?>&term=<?php echo urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : ''); ?>&id="+id+"&token=<?php echo currentToken(); ?>", function(data, status) {
1416 $.ajax({
1417 type: "POST",
1418 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1419 data: 'invoice='+data
1420 });
1421 });
1422 return true;
1423}
1424
1425function DolibarrTakeposPrinting(id) {
1426 console.log("DolibarrTakeposPrinting Printing invoice ticket " + id)
1427 $.ajax({
1428 type: "GET",
1429 data: { token: '<?php echo currentToken(); ?>' },
1430 url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=printinvoiceticket&token='.newToken().'&term='.urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '').'&id='; ?>" + id,
1431 });
1432 return true;
1433}
1434
1435function CreditNote() {
1436 $("#poslines").load("invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() { });
1437 return true;
1438}
1439
1440function SetNote() {
1441 $("#poslines").load("invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1442 return true;
1443}
1444
1445
1446$( document ).ready(function() {
1447 console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
1448
1449 <?php
1450 $s = $langs->trans("Customer");
1451 if ($invoice->id > 0 && ($invoice->socid != getDolGlobalString($constforcompanyid))) {
1452 $s = $soc->name;
1453 if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT')) {
1454 $contactids = $invoice->getIdContact('external', 'BILLING');
1455 $contactid = $contactids[0];
1456 if ($contactid > 0) {
1457 $contact = new Contact($db);
1458 $contact->fetch($contactid);
1459 $s .= " - " . $contact->getFullName($langs);
1460 }
1461 }
1462 }
1463 ?>
1464
1465 $("#customerandsales").html('');
1466 $("#shoppingcart").html('');
1467
1468 <?php if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT') == 0) { ?>
1469 $("#customerandsales").append('<a class="valignmiddle tdoverflowmax100 minwidth100" id="customer" onclick="Customer();" title="<?php print dol_escape_js(dol_escape_htmltag($s)); ?>"><span class="fas fa-building paddingrightonly"></span><?php print dol_escape_js($s); ?></a>');
1470 <?php } else { ?>
1471 $("#customerandsales").append('<a class="valignmiddle tdoverflowmax300 minwidth100" id="contact" onclick="Contact();" title="<?php print dol_escape_js(dol_escape_htmltag($s)); ?>"><span class="fas fa-building paddingrightonly"></span><?php print dol_escape_js($s); ?></a>');
1472 <?php } ?>
1473
1474 <?php
1475 $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
1476 $sql .= " WHERE entity IN (".getEntity('invoice').")";
1477 if (!getDolGlobalString('TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED')) {
1478 // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1479 $sql .= " AND ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%'";
1480 } else {
1481 // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1482 $sql .= " AND pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
1483 $sql .= " AND module_source = 'takepos'";
1484 }
1485
1486 $sql .= $db->order('datec', 'ASC');
1487 $resql = $db->query($sql);
1488 if ($resql) {
1489 $max_sale = 0;
1490 while ($obj = $db->fetch_object($resql)) {
1491 echo '$("#shoppingcart").append(\'';
1492 echo '<a class="valignmiddle" title="'.dol_escape_js($langs->trans("SaleStartedAt", dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser')).' - '.$obj->ref).'" onclick="place=\\\'';
1493 $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
1494 echo $num_sale;
1495 if (str_replace("-", "", $num_sale) > $max_sale) {
1496 $max_sale = str_replace("-", "", $num_sale);
1497 }
1498 echo '\\\'; invoiceid=\\\'';
1499 echo $obj->rowid;
1500 echo '\\\'; Refresh();">';
1501 if ($placeid == $obj->rowid) {
1502 echo '<span class="basketselected">';
1503 } else {
1504 echo '<span class="basketnotselected">';
1505 }
1506 echo '<span class="fa fa-shopping-cart paddingright"></span>'.dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1507 echo '</span>';
1508 echo '</a>\');';
1509 }
1510 echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1511 echo $max_sale + 1;
1512 echo '\\\'; invoiceid=0; Refresh();"><div><span class="fa fa-plus" title="'.dol_escape_htmltag($langs->trans("StartAParallelSale")).'"><span class="fa fa-shopping-cart"></span></div></a>\');';
1513 } else {
1514 dol_print_error($db);
1515 }
1516
1517 $s = '';
1518
1519 $idwarehouse = 0;
1520 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1521 if (isModEnabled('stock')) {
1522 if (getDolGlobalString($constantforkey) != "1") {
1523 $constantforkey = 'CASHDESK_ID_WAREHOUSE'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1524 $idwarehouse = getDolGlobalString($constantforkey);
1525 if ($idwarehouse > 0) {
1526 $s = '<span class="small">';
1527 $warehouse = new Entrepot($db);
1528 $warehouse->fetch($idwarehouse);
1529 $s .= '<span class="hideonsmartphone">'.$langs->trans("Warehouse").'<br></span>'.$warehouse->ref;
1530 if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1531 $s .= ' ('.$langs->trans("Closed").')';
1532 }
1533 $s .= '</span>';
1534 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1535 print '$("#infowarehouse").css("display", "inline-block");';
1536 } else {
1537 $s = '<span class="small hideonsmartphone">';
1538 $s .= $langs->trans("StockChangeDisabled").'<br>'.$langs->trans("NoWarehouseDefinedForTerminal");
1539 $s .= '</span>';
1540 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1541 if (!empty($conf->dol_optimize_smallscreen)) {
1542 print '$("#infowarehouse").css("display", "none");';
1543 }
1544 }
1545 } else {
1546 $s = '<span class="small hideonsmartphone">'.$langs->trans("StockChangeDisabled").'</span>';
1547 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1548 if (!empty($conf->dol_optimize_smallscreen)) {
1549 print '$("#infowarehouse").css("display", "none");';
1550 }
1551 }
1552 }
1553
1554
1555 // Module Adherent
1556 $s = '';
1557 if (isModEnabled('adherent') && $invoice->socid > 0 && $invoice->socid != getDolGlobalInt($constforcompanyid)) {
1558 $s = '<span class="small">';
1559 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1560 $langs->load("members");
1561 $s .= $langs->trans("Member").': ';
1562 $adh = new Adherent($db);
1563 $result = $adh->fetch('', '', $invoice->socid);
1564 if ($result > 0) {
1565 $adh->ref = $adh->getFullName($langs);
1566 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1567 $s .= "<s>";
1568 }
1569 $s .= $adh->getFullName($langs);
1570 $s .= ' - '.$adh->type;
1571 if ($adh->datefin) {
1572 $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
1573 if ($adh->hasDelay()) {
1574 $s .= " ".img_warning($langs->trans("Late"));
1575 }
1576 } else {
1577 $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
1578 if ($adh->statut > 0) {
1579 $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1580 }
1581 }
1582 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1583 $s .= "</s>";
1584 }
1585 } else {
1586 $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
1587 }
1588 $s .= '</span>';
1589 }
1590 ?>
1591 $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1592
1593});
1594
1595
1596<?php
1597if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
1598 echo "function CustomerDisplay(){";
1599 echo "var line1='".$CUSTOMER_DISPLAY_line1."'.substring(0,20);";
1600 echo "line1=line1.padEnd(20);";
1601 echo "var line2='".$CUSTOMER_DISPLAY_line2."'.substring(0,20);";
1602 echo "line2=line2.padEnd(20);";
1603 echo "$.ajax({
1604 type: 'GET',
1605 data: { text: line1+line2 },
1606 url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
1607 });";
1608 echo "}";
1609}
1610?>
1611
1612</script>
1613
1614<?php
1615// Add again js for footer because this content is injected into index.php page so all init
1616// for tooltip and other js beautifiers must be reexecuted too.
1617if (!empty($conf->use_javascript_ajax)) {
1618 print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1619 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
1620}
1621
1622$usediv = (GETPOST('format') == 'div');
1623
1624print '<!-- invoice.php place='.(int) $place.' invoice='.$invoice->ref.' usediv='.$usediv.', mobilepage='.(empty($mobilepage) ? '' : $mobilepage).' $_SESSION["basiclayout"]='.(empty($_SESSION["basiclayout"]) ? '' : $_SESSION["basiclayout"]).' conf TAKEPOS_BAR_RESTAURANT='.getDolGlobalString('TAKEPOS_BAR_RESTAURANT').' -->'."\n";
1625print '<div class="div-table-responsive-no-min invoice">';
1626if ($usediv) {
1627 print '<div id="tablelines">';
1628} else {
1629 print '<table id="tablelines" class="noborder noshadow postablelines centpercent">';
1630}
1631if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1632 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1633 print '<tr><td colspan="5">'.$sectionwithinvoicelink.'</td></tr>';
1634 } else {
1635 print '<tr><td colspan="4">'.$sectionwithinvoicelink.'</td></tr>';
1636 }
1637}
1638
1639// Show the list of selected product
1640if (!$usediv) {
1641 print '<tr class="liste_titre nodrag nodrop">';
1642 print '<td class="linecoldescription">';
1643}
1644// In phone version only show when it is invoice page
1645if (empty($mobilepage) || $mobilepage == "invoice") {
1646 print '<!-- hidden var used by some js functions -->';
1647 print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
1648 print '<input type="hidden" name="thirdpartyid" id="thirdpartyid" value="'.$invoice->socid.'">';
1649}
1650if (!$usediv) {
1651 if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1652 $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1653 $resql = $db->query($sql);
1654 $obj = $db->fetch_object($resql);
1655 if ($obj) {
1656 $label = $obj->label;
1657 $floor = $obj->floor;
1658 }
1659 if ($mobilepage == "invoice" || $mobilepage == "") {
1660 // If not on smartphone version or if it is the invoice page
1661 //print 'mobilepage='.$mobilepage;
1662 print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
1663 print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
1664 }
1665 }
1666 print '</td>';
1667}
1668
1669// Complete header by hook
1670$parameters=array();
1671$reshook=$hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1672if ($reshook < 0) {
1673 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1674}
1675print $hookmanager->resPrint;
1676
1677if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1678 print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
1679 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1680 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1681 print '<td class="linecolht right nowraponall">';
1682 print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1683 // In phone version only show when it is invoice page
1684 if (empty($mobilepage) || $mobilepage == "invoice") {
1685 print '<span id="linecolht-span-total" style="font-size:1.3em; font-weight: bold;">' . price($invoice->total_ht, 1, '', 1, -1, -1, $conf->currency) . '</span>';
1686 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1687 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1688 include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
1689 $multicurrency = new MultiCurrency($db);
1690 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1691 print '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">(' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
1692 }
1693 }
1694 print '</td>';
1695 }
1696 print '<td class="linecolht right nowraponall">';
1697 print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
1698 // In phone version only show when it is invoice page
1699 if (empty($mobilepage) || $mobilepage == "invoice") {
1700 print '<span id="linecolht-span-total" style="font-size:1.3em; font-weight: bold;">'.price($invoice->total_ttc, 1, '', 1, -1, -1, $conf->currency).'</span>';
1701 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1702 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1703 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1704 $multicurrency = new MultiCurrency($db);
1705 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1706 print '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($invoice->total_ttc * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
1707 }
1708 }
1709 print '</td>';
1710} elseif ($mobilepage == "invoice") {
1711 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1712}
1713if (!$usediv) {
1714 print "</tr>\n";
1715}
1716
1717if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1718 if ($mobilepage == "cats") {
1719 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1720 $categorie = new Categorie($db);
1721 $categories = $categorie->get_full_arbo('product');
1722 foreach ($categories as $row) {
1723 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1724 $htmlforlines .= '<div class="leftcat"';
1725 } else {
1726 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1727 }
1728 $htmlforlines .= ' onclick="LoadProducts('.$row['id'].');">';
1729 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1730 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
1731 } else {
1732 $htmlforlines .= '<td class="left">';
1733 }
1734 $htmlforlines .= $row['label'];
1735 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1736 $htmlforlines .= '</div>'."\n";
1737 } else {
1738 $htmlforlines .= '</td></tr>'."\n";
1739 }
1740 }
1741 print $htmlforlines;
1742 }
1743
1744 if ($mobilepage == "products") {
1745 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1746 $object = new Categorie($db);
1747 $catid = GETPOST('catid', 'int');
1748 $result = $object->fetch($catid);
1749 $prods = $object->getObjectsInCateg("product");
1750 $htmlforlines = '';
1751 foreach ($prods as $row) {
1752 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1753 $htmlforlines .= '<div class="leftcat"';
1754 } else {
1755 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1756 }
1757 $htmlforlines .= ' onclick="AddProduct(\''.$place.'\', '.$row->id.')"';
1758 $htmlforlines .= '>';
1759 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1760 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
1761 $htmlforlines .= $row->label.' '.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1762 $htmlforlines .= '</div>'."\n";
1763 } else {
1764 $htmlforlines .= '<td class="left">';
1765 $htmlforlines .= $row->label;
1766 $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
1767 $htmlforlines .= '</td>';
1768 $htmlforlines .= '</tr>'."\n";
1769 }
1770 }
1771 print $htmlforlines;
1772 }
1773
1774 if ($mobilepage == "places") {
1775 $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
1776 $resql = $db->query($sql);
1777 $rows = array();
1778 $htmlforlines = '';
1779 while ($row = $db->fetch_array($resql)) {
1780 $rows[] = $row;
1781 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1782 $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
1783 $htmlforlines .= '<td class="left">';
1784 $htmlforlines .= $row['label'];
1785 $htmlforlines .= '</td>';
1786 $htmlforlines .= '</tr>'."\n";
1787 }
1788 print $htmlforlines;
1789 }
1790}
1791
1792if ($placeid > 0) {
1793 //In Phone basic layout hide some content depends situation
1794 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1795 return;
1796 }
1797
1798 // Loop on each lines on invoice
1799 if (is_array($invoice->lines) && count($invoice->lines)) {
1800 print '<!-- invoice.php show lines of invoices -->'."\n";
1801 $tmplines = array_reverse($invoice->lines);
1802 $htmlsupplements = array();
1803 foreach ($tmplines as $line) {
1804 if ($line->fk_parent_line != false) {
1805 $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1806 if ($line->special_code == "4") {
1807 $htmlsupplements[$line->fk_parent_line] .= ' order';
1808 }
1809 $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'"';
1810 if ($line->special_code == "4") {
1811 $htmlsupplements[$line->fk_parent_line] .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1812 }
1813 $htmlsupplements[$line->fk_parent_line] .= '>';
1814 $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1815 $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1816 if ($line->product_label) {
1817 $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1818 }
1819 if ($line->product_label && $line->desc) {
1820 $htmlsupplements[$line->fk_parent_line] .= '<br>';
1821 }
1822 if ($line->product_label != $line->desc) {
1823 $firstline = dolGetFirstLineOfText($line->desc);
1824 if ($firstline != $line->desc) {
1825 $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1826 } else {
1827 $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1828 }
1829 }
1830 $htmlsupplements[$line->fk_parent_line] .= '</td>';
1831
1832 // complete line by hook
1833 $parameters=array('line' => $line);
1834 $reshook=$hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1835 if ($reshook < 0) {
1836 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1837 }
1838 $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1839
1840 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1841 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1842 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
1843 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
1844 }
1845 $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
1846 continue;
1847 }
1848 $htmlforlines = '';
1849
1850 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1851 if ($line->special_code == "4") {
1852 $htmlforlines .= ' order';
1853 }
1854 $htmlforlines .= '" id="'.$line->id.'"';
1855 if ($line->special_code == "4") {
1856 $htmlforlines .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1857 }
1858 $htmlforlines .= '>';
1859 $htmlforlines .= '<td class="left">';
1860 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1861 $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
1862 }
1863 if (isset($line->product_type)) {
1864 if (empty($line->product_type)) {
1865 $htmlforlines .= img_object('', 'product').' ';
1866 } else {
1867 $htmlforlines .= img_object('', 'service').' ';
1868 }
1869 }
1870 if (!getDolGlobalString('TAKEPOS_SHOW_N_FIRST_LINES')) {
1871 $tooltiptext = '';
1872 if ($line->product_ref) {
1873 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1874 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1875 if (!empty($line->batch)) {
1876 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1877 }
1878 if (!empty($line->fk_warehouse)) {
1879 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1880 }
1881 if ($line->product_label != $line->desc) {
1882 if ($line->desc) {
1883 $tooltiptext .= '<br>';
1884 }
1885 $tooltiptext .= $line->desc;
1886 }
1887 }
1888 if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
1889 $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1890 } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
1891 $htmlforlines .= $form->textwithpicto($line->product_ref ? '<b>'.$line->product_ref.'<b>' : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1892 } else {
1893 $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
1894 }
1895 } else {
1896 if ($line->product_label) {
1897 $htmlforlines .= $line->product_label;
1898 }
1899 if (!empty($line->batch)) {
1900 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1901 }
1902 if (!empty($line->fk_warehouse)) {
1903 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1904 }
1905
1906 if ($line->product_label != $line->desc) {
1907 if ($line->product_label && $line->desc) {
1908 $htmlforlines .= '<br>';
1909 }
1910 $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
1911 if ($firstline != $line->desc) {
1912 $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1913 } else {
1914 $htmlforlines .= $line->desc;
1915 }
1916 }
1917 }
1918 if (!empty($line->array_options['options_order_notes'])) {
1919 $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
1920 }
1921 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1922 $htmlforlines .= '</td><td class="right phonetable"><button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty - 1).');" class="publicphonebutton2 phonered">-</button>&nbsp;&nbsp;<button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty + 1).');" class="publicphonebutton2 phonegreen">+</button>';
1923 }
1924 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1925 $moreinfo = '';
1926 $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
1927 if ($line->vat_src_code) {
1928 $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
1929 }
1930 $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
1931 $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
1932 $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
1933 $moreinfo .= '<hr>';
1934 $moreinfo .= $langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
1935 //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
1936 if ($line->date_start || $line->date_end) {
1937 $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
1938 }
1939 $htmlforlines .= '</td>';
1940
1941 // complete line by hook
1942 $parameters=array('line' => $line);
1943 $reshook=$hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1944 if ($reshook < 0) {
1945 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1946 }
1947 $htmlforlines .= $hookmanager->resPrint;
1948
1949 $htmlforlines .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1950 $htmlforlines .= '<td class="right">';
1951 if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire')) {
1952 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1953 if (getDolGlobalString($constantforkey) && $line->fk_product > 0 && !getDolGlobalString('TAKEPOS_HIDE_STOCK_ON_LINE')) {
1954 $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
1955 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
1956 $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
1957 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
1958 $sql .= " WHERE ps.reel != 0";
1959 $sql .= " AND ps.fk_entrepot = ".((int) getDolGlobalString($constantforkey));
1960 $sql .= " AND e.entity IN (".getEntity('stock').")";
1961 $sql .= " AND ps.fk_product = ".((int) $line->fk_product);
1962 $resql = $db->query($sql);
1963 if ($resql) {
1964 $obj = $db->fetch_object($resql);
1965 if ($obj) {
1966 $stock_real = price2num($obj->reel, 'MS');
1967 } else {
1968 $stock_real = 0;
1969 }
1970 $htmlforlines .= $line->qty;
1971 if ($line->qty && $line->qty > $stock_real) {
1972 $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
1973 }
1974 $htmlforlines .= ' <span class="posstocktoolow">('.$langs->trans("Stock").' '.$stock_real.')</span>';
1975 if ($line->qty && $line->qty > $stock_real) {
1976 $htmlforlines .= "</span>";
1977 }
1978 } else {
1979 dol_print_error($db);
1980 }
1981 } else {
1982 $htmlforlines .= $line->qty;
1983 }
1984 } else {
1985 $htmlforlines .= $line->qty;
1986 }
1987
1988 $htmlforlines .= '</td>';
1989 if (getDolGlobalInt('TAKEPOS_SHOW_HT')) {
1990 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
1991 $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
1992 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1993 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1994 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1995 $multicurrency = new MultiCurrency($db);
1996 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1997 $htmlforlines .= '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($line->total_ht * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
1998 }
1999 $htmlforlines .= '</td>';
2000 }
2001 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
2002 $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
2003 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
2004 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
2005 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
2006 $multicurrency = new MultiCurrency($db);
2007 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
2008 $htmlforlines .= '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($line->total_ttc * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
2009 }
2010 $htmlforlines .= '</td>';
2011 }
2012 $htmlforlines .= '</tr>'."\n";
2013 $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
2014
2015 print $htmlforlines;
2016 }
2017 } else {
2018 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2019 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2020 print '<td></td><td></td>';
2021 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2022 print '<td></td>';
2023 }
2024 }
2025 print '</tr>';
2026 }
2027} else { // No invoice generated yet
2028 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2029 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2030 print '<td></td><td></td>';
2031 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2032 print '<td></td>';
2033 }
2034 }
2035 print '</tr>';
2036}
2037
2038if ($usediv) {
2039 print '</div>';
2040} else {
2041 print '</table>';
2042}
2043
2044if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE && !getDolGlobalString('TAKEPOS_NO_CREDITNOTE')) {
2045 print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
2046 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
2047 print ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
2048 }
2049}
2050
2051
2052if ($action == "search") {
2053 print '<center>
2054 <input type="text" id="search" class="input-nobottom" name="search" onkeyup="Search2(\'\', null);" style="width: 80%; font-size: 150%;" placeholder="'.dol_escape_htmltag($langs->trans('Search')).'">
2055 </center>';
2056}
2057
2058print '</div>';
2059
2060// llxFooter
2061if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
2062 print '</body></html>';
2063}
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Definition security.php:604
$object ref
Definition info.php:79
Class to manage members of a foundation.
const STATUS_EXCLUDED
Excluded.
Class to manage categories.
Class to manage warehouses.
const STATUS_CLOSED
Warehouse closed, inactive.
Class to manage invoices.
const STATUS_DRAFT
Draft status.
const TYPE_CREDIT_NOTE
Credit note invoice.
Class to manage generation of HTML components Only common components must be here.
Class to manage stock movements.
Class Currency.
Class to manage payments of customer invoices.
Class to manage products or services.
Manage record for batch number management.
const BATCH_RULE_SELLBY_EATBY_DATES_FIRST
Batches rules.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0)
Print formated error messages to output (Used to show messages on html output).
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
Definition invoice.php:1954
if(! $user->hasRight( 'takepos', 'run') &&!defined( 'INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) if((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT')==1 && $conf->browser->layout=='phone')||defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) if(empty( $_SESSION["takeposterminal"])) fail($message)
Abort invoice creationg with a given error message.
Definition invoice.php:107
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Ouput html header of a page.
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
ui dialog ui datepicker calendar ui widget content ui state ui datepicker calendar ui widget header ui state ui datepicker calendar ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:121
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
Contact()
Old copy.
Definition index.php:572