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