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