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