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