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 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
626 $invoice->date = dol_get_first_hour(dol_now('tzuserrel')); // Invoice::create() needs a date with no hours
627
628 $invoice->module_source = 'takepos';
629 $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
630 $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
631
632 if ($invoice->socid <= 0) {
633 $langs->load('errors');
634 dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1);
635 } else {
636 $db->begin();
637
638 // Create invoice
639 $placeid = $invoice->create($user);
640 if ($placeid < 0) {
641 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
642 }
643 $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid = ".((int) $placeid);
644 $resql = $db->query($sql);
645 if (!$resql) {
646 $error++;
647 }
648
649 if (!$error) {
650 $db->commit();
651 } else {
652 $db->rollback();
653 }
654 }
655 }
656
657 // If we add a line by click on product (invoice exists here because it was created juste before if it didn't exists)
658 if ($action == "addline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
659 $prod = new Product($db);
660 $prod->fetch($idproduct);
661
662 $customer = new Societe($db);
663 $customer->fetch($invoice->socid);
664
665 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
666
667 $qty = GETPOSTISSET('qty') ? GETPOSTINT('qty') : 1;
668 $price = $datapriceofproduct['pu_ht'];
669 $price_ttc = $datapriceofproduct['pu_ttc'];
670 //$price_min = $datapriceofproduct['price_min'];
671 $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
672 $tva_tx = $datapriceofproduct['tva_tx'];
673 $tva_npr = $datapriceofproduct['tva_npr'];
674
675 // Local Taxes
676 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
677 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
678
679
680 if (isModEnabled('productbatch') && isModEnabled('stock')) {
681 $batch = GETPOST('batch', 'alpha');
682
683 if (!empty($batch)) { // We have just clicked on a batch number, we will execute action=setbatch later...
684 $action = "setbatch";
685 } elseif ($prod->status_batch > 0) {
686 // If product need a lot/serial, we show the list of lot/serial available for the product...
687
688 // Set nb of suggested with nb of batch into the warehouse of the terminal
689 $nbofsuggested = 0;
690 $prod->load_stock('warehouseopen');
691
692 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
693 $warehouseid = getDolGlobalInt($constantforkey);
694
695 //var_dump($prod->stock_warehouse);
696 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
697 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
698 // Product to select is not on the warehouse configured for terminal, so we ignore this warehouse
699 continue;
700 }
701 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
702 if (is_object($prod->stock_warehouse[$tmpwarehouseid]) && count($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
703 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) {
704 $nbofsuggested++;
705 }
706 }
707 }
708 }
709 //var_dump($prod->stock_warehouse);
710
711 echo "<script>\n";
712 echo "function addbatch(batch, warehouseid) {\n";
713 echo "console.log('We add batch '+batch+' from warehouse id '+warehouseid);\n";
714 echo '$("#poslines").load("'.DOL_URL_ROOT.'/takepos/invoice.php?action=addline&batch="+encodeURI(batch)+"&warehouseid="+warehouseid+"&place='.$place.'&idproduct='.$idproduct.'&token='.newToken().'", function() {});'."\n";
715 echo "}\n";
716 echo "</script>\n";
717
718 $suggestednb = 1;
719 echo "<center>".$langs->trans("SearchIntoBatch").": <b> $nbofsuggested </b></center><br><table>";
720 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
721 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
722 // Not on the forced warehouse, so we ignore this warehouse
723 continue;
724 }
725 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
726 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) { // $dbatch is instance of Productbatch
727 $batchStock = + $dbatch->qty; // To get a numeric
728 $quantityToBeDelivered = 1;
729 $deliverableQty = min($quantityToBeDelivered, $batchStock);
730 print '<tr>';
731 print '<!-- subj='.$suggestednb.'/'.$nbofsuggested.' -->';
732 print '<!-- Show details of lot/serial in warehouseid='.$tmpwarehouseid.' -->';
733 print '<td class="left">';
734 $detail = '';
735 $detail .= '<span class="opacitymedium">'.$langs->trans("LotSerial").':</span> '.$dbatch->batch;
736 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
737 //$detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
738 }
739 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
740 //$detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
741 }
742 $detail .= '</td><td>';
743 $detail .= '<span class="opacitymedium">'.$langs->trans("Qty").':</span> '.$dbatch->qty;
744 $detail .= '</td><td>';
745 $detail .= ' <button class="marginleftonly" onclick="addbatch(\''.dol_escape_js($dbatch->batch).'\', '.$tmpwarehouseid.')">'.$langs->trans("Select")."</button>";
746 $detail .= '<br>';
747 print $detail;
748
749 $quantityToBeDelivered -= $deliverableQty;
750 if ($quantityToBeDelivered < 0) {
751 $quantityToBeDelivered = 0;
752 }
753 $suggestednb++;
754 print '</td></tr>';
755 }
756 }
757 }
758 print "</table>";
759
760 print '</body></html>';
761 exit;
762 }
763 }
764
765
766 if (getDolGlobalString('TAKEPOS_SUPPLEMENTS')) {
767 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
768 $cat = new Categorie($db);
769 $categories = $cat->containing($idproduct, 'product');
770 $found = (array_search(getDolGlobalInt('TAKEPOS_SUPPLEMENTS_CATEGORY'), array_column($categories, 'id')));
771 if ($found !== false) { // If this product is a supplement
772 $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid = ".((int) $selectedline);
773 $resql = $db->query($sql);
774 $row = $db->fetch_array($resql);
775 if ($row[0] == null) {
776 $parent_line = $selectedline;
777 } else {
778 $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product
779 }
780 }
781 }
782
783 $idoflineadded = 0;
784 $err = 0;
785 // Group if enabled. Skip group if line already sent to the printer
786 if (getDolGlobalString('TAKEPOS_GROUP_SAME_PRODUCT')) {
787 foreach ($invoice->lines as $line) {
788 if ($line->product_ref == $prod->ref) {
789 if ($line->special_code == 4) {
790 continue;
791 } // If this line is sended to printer create new line
792 // check if qty in stock
793 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && (($line->qty + $qty) > $prod->stock_reel)) {
794 $invoice->error = $langs->trans("ErrorStockIsNotEnough");
795 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
796 $err++;
797 break;
798 }
799 $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);
800 if ($result < 0) {
801 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
802 } else {
803 $idoflineadded = $line->id;
804 }
805 break;
806 }
807 }
808 }
809 if ($idoflineadded <= 0 && empty($err)) {
810 $invoice->fetch_thirdparty();
811 $array_options = array();
812
813 $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);
814
815 /* setup of margin calculation */
816 if (isset($conf->global->MARGIN_TYPE)) {
817 if (getDolGlobalString('MARGIN_TYPE') == 'pmp' && !empty($prod->pmp)) {
818 $line['fk_fournprice'] = null;
819 $line['pa_ht'] = $prod->pmp;
820 } elseif (getDolGlobalString('MARGIN_TYPE') == 'costprice' && !empty($prod->cost_price)) {
821 $line['fk_fournprice'] = null;
822 $line['pa_ht'] = $prod->cost_price;
823 } else {
824 // default is fournprice
825 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
826 $pf = new ProductFournisseur($db);
827 if ($pf->find_min_price_product_fournisseur($idproduct, $qty) > 0) {
828 $line['fk_fournprice'] = $pf->product_fourn_price_id;
829 $line['pa_ht'] = $pf->fourn_unitprice_with_discount;
830 if (getDolGlobalString('PRODUCT_CHARGES') && $pf->fourn_charges > 0) {
831 $line['pa_ht'] += $pf->fourn_charges / $pf->fourn_qty;
832 }
833 }
834 }
835 }
836
837 // complete line by hook
838 $parameters = array('prod' => $prod, 'line' => $line);
839 $reshook = $hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); // Note that $action and $line may have been modified by some hooks
840 if ($reshook < 0) {
841 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
842 }
843
844
845 if (empty($reshook)) {
846 if (!empty($hookmanager->resArray)) {
847 $line = $hookmanager->resArray;
848 }
849
850 // check if qty in stock
851 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && $qty > $prod->stock_reel) {
852 $invoice->error = $langs->trans("ErrorStockIsNotEnough");
853 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
854 $err++;
855 }
856
857 if (empty($err)) {
858 $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);
859 }
860 }
861
862 if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
863 $CUSTOMER_DISPLAY_line1 = $prod->label;
864 $CUSTOMER_DISPLAY_line2 = price($price_ttc);
865 }
866 }
867
868 $invoice->fetch($placeid);
869 }
870
871 // If we add a line by submitting freezone form (invoice exists here because it was created juste before if it didn't exists)
872 if ($action == "freezone" && $user->hasRight('takepos', 'run')) {
873 $customer = new Societe($db);
874 $customer->fetch($invoice->socid);
875
876 $tva_tx = GETPOST('tva_tx', 'alpha');
877 if ($tva_tx != '') {
878 if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
879 $tva_tx = price2num($tva_tx);
880 }
881 } else {
882 $tva_tx = get_default_tva($mysoc, $customer);
883 }
884
885 // Local Taxes
886 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
887 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
888
889 $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);
890 if ($res < 0) {
891 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
892 }
893 $invoice->fetch($placeid);
894 }
895
896 if ($action == "addnote" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
897 $desc = GETPOST('addnote', 'alpha');
898 if ($idline == 0) {
899 $invoice->update_note($desc, '_public');
900 } else {
901 foreach ($invoice->lines as $line) {
902 if ($line->id == $idline) {
903 $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);
904 }
905 }
906 }
907 $invoice->fetch($placeid);
908 }
909
910 if ($action == "deleteline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
911 /*
912 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
913 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
914 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
915 $permissiontoupdateline = true;
916 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
917 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
918 }
919 }*/
920
921 if ($idline > 0 && $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
922 $invoice->deleteLine($idline);
923 $invoice->fetch($placeid);
924 } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line.
925 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC";
926 $resql = $db->query($sql);
927 $row = $db->fetch_array($resql);
928 $deletelineid = $row[0];
929 $invoice->deleteLine($deletelineid);
930 $invoice->fetch($placeid);
931 }
932
933 if (count($invoice->lines) == 0) {
934 $invoice->delete($user);
935
936 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
937 header("Location: ".DOL_URL_ROOT."/takepos/public/auto_order.php");
938 } else {
939 header("Location: ".DOL_URL_ROOT."/takepos/invoice.php");
940 }
941 exit;
942 }
943 }
944
945 // Action to delete or discard an invoice
946 if ($action == "delete" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
947 // $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.
948 if ($placeid > 0) {
949 $result = $invoice->fetch($placeid);
950
951 if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) {
952 $db->begin();
953
954 // We delete the lines
955 $resdeletelines = 1;
956 foreach ($invoice->lines as $line) {
957 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
958 $tmpres = $invoice->deleteLine($line->id);
959 if ($tmpres < 0) {
960 $resdeletelines = 0;
961 break;
962 }
963 }
964
965 $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
966 $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
967 $sql .= " SET fk_soc = ".((int) getDolGlobalString($varforconst)).", ";
968 $sql .= " datec = '".$db->idate(dol_now())."'";
969 $sql .= " WHERE entity IN (".getEntity('invoice').")";
970 $sql .= " AND ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
971 $resql1 = $db->query($sql);
972
973 if ($resdeletelines && $resql1) {
974 $db->commit();
975 } else {
976 $db->rollback();
977 }
978
979 $invoice->fetch($placeid);
980 }
981 }
982 }
983
984 if ($action == "updateqty") { // Test on permission is done later
985 foreach ($invoice->lines as $line) {
986 if ($line->id == $idline) {
987 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
988 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
989 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
990 $permissiontoupdateline = true;
991 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
992 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
993 }
994 }
995 if (!$permissiontoupdateline) {
996 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateqty', null, 1);
997 } else {
998 $vatratecode = $line->tva_tx;
999 if ($line->vat_src_code) {
1000 $vatratecode .= ' ('.$line->vat_src_code.')';
1001 }
1002
1003 $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);
1004 }
1005 }
1006 }
1007
1008 $invoice->fetch($placeid);
1009 }
1010
1011 if ($action == "updateprice") { // Test on permission is done later
1012 $customer = new Societe($db);
1013 $customer->fetch($invoice->socid);
1014
1015 foreach ($invoice->lines as $line) {
1016 if ($line->id == $idline) {
1017 $prod = new Product($db);
1018 $prod->fetch($line->fk_product);
1019 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
1020 $price_min = $datapriceofproduct['price_min'];
1021 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
1022 $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
1023 //Check min price
1024 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) {
1025 $langs->load("products");
1026 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
1027 //echo $langs->trans("CantBeLessThanMinPrice");
1028 } else {
1029 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1030 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1031 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1032 $permissiontoupdateline = true;
1033 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1034 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
1035 }
1036 }
1037
1038 $vatratecode = $line->tva_tx;
1039 if ($line->vat_src_code) {
1040 $vatratecode .= ' ('.$line->vat_src_code.')';
1041 }
1042
1043 if (!$permissiontoupdateline) {
1044 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateprice', null, 1);
1045 } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) {
1046 $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);
1047 } else {
1048 $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);
1049 }
1050 }
1051 }
1052 }
1053
1054 // Reload data
1055 $invoice->fetch($placeid);
1056 }
1057
1058 if ($action == "updatereduction") { // Test on permission is done later
1059 $customer = new Societe($db);
1060 $customer->fetch($invoice->socid);
1061
1062 foreach ($invoice->lines as $line) {
1063 if ($line->id == $idline) {
1064 dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%');
1065
1066 $prod = new Product($db);
1067 $prod->fetch($line->fk_product);
1068
1069 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
1070 $price_min = $datapriceofproduct['price_min'];
1071 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
1072
1073 $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
1074
1075 // Check min price
1076 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) {
1077 $langs->load("products");
1078 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
1079 } else {
1080 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1081 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1082 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1083 $permissiontoupdateline = true;
1084 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1085 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
1086 }
1087 }
1088 if (!$permissiontoupdateline) {
1089 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
1090 } else {
1091 $vatratecode = $line->tva_tx;
1092 if ($line->vat_src_code) {
1093 $vatratecode .= ' ('.$line->vat_src_code.')';
1094 }
1095 $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);
1096 }
1097 }
1098 }
1099 }
1100
1101 // Reload data
1102 $invoice->fetch($placeid);
1103 } elseif ($action == 'update_reduction_global' && $user->hasRight('takepos', 'editlines')) {
1104 foreach ($invoice->lines as $line) {
1105 $vatratecode = $line->tva_tx;
1106 if ($line->vat_src_code) {
1107 $vatratecode .= ' ('.$line->vat_src_code.')';
1108 }
1109 $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);
1110 }
1111
1112 $invoice->fetch($placeid);
1113 }
1114
1115 if ($action == "setbatch" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1116 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1117 $warehouseid = (GETPOSTINT('warehouseid') > 0 ? GETPOSTINT('warehouseid') : getDolGlobalInt($constantforkey)); // Get the warehouse id from GETPOSTINT('warehouseid'), otherwise use default setup.
1118 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet SET batch = '".$db->escape($batch)."', fk_warehouse = ".((int) $warehouseid);
1119 $sql .= " WHERE rowid=".((int) $idoflineadded);
1120 $db->query($sql);
1121 }
1122
1123 if ($action == "order" && $placeid != 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1124 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1125 if ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1126 require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
1127 $printer = new dolReceiptPrinter($db);
1128 }
1129
1130 $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1131 $resql = $db->query($sql);
1132 $row = $db->fetch_object($resql);
1133 $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>';
1134 $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
1135 $order_receipt_printer1 = "";
1136 $order_receipt_printer2 = "";
1137 $order_receipt_printer3 = "";
1138 $catsprinter1 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_1'));
1139 $catsprinter2 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_2'));
1140 $catsprinter3 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_3'));
1141 $linestoprint = 0;
1142 foreach ($invoice->lines as $line) {
1143 if ($line->special_code == "4") {
1144 continue;
1145 }
1146 $c = new Categorie($db);
1147 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1148 $result = array_intersect($catsprinter1, $existing);
1149 $count = count($result);
1150 if (!$line->fk_product) {
1151 $count++; // Print Free-text item (Unassigned printer) to Printer 1
1152 }
1153 if ($count > 0) {
1154 $linestoprint++;
1155 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
1156 $db->query($sql);
1157 $order_receipt_printer1 .= '<tr><td class="left">';
1158 if ($line->fk_product) {
1159 $order_receipt_printer1 .= $line->product_label;
1160 } else {
1161 $order_receipt_printer1 .= $line->description;
1162 }
1163 $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
1164 if (!empty($line->array_options['options_order_notes'])) {
1165 $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
1166 }
1167 $order_receipt_printer1 .= '</td></tr>';
1168 }
1169 }
1170 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1171 $invoice->fetch($placeid); //Reload object before send to printer
1172 $printer->orderprinter = 1;
1173 echo "<script>";
1174 echo "var orderprinter1esc='";
1175 $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
1176 echo "';</script>";
1177 }
1178 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
1179 $db->query($sql);
1180 $invoice->fetch($placeid); //Reload object after set lines as printed
1181 $linestoprint = 0;
1182
1183 foreach ($invoice->lines as $line) {
1184 if ($line->special_code == "4") {
1185 continue;
1186 }
1187 $c = new Categorie($db);
1188 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1189 $result = array_intersect($catsprinter2, $existing);
1190 $count = count($result);
1191 if ($count > 0) {
1192 $linestoprint++;
1193 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
1194 $db->query($sql);
1195 $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1196 if (!empty($line->array_options['options_order_notes'])) {
1197 $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
1198 }
1199 $order_receipt_printer2 .= '</td></tr>';
1200 }
1201 }
1202 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1203 $invoice->fetch($placeid); //Reload object before send to printer
1204 $printer->orderprinter = 2;
1205 echo "<script>";
1206 echo "var orderprinter2esc='";
1207 $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
1208 echo "';</script>";
1209 }
1210 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
1211 $db->query($sql);
1212 $invoice->fetch($placeid); //Reload object after set lines as printed
1213 $linestoprint = 0;
1214
1215 foreach ($invoice->lines as $line) {
1216 if ($line->special_code == "4") {
1217 continue;
1218 }
1219 $c = new Categorie($db);
1220 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1221 $result = array_intersect($catsprinter3, $existing);
1222 $count = count($result);
1223 if ($count > 0) {
1224 $linestoprint++;
1225 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
1226 $db->query($sql);
1227 $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1228 if (!empty($line->array_options['options_order_notes'])) {
1229 $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
1230 }
1231 $order_receipt_printer3 .= '</td></tr>';
1232 }
1233 }
1234 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1235 $invoice->fetch($placeid); //Reload object before send to printer
1236 $printer->orderprinter = 3;
1237 echo "<script>";
1238 echo "var orderprinter3esc='";
1239 $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
1240 echo "';</script>";
1241 }
1242 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
1243 $db->query($sql);
1244 $invoice->fetch($placeid); //Reload object after set lines as printed
1245 }
1246
1247 $sectionwithinvoicelink = '';
1248 if (($action == "valid" || $action == "history" || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
1249 $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
1250 $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
1251 $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
1252 $remaintopay = $invoice->getRemainToPay();
1253 if ($remaintopay > 0) {
1254 $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
1255 } else {
1256 if ($invoice->paye) {
1257 $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">'.$langs->trans("Paid").'</span>';
1258 } else {
1259 $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
1260 }
1261 }
1262
1263 $sectionwithinvoicelink .= '</span><br>';
1264 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1265 $sectionwithinvoicelink .= ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
1266 } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1267 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1268 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1269 } else {
1270 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1271 }
1272 } elseif ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
1273 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1274 } else {
1275 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1276 if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
1277 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox('.$placeid.', \'without_details\')">'.$langs->trans('PrintWithoutDetails').'</button>';
1278 }
1279 if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
1280 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1)">'.$langs->trans('GiftReceipt').'</button>';
1281 }
1282 }
1283 if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && getDolGlobalInt('TAKEPOS_EMAIL_TEMPLATE_INVOICE') > 0) {
1284 $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.')">'.$langs->trans('SendTicket').'</button>';
1285 }
1286
1287 if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
1288 $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
1289 }
1290 }
1291}
1292
1293
1294/*
1295 * View
1296 */
1297
1298$form = new Form($db);
1299
1300// llxHeader
1301if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1302 $title = 'TakePOS - Dolibarr '.DOL_VERSION;
1303 if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
1304 $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
1305 }
1306 $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
1307 <meta name="apple-mobile-web-app-capable" content="yes">
1308 <meta name="mobile-web-app-capable" content="yes">
1309 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
1310 $arrayofcss = array(
1311 '/takepos/css/pos.css.php',
1312 );
1313 $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
1314 $disablejs = 0;
1315 $disablehead = 0;
1316 top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1317
1318 print '<body>'."\n";
1319} else {
1320 top_httphead('text/html', 1);
1321}
1322
1323?>
1324<!-- invoice.php -->
1325<script type="text/javascript">
1326var selectedline=0;
1327var selectedtext="";
1328<?php if ($action == "valid") {
1329 echo "var place=0;";
1330}?> // Set to default place after close sale
1331var placeid=<?php echo($placeid > 0 ? $placeid : 0); ?>;
1332$(document).ready(function() {
1333 var idoflineadded = <?php echo(empty($idoflineadded) ? 0 : $idoflineadded); ?>;
1334
1335 $('.posinvoiceline').click(function(){
1336 console.log("Click done on "+this.id);
1337 $('.posinvoiceline').removeClass("selected");
1338 $(this).addClass("selected");
1339 if (!this.id) {
1340 return;
1341 }
1342 if (selectedline == this.id) {
1343 return; // If is already selected
1344 } else {
1345 selectedline = this.id;
1346 }
1347 selectedtext=$('#'+selectedline).find("td:first").html();
1348 <?php
1349 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1350 print '$("#phonediv1").load("'.DOL_URL_ROOT.'/takepos/public/auto_order.php?action=editline&token='.newToken().'&placeid="+placeid+"&selectedline="+selectedline, function() {
1351 });';
1352 }
1353 ?>
1354 });
1355
1356 /* Autoselect the line */
1357 if (idoflineadded > 0)
1358 {
1359 console.log("Auto select "+idoflineadded);
1360 $('.posinvoiceline#'+idoflineadded).click();
1361 }
1362<?php
1363
1364if ($action == "order" && !empty($order_receipt_printer1)) {
1365 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1366 ?>
1367 $.ajax({
1368 type: "POST",
1369 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
1370 data: 'invoice='+orderprinter1esc
1371 });
1372 <?php
1373 } else {
1374 ?>
1375 $.ajax({
1376 type: "POST",
1377 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1378 data: '<?php
1379 print $headerorder.$order_receipt_printer1.$footerorder; ?>'
1380 });
1381 <?php
1382 }
1383}
1384
1385if ($action == "order" && !empty($order_receipt_printer2)) {
1386 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1387 ?>
1388 $.ajax({
1389 type: "POST",
1390 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
1391 data: 'invoice='+orderprinter2esc
1392 });
1393 <?php
1394 } else {
1395 ?>
1396 $.ajax({
1397 type: "POST",
1398 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
1399 data: '<?php
1400 print $headerorder.$order_receipt_printer2.$footerorder; ?>'
1401 });
1402 <?php
1403 }
1404}
1405
1406if ($action == "order" && !empty($order_receipt_printer3)) {
1407 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1408 ?>
1409 $.ajax({
1410 type: "POST",
1411 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
1412 data: 'invoice='+orderprinter3esc
1413 });
1414 <?php
1415 }
1416}
1417
1418// Set focus to search field
1419if ($action == "search" || $action == "valid") {
1420 ?>
1421 parent.ClearSearch(true);
1422 <?php
1423}
1424
1425
1426if ($action == "temp" && !empty($ticket_printer1)) {
1427 ?>
1428 $.ajax({
1429 type: "POST",
1430 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1431 data: '<?php
1432 print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
1433 });
1434 <?php
1435}
1436
1437if ($action == "search") {
1438 ?>
1439 $('#search').focus();
1440 <?php
1441}
1442
1443?>
1444
1445});
1446
1447function SendTicket(id)
1448{
1449 console.log("Open box to select the Print/Send form");
1450 $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1451 return true;
1452}
1453
1454function PrintBox(id, action) {
1455 console.log("Open box before printing");
1456 $.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"); ?>"});
1457 return true;
1458}
1459
1460function Print(id, gift){
1461 console.log("Call Print() to generate the receipt.");
1462 $.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")); ?>'});
1463 return true;
1464}
1465
1466function TakeposPrinting(id){
1467 var receipt;
1468 console.log("TakeposPrinting" + id);
1469 $.get("receipt.php?facid="+id, function(data, status) {
1470 receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1471 $.ajax({
1472 type: "POST",
1473 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1474 data: receipt
1475 });
1476 });
1477 return true;
1478}
1479
1480function TakeposConnector(id){
1481 console.log("TakeposConnector" + id);
1482 $.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) {
1483 $.ajax({
1484 type: "POST",
1485 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1486 data: 'invoice='+data
1487 });
1488 });
1489 return true;
1490}
1491
1492// Call the ajax to execute the print.
1493// With some external module another method may be called.
1494function DolibarrTakeposPrinting(id) {
1495 console.log("DolibarrTakeposPrinting Printing invoice ticket " + id);
1496 $.ajax({
1497 type: "GET",
1498 data: { token: '<?php echo currentToken(); ?>' },
1499 url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=printinvoiceticket&token='.newToken().'&term='.urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '').'&id='; ?>" + id,
1500
1501 });
1502 return true;
1503}
1504
1505// Call url to generate a credit note (with same lines) from existing invoice
1506function CreditNote() {
1507 $("#poslines").load("<?php print DOL_URL_ROOT; ?>/takepos/invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() { });
1508 return true;
1509}
1510
1511// Call url to add notes
1512function SetNote() {
1513 $("#poslines").load("<?php print DOL_URL_ROOT; ?>/takepos/invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1514 return true;
1515}
1516
1517
1518$( document ).ready(function() {
1519 console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
1520
1521 <?php
1522 $s = $langs->trans("Customer");
1523 if ($invoice->id > 0 && ($invoice->socid != getDolGlobalString($constforcompanyid))) {
1524 $s = $soc->name;
1525 if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT')) {
1526 $contactids = $invoice->getIdContact('external', 'BILLING');
1527 $contactid = $contactids[0];
1528 if ($contactid > 0) {
1529 $contact = new Contact($db);
1530 $contact->fetch($contactid);
1531 $s .= " - " . $contact->getFullName($langs);
1532 }
1533 }
1534 }
1535 ?>
1536
1537 $("#customerandsales").html('');
1538 $("#shoppingcart").html('');
1539
1540 <?php if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT') == 0) { ?>
1541 $("#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>');
1542 <?php } else { ?>
1543 $("#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>');
1544 <?php } ?>
1545
1546 <?php
1547 $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
1548 $sql .= " WHERE entity IN (".getEntity('invoice').")";
1549 if (!getDolGlobalString('TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED')) {
1550 // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1551 $sql .= " AND ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%'";
1552 } else {
1553 // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1554 $sql .= " AND pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
1555 $sql .= " AND module_source = 'takepos'";
1556 }
1557
1558 $sql .= $db->order('datec', 'ASC');
1559 $resql = $db->query($sql);
1560 if ($resql) {
1561 $max_sale = 0;
1562 while ($obj = $db->fetch_object($resql)) {
1563 echo '$("#shoppingcart").append(\'';
1564 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=\\\'';
1565 $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
1566 echo $num_sale;
1567 if (str_replace("-", "", $num_sale) > $max_sale) {
1568 $max_sale = str_replace("-", "", $num_sale);
1569 }
1570 echo '\\\'; invoiceid=\\\'';
1571 echo $obj->rowid;
1572 echo '\\\'; Refresh();">';
1573 if ($placeid == $obj->rowid) {
1574 echo '<span class="basketselected">';
1575 } else {
1576 echo '<span class="basketnotselected">';
1577 }
1578 echo '<span class="fa fa-shopping-cart paddingright"></span>'.dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1579 echo '</span>';
1580 echo '</a>\');';
1581 }
1582 echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1583 echo $max_sale + 1;
1584 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>\');';
1585 } else {
1586 dol_print_error($db);
1587 }
1588
1589 $s = '';
1590
1591 $idwarehouse = 0;
1592 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1593 if (isModEnabled('stock')) {
1594 if (getDolGlobalString($constantforkey) != "1") {
1595 $constantforkey = 'CASHDESK_ID_WAREHOUSE'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1596 $idwarehouse = getDolGlobalString($constantforkey);
1597 if ($idwarehouse > 0) {
1598 $s = '<span class="small">';
1599 $warehouse = new Entrepot($db);
1600 $warehouse->fetch($idwarehouse);
1601 $s .= '<span class="hideonsmartphone">'.$langs->trans("Warehouse").'<br></span>'.$warehouse->ref;
1602 if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1603 $s .= ' ('.$langs->trans("Closed").')';
1604 }
1605 $s .= '</span>';
1606 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1607 print '$("#infowarehouse").css("display", "inline-block");';
1608 } else {
1609 $s = '<span class="small hideonsmartphone">';
1610 $s .= $langs->trans("StockChangeDisabled").'<br>'.$langs->trans("NoWarehouseDefinedForTerminal");
1611 $s .= '</span>';
1612 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1613 if (!empty($conf->dol_optimize_smallscreen)) {
1614 print '$("#infowarehouse").css("display", "none");';
1615 }
1616 }
1617 } else {
1618 $s = '<span class="small hideonsmartphone">'.$langs->trans("StockChangeDisabled").'</span>';
1619 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1620 if (!empty($conf->dol_optimize_smallscreen)) {
1621 print '$("#infowarehouse").css("display", "none");';
1622 }
1623 }
1624 }
1625
1626
1627 // Module Adherent
1628 $s = '';
1629 if (isModEnabled('member') && $invoice->socid > 0 && $invoice->socid != getDolGlobalInt($constforcompanyid)) {
1630 $s = '<span class="small">';
1631 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1632 $langs->load("members");
1633 $s .= $langs->trans("Member").': ';
1634 $adh = new Adherent($db);
1635 $result = $adh->fetch('', '', $invoice->socid);
1636 if ($result > 0) {
1637 $adh->ref = $adh->getFullName($langs);
1638 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1639 $s .= "<s>";
1640 }
1641 $s .= $adh->getFullName($langs);
1642 $s .= ' - '.$adh->type;
1643 if ($adh->datefin) {
1644 $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
1645 if ($adh->hasDelay()) {
1646 $s .= " ".img_warning($langs->trans("Late"));
1647 }
1648 } else {
1649 $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
1650 if ($adh->statut > 0) {
1651 $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1652 }
1653 }
1654 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1655 $s .= "</s>";
1656 }
1657 } else {
1658 $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
1659 }
1660 $s .= '</span>';
1661 }
1662 ?>
1663 $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1664
1665});
1666
1667
1668<?php
1669if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
1670 echo "function CustomerDisplay(){";
1671 echo "var line1='".$CUSTOMER_DISPLAY_line1."'.substring(0,20);";
1672 echo "line1=line1.padEnd(20);";
1673 echo "var line2='".$CUSTOMER_DISPLAY_line2."'.substring(0,20);";
1674 echo "line2=line2.padEnd(20);";
1675 echo "$.ajax({
1676 type: 'GET',
1677 data: { text: line1+line2 },
1678 url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
1679 });";
1680 echo "}";
1681}
1682?>
1683
1684</script>
1685
1686<?php
1687// Add again js for footer because this content is injected into index.php page so all init
1688// for tooltip and other js beautifiers must be reexecuted too.
1689if (!empty($conf->use_javascript_ajax)) {
1690 print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1691 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
1692}
1693
1694$usediv = (GETPOST('format') == 'div');
1695
1696print '<!-- 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";
1697print '<div class="div-table-responsive-no-min invoice">';
1698if ($usediv) {
1699 print '<div id="tablelines">';
1700} else {
1701 print '<table id="tablelines" class="noborder noshadow postablelines centpercent">';
1702}
1703if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1704 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1705 print '<tr><td colspan="5">'.$sectionwithinvoicelink.'</td></tr>';
1706 } else {
1707 print '<tr><td colspan="4">'.$sectionwithinvoicelink.'</td></tr>';
1708 }
1709}
1710
1711// Show the list of selected product
1712if (!$usediv) {
1713 print '<tr class="liste_titre nodrag nodrop">';
1714 print '<td class="linecoldescription">';
1715}
1716// In phone version only show when it is invoice page
1717if (empty($mobilepage) || $mobilepage == "invoice") {
1718 print '<!-- hidden var used by some js functions -->';
1719 print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
1720 print '<input type="hidden" name="thirdpartyid" id="thirdpartyid" value="'.$invoice->socid.'">';
1721}
1722if (!$usediv) {
1723 if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1724 $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1725 $resql = $db->query($sql);
1726 $obj = $db->fetch_object($resql);
1727 if ($obj) {
1728 $label = $obj->label;
1729 $floor = $obj->floor;
1730 }
1731 if ($mobilepage == "invoice" || $mobilepage == "") {
1732 // If not on smartphone version or if it is the invoice page
1733 //print 'mobilepage='.$mobilepage;
1734 print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
1735 print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
1736 }
1737 }
1738 print '</td>';
1739}
1740
1741// Complete header by hook
1742$parameters = array();
1743$reshook = $hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1744if ($reshook < 0) {
1745 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1746}
1747print $hookmanager->resPrint;
1748
1749if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1750 if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
1751 print '<td class="linecolqty right">'.$langs->trans('PriceUHT').'</td>';
1752 }
1753 print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
1754 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1755 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1756 print '<td class="linecolht right nowraponall">';
1757 print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1758 // In phone version only show when it is invoice page
1759 if (empty($mobilepage) || $mobilepage == "invoice") {
1760 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>';
1761 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1762 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1763 include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
1764 $multicurrency = new MultiCurrency($db);
1765 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1766 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>';
1767 }
1768 }
1769 print '</td>';
1770 }
1771 print '<td class="linecolht right nowraponall">';
1772 print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
1773 // In phone version only show when it is invoice page
1774 if (empty($mobilepage) || $mobilepage == "invoice") {
1775 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>';
1776 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1777 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1778 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1779 $multicurrency = new MultiCurrency($db);
1780 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1781 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>';
1782 }
1783 }
1784 print '</td>';
1785} elseif ($mobilepage == "invoice") {
1786 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1787}
1788if (!$usediv) {
1789 print "</tr>\n";
1790}
1791
1792if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1793 if ($mobilepage == "cats") {
1794 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1795 $categorie = new Categorie($db);
1796 $categories = $categorie->get_full_arbo('product');
1797 $htmlforlines = '';
1798 foreach ($categories as $row) {
1799 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1800 $htmlforlines .= '<div class="leftcat"';
1801 } else {
1802 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1803 }
1804 $htmlforlines .= ' onclick="LoadProducts('.$row['id'].');">';
1805 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1806 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
1807 } else {
1808 $htmlforlines .= '<td class="left">';
1809 }
1810 $htmlforlines .= $row['label'];
1811 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1812 $htmlforlines .= '</div>'."\n";
1813 } else {
1814 $htmlforlines .= '</td></tr>'."\n";
1815 }
1816 }
1817 print $htmlforlines;
1818 }
1819
1820 if ($mobilepage == "products") {
1821 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1822 $object = new Categorie($db);
1823 $catid = GETPOSTINT('catid');
1824 $result = $object->fetch($catid);
1825 $prods = $object->getObjectsInCateg("product");
1826 $htmlforlines = '';
1827 foreach ($prods as $row) {
1828 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1829 $htmlforlines .= '<div class="leftcat"';
1830 } else {
1831 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1832 }
1833 $htmlforlines .= ' onclick="AddProduct(\''.$place.'\', '.$row->id.')"';
1834 $htmlforlines .= '>';
1835 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1836 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
1837 $htmlforlines .= $row->label.' '.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1838 $htmlforlines .= '</div>'."\n";
1839 } else {
1840 $htmlforlines .= '<td class="left">';
1841 $htmlforlines .= $row->label;
1842 $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
1843 $htmlforlines .= '</td>';
1844 $htmlforlines .= '</tr>'."\n";
1845 }
1846 }
1847 print $htmlforlines;
1848 }
1849
1850 if ($mobilepage == "places") {
1851 $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
1852 $resql = $db->query($sql);
1853 $rows = array();
1854 $htmlforlines = '';
1855 while ($row = $db->fetch_array($resql)) {
1856 $rows[] = $row;
1857 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1858 $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
1859 $htmlforlines .= '<td class="left">';
1860 $htmlforlines .= $row['label'];
1861 $htmlforlines .= '</td>';
1862 $htmlforlines .= '</tr>'."\n";
1863 }
1864 print $htmlforlines;
1865 }
1866}
1867
1868if ($placeid > 0) {
1869 //In Phone basic layout hide some content depends situation
1870 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1871 return;
1872 }
1873
1874 // Loop on each lines on invoice
1875 if (is_array($invoice->lines) && count($invoice->lines)) {
1876 print '<!-- invoice.php show lines of invoices -->'."\n";
1877 $tmplines = array_reverse($invoice->lines);
1878 $htmlsupplements = array();
1879 foreach ($tmplines as $line) {
1880 if ($line->fk_parent_line != false) {
1881 $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1882 if ($line->special_code == "4") {
1883 $htmlsupplements[$line->fk_parent_line] .= ' order';
1884 }
1885 $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'"';
1886 if ($line->special_code == "4") {
1887 $htmlsupplements[$line->fk_parent_line] .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1888 }
1889 $htmlsupplements[$line->fk_parent_line] .= '>';
1890 $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1891 $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1892 if ($line->product_label) {
1893 $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1894 }
1895 if ($line->product_label && $line->desc) {
1896 $htmlsupplements[$line->fk_parent_line] .= '<br>';
1897 }
1898 if ($line->product_label != $line->desc) {
1899 $firstline = dolGetFirstLineOfText($line->desc);
1900 if ($firstline != $line->desc) {
1901 $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1902 } else {
1903 $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1904 }
1905 }
1906 $htmlsupplements[$line->fk_parent_line] .= '</td>';
1907
1908 // complete line by hook
1909 $parameters = array('line' => $line);
1910 $reshook = $hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1911 if ($reshook < 0) {
1912 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1913 }
1914 $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1915
1916 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1917 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1918 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
1919 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
1920 }
1921 $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
1922 continue;
1923 }
1924 $htmlforlines = '';
1925
1926 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1927 if ($line->special_code == "4") {
1928 $htmlforlines .= ' order';
1929 }
1930 $htmlforlines .= '" id="'.$line->id.'"';
1931 if ($line->special_code == "4") {
1932 $htmlforlines .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1933 }
1934 $htmlforlines .= '>';
1935 $htmlforlines .= '<td class="left">';
1936 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1937 $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
1938 }
1939 if (isset($line->product_type)) {
1940 if (empty($line->product_type)) {
1941 $htmlforlines .= img_object('', 'product').' ';
1942 } else {
1943 $htmlforlines .= img_object('', 'service').' ';
1944 }
1945 }
1946 $tooltiptext = '';
1947 if (!getDolGlobalString('TAKEPOS_SHOW_N_FIRST_LINES')) {
1948 if ($line->product_ref) {
1949 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1950 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1951 if (!empty($line->batch)) {
1952 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1953 }
1954 if (!empty($line->fk_warehouse)) {
1955 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1956 }
1957 if ($line->product_label != $line->desc) {
1958 if ($line->desc) {
1959 $tooltiptext .= '<br>';
1960 }
1961 $tooltiptext .= $line->desc;
1962 }
1963 }
1964 if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
1965 $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1966 } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
1967 $htmlforlines .= $form->textwithpicto($line->product_ref ? '<b>'.$line->product_ref.'<b>' : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1968 } else {
1969 $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
1970 }
1971 } else {
1972 if ($line->product_ref) {
1973 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1974 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1975 }
1976 if (!empty($line->batch)) {
1977 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1978 }
1979 if (!empty($line->fk_warehouse)) {
1980 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1981 }
1982
1983 if ($line->product_label) {
1984 $htmlforlines .= $line->product_label;
1985 }
1986 if ($line->product_label != $line->desc) {
1987 if ($line->product_label && $line->desc) {
1988 $htmlforlines .= '<br>';
1989 }
1990 $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
1991 if ($firstline != $line->desc) {
1992 $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1993 } else {
1994 $htmlforlines .= $line->desc;
1995 }
1996 }
1997 }
1998 if (!empty($line->array_options['options_order_notes'])) {
1999 $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
2000 }
2001 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
2002 $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>';
2003 }
2004 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2005 $moreinfo = '';
2006 $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
2007 if ($line->vat_src_code) {
2008 $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
2009 }
2010 $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
2011 $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
2012 $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
2013 $moreinfo .= '<hr>';
2014 $moreinfo .= $langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
2015 //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
2016 if ($line->date_start || $line->date_end) {
2017 $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
2018 }
2019 $htmlforlines .= '</td>';
2020
2021 // complete line by hook
2022 $parameters = array('line' => $line);
2023 $reshook = $hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
2024 if ($reshook < 0) {
2025 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2026 }
2027 $htmlforlines .= $hookmanager->resPrint;
2028
2029 if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
2030 $htmlforlines .= '<td class="right">'.price($line->subprice).'</td>';
2031 }
2032 $htmlforlines .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
2033 $htmlforlines .= '<td class="right">';
2034 if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire')) {
2035 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
2036 if (getDolGlobalString($constantforkey) && $line->fk_product > 0 && !getDolGlobalString('TAKEPOS_HIDE_STOCK_ON_LINE')) {
2037 $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
2038 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
2039 $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
2040 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
2041 $sql .= " WHERE ps.reel != 0";
2042 $sql .= " AND ps.fk_entrepot = ".((int) getDolGlobalString($constantforkey));
2043 $sql .= " AND e.entity IN (".getEntity('stock').")";
2044 $sql .= " AND ps.fk_product = ".((int) $line->fk_product);
2045 $resql = $db->query($sql);
2046 if ($resql) {
2047 $stock_real = 0;
2048 $obj = $db->fetch_object($resql);
2049 if ($obj) {
2050 $stock_real = price2num($obj->reel, 'MS');
2051 }
2052 $htmlforlines .= $line->qty;
2053 $htmlforlines .= '&nbsp; ';
2054 $htmlforlines .= '<span class="opacitylow" title="'.$langs->trans("Stock").' '.price($stock_real, 1, '', 1, 0).'">';
2055 $htmlforlines .= '(';
2056 if ($line->qty && $line->qty > $stock_real) {
2057 $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
2058 }
2059 $htmlforlines .= img_picto('', 'stock', 'class="pictofixedwidth"').price($stock_real, 1, '', 1, 0);
2060 if ($line->qty && $line->qty > $stock_real) {
2061 $htmlforlines .= "</span>";
2062 }
2063 $htmlforlines .= ')';
2064 $htmlforlines .= '</span>';
2065 } else {
2066 dol_print_error($db);
2067 }
2068 } else {
2069 $htmlforlines .= $line->qty;
2070 }
2071 } else {
2072 $htmlforlines .= $line->qty;
2073 }
2074
2075 $htmlforlines .= '</td>';
2076 if (getDolGlobalInt('TAKEPOS_SHOW_HT')) {
2077 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
2078 $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
2079 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
2080 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
2081 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
2082 $multicurrency = new MultiCurrency($db);
2083 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
2084 $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>';
2085 }
2086 $htmlforlines .= '</td>';
2087 }
2088 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
2089 $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
2090 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
2091 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
2092 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
2093 $multicurrency = new MultiCurrency($db);
2094 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
2095 $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>';
2096 }
2097 $htmlforlines .= '</td>';
2098 }
2099 $htmlforlines .= '</tr>'."\n";
2100 $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
2101
2102 print $htmlforlines;
2103 }
2104 } else {
2105 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2106 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2107 print '<td></td><td></td>';
2108 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2109 print '<td></td>';
2110 }
2111 }
2112 print '</tr>';
2113 }
2114} else { // No invoice generated yet
2115 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2116 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2117 print '<td></td><td></td>';
2118 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2119 print '<td></td>';
2120 }
2121 }
2122 print '</tr>';
2123}
2124
2125if ($usediv) {
2126 print '</div>';
2127} else {
2128 print '</table>';
2129}
2130
2131if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE && !getDolGlobalString('TAKEPOS_NO_CREDITNOTE')) {
2132 print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
2133 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
2134 print ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
2135 }
2136}
2137
2138
2139if ($action == "search") {
2140 print '<center>
2141 <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')).'">
2142 </center>';
2143}
2144
2145print '</div>';
2146
2147// llxFooter
2148if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
2149 print '</body></html>';
2150}
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_get_first_hour($date, $gm='tzserver')
Return GMT time for first hour of a given GMT date (it removes hours, min and second part)
Definition date.lib.php:655
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:2037
if(empty( $takeposterminal)) fail($message)
Abort invoice creation with a given error message.
Definition invoice.php:114