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