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 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
904 }
905 }
906 }
907
908 $invoice->fetch($placeid);
909 }
910
911 if ($action == "updateprice") { // Test on permission is done later
912 $customer = new Societe($db);
913 $customer->fetch($invoice->socid);
914
915 foreach ($invoice->lines as $line) {
916 if ($line->id == $idline) {
917 $prod = new Product($db);
918 $prod->fetch($line->fk_product);
919 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
920 $price_min = $datapriceofproduct['price_min'];
921 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && empty($user->rights->produit->ignore_price_min_advance)) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
922 $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
923 //Check min price
924 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) {
925 $langs->load("products");
926 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
927 //echo $langs->trans("CantBeLessThanMinPrice");
928 } else {
929 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
930 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
931 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
932 $permissiontoupdateline = true;
933 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
934 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
935 }
936 }
937 if (!$permissiontoupdateline) {
938 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateprice', null, 1);
939 } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) {
940 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
941 } else {
942 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'TTC', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
943 }
944 }
945 }
946 }
947
948 // Reload data
949 $invoice->fetch($placeid);
950 }
951
952 if ($action == "updatereduction") { // Test on permission is done later
953 $customer = new Societe($db);
954 $customer->fetch($invoice->socid);
955
956 foreach ($invoice->lines as $line) {
957 if ($line->id == $idline) {
958 dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%');
959
960 $prod = new Product($db);
961 $prod->fetch($line->fk_product);
962
963 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
964 $price_min = $datapriceofproduct['price_min'];
965 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && empty($user->rights->produit->ignore_price_min_advance)) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
966
967 $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
968
969 // Check min price
970 if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) {
971 $langs->load("products");
972 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
973 } else {
974 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
975 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
976 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
977 $permissiontoupdateline = true;
978 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
979 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
980 }
981 }
982 if (!$permissiontoupdateline) {
983 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
984 } else {
985 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
986 }
987 }
988 }
989 }
990
991 // Reload data
992 $invoice->fetch($placeid);
993 } elseif ($action == 'update_reduction_global' && $user->hasRight('takepos', 'editlines')) {
994 foreach ($invoice->lines as $line) {
995 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
996 }
997
998 $invoice->fetch($placeid);
999 }
1000
1001 if ($action=="setbatch" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1002 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1003 $warehouseid = getDolGlobalInt($constantforkey); // TODO Get the wrehouse id from GETPOSTINT('warehouseid');
1004 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet SET batch = '".$db->escape($batch)."', fk_warehouse = ".((int) $warehouseid);
1005 $sql .= " WHERE rowid=".((int) $idoflineadded);
1006 $db->query($sql);
1007 }
1008
1009 if ($action == "order" && $placeid != 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1010 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1011 if ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1012 require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
1013 $printer = new dolReceiptPrinter($db);
1014 }
1015
1016 $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1017 $resql = $db->query($sql);
1018 $row = $db->fetch_object($resql);
1019 $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>';
1020 $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
1021 $order_receipt_printer1 = "";
1022 $order_receipt_printer2 = "";
1023 $order_receipt_printer3 = "";
1024 $catsprinter1 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_1'));
1025 $catsprinter2 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_2'));
1026 $catsprinter3 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_3'));
1027 $linestoprint = 0;
1028 foreach ($invoice->lines as $line) {
1029 if ($line->special_code == "4") {
1030 continue;
1031 }
1032 $c = new Categorie($db);
1033 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1034 $result = array_intersect($catsprinter1, $existing);
1035 $count = count($result);
1036 if (!$line->fk_product) {
1037 $count++; // Print Free-text item (Unassigned printer) to Printer 1
1038 }
1039 if ($count > 0) {
1040 $linestoprint++;
1041 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
1042 $db->query($sql);
1043 $order_receipt_printer1 .= '<tr><td class="left">';
1044 if ($line->fk_product) {
1045 $order_receipt_printer1 .= $line->product_label;
1046 } else {
1047 $order_receipt_printer1 .= $line->description;
1048 }
1049 $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
1050 if (!empty($line->array_options['options_order_notes'])) {
1051 $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
1052 }
1053 $order_receipt_printer1 .= '</td></tr>';
1054 }
1055 }
1056 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1057 $invoice->fetch($placeid); //Reload object before send to printer
1058 $printer->orderprinter = 1;
1059 echo "<script>";
1060 echo "var orderprinter1esc='";
1061 $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
1062 echo "';</script>";
1063 }
1064 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
1065 $db->query($sql);
1066 $invoice->fetch($placeid); //Reload object after set lines as printed
1067 $linestoprint = 0;
1068
1069 foreach ($invoice->lines as $line) {
1070 if ($line->special_code == "4") {
1071 continue;
1072 }
1073 $c = new Categorie($db);
1074 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1075 $result = array_intersect($catsprinter2, $existing);
1076 $count = count($result);
1077 if ($count > 0) {
1078 $linestoprint++;
1079 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
1080 $db->query($sql);
1081 $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1082 if (!empty($line->array_options['options_order_notes'])) {
1083 $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
1084 }
1085 $order_receipt_printer2 .= '</td></tr>';
1086 }
1087 }
1088 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1089 $invoice->fetch($placeid); //Reload object before send to printer
1090 $printer->orderprinter = 2;
1091 echo "<script>";
1092 echo "var orderprinter2esc='";
1093 $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
1094 echo "';</script>";
1095 }
1096 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
1097 $db->query($sql);
1098 $invoice->fetch($placeid); //Reload object after set lines as printed
1099 $linestoprint = 0;
1100
1101 foreach ($invoice->lines as $line) {
1102 if ($line->special_code == "4") {
1103 continue;
1104 }
1105 $c = new Categorie($db);
1106 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1107 $result = array_intersect($catsprinter3, $existing);
1108 $count = count($result);
1109 if ($count > 0) {
1110 $linestoprint++;
1111 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
1112 $db->query($sql);
1113 $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1114 if (!empty($line->array_options['options_order_notes'])) {
1115 $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
1116 }
1117 $order_receipt_printer3 .= '</td></tr>';
1118 }
1119 }
1120 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1121 $invoice->fetch($placeid); //Reload object before send to printer
1122 $printer->orderprinter = 3;
1123 echo "<script>";
1124 echo "var orderprinter3esc='";
1125 $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
1126 echo "';</script>";
1127 }
1128 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
1129 $db->query($sql);
1130 $invoice->fetch($placeid); //Reload object after set lines as printed
1131 }
1132
1133 $sectionwithinvoicelink = '';
1134 if (($action == "valid" || $action == "history" || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
1135 $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
1136 $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
1137 $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
1138 $remaintopay = $invoice->getRemainToPay();
1139 if ($remaintopay > 0) {
1140 $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
1141 } else {
1142 if ($invoice->paye) {
1143 $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">'.$langs->trans("Paid").'</span>';
1144 } else {
1145 $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
1146 }
1147 }
1148
1149 $sectionwithinvoicelink .= '</span><br>';
1150 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1151 $sectionwithinvoicelink .= ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
1152 } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1153 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1154 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1155 } else {
1156 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1157 }
1158 } elseif ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
1159 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1160 } else {
1161 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1162 if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
1163 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox('.$placeid.', \'without_details\')">'.$langs->trans('PrintWithoutDetails').'</button>';
1164 }
1165 if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
1166 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1)">'.$langs->trans('GiftReceipt').'</button>';
1167 }
1168 }
1169 if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && getDolGlobalInt('TAKEPOS_EMAIL_TEMPLATE_INVOICE') > 0) {
1170 $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.')">'.$langs->trans('SendTicket').'</button>';
1171 }
1172
1173 if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
1174 $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
1175 }
1176 }
1177}
1178
1179
1180/*
1181 * View
1182 */
1183
1184$form = new Form($db);
1185
1186// llxHeader
1187if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1188 $title = 'TakePOS - Dolibarr '.DOL_VERSION;
1189 if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
1190 $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
1191 }
1192 $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
1193 <meta name="apple-mobile-web-app-capable" content="yes">
1194 <meta name="mobile-web-app-capable" content="yes">
1195 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
1196 $arrayofcss = array(
1197 '/takepos/css/pos.css.php',
1198 );
1199 $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
1200 $disablejs = 0;
1201 $disablehead = 0;
1202 top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1203
1204 print '<body>'."\n";
1205} else {
1206 top_httphead('text/html', 1);
1207}
1208
1209?>
1210<!-- invoice.php -->
1211<script type="text/javascript">
1212var selectedline=0;
1213var selectedtext="";
1214<?php if ($action=="valid") {
1215 echo "var place=0;";
1216}?> // Set to default place after close sale
1217var placeid=<?php echo($placeid > 0 ? $placeid : 0); ?>;
1218$(document).ready(function() {
1219 var idoflineadded = <?php echo(empty($idoflineadded) ? 0 : $idoflineadded); ?>;
1220
1221 $('.posinvoiceline').click(function(){
1222 console.log("Click done on "+this.id);
1223 $('.posinvoiceline').removeClass("selected");
1224 $(this).addClass("selected");
1225 if (!this.id) {
1226 return;
1227 }
1228 if (selectedline == this.id) {
1229 return; // If is already selected
1230 } else {
1231 selectedline = this.id;
1232 }
1233 selectedtext=$('#'+selectedline).find("td:first").html();
1234 <?php
1235 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1236 print '$("#phonediv1").load("'.DOL_URL_ROOT.'/takepos/public/auto_order.php?action=editline&token='.newToken().'&placeid="+placeid+"&selectedline="+selectedline, function() {
1237 });';
1238 }
1239 ?>
1240 });
1241
1242 /* Autoselect the line */
1243 if (idoflineadded > 0)
1244 {
1245 console.log("Auto select "+idoflineadded);
1246 $('.posinvoiceline#'+idoflineadded).click();
1247 }
1248<?php
1249
1250if ($action == "order" && !empty($order_receipt_printer1)) {
1251 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1252 ?>
1253 $.ajax({
1254 type: "POST",
1255 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
1256 data: 'invoice='+orderprinter1esc
1257 });
1258 <?php
1259 } else {
1260 ?>
1261 $.ajax({
1262 type: "POST",
1263 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1264 data: '<?php
1265 print $headerorder.$order_receipt_printer1.$footerorder; ?>'
1266 });
1267 <?php
1268 }
1269}
1270
1271if ($action == "order" && !empty($order_receipt_printer2)) {
1272 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1273 ?>
1274 $.ajax({
1275 type: "POST",
1276 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
1277 data: 'invoice='+orderprinter2esc
1278 });
1279 <?php
1280 } else {
1281 ?>
1282 $.ajax({
1283 type: "POST",
1284 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
1285 data: '<?php
1286 print $headerorder.$order_receipt_printer2.$footerorder; ?>'
1287 });
1288 <?php
1289 }
1290}
1291
1292if ($action == "order" && !empty($order_receipt_printer3)) {
1293 if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1294 ?>
1295 $.ajax({
1296 type: "POST",
1297 url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
1298 data: 'invoice='+orderprinter3esc
1299 });
1300 <?php
1301 }
1302}
1303
1304// Set focus to search field
1305if ($action == "search" || $action == "valid") {
1306 ?>
1307 parent.setFocusOnSearchField();
1308 <?php
1309}
1310
1311
1312if ($action == "temp" && !empty($ticket_printer1)) {
1313 ?>
1314 $.ajax({
1315 type: "POST",
1316 url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1317 data: '<?php
1318 print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
1319 });
1320 <?php
1321}
1322
1323if ($action == "search") {
1324 ?>
1325 $('#search').focus();
1326 <?php
1327}
1328
1329?>
1330
1331});
1332
1333function SendTicket(id)
1334{
1335 console.log("Open box to select the Print/Send form");
1336 $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1337 return true;
1338}
1339
1340function PrintBox(id, action) {
1341 console.log("Open box before printing");
1342 $.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"); ?>"});
1343 return true;
1344}
1345
1346function Print(id, gift){
1347 console.log("Call Print() to generate the receipt.");
1348 $.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")); ?>'});
1349 return true;
1350}
1351
1352function TakeposPrinting(id){
1353 var receipt;
1354 console.log("TakeposPrinting" + id);
1355 $.get("receipt.php?facid="+id, function(data, status) {
1356 receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1357 $.ajax({
1358 type: "POST",
1359 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1360 data: receipt
1361 });
1362 });
1363 return true;
1364}
1365
1366function TakeposConnector(id){
1367 console.log("TakeposConnector" + id);
1368 $.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) {
1369 $.ajax({
1370 type: "POST",
1371 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1372 data: 'invoice='+data
1373 });
1374 });
1375 return true;
1376}
1377
1378function DolibarrTakeposPrinting(id) {
1379 console.log("DolibarrTakeposPrinting Printing invoice ticket " + id)
1380 $.ajax({
1381 type: "GET",
1382 data: { token: '<?php echo currentToken(); ?>' },
1383 url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=printinvoiceticket&token='.newToken().'&term='.urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '').'&id='; ?>" + id,
1384 });
1385 return true;
1386}
1387
1388function CreditNote() {
1389 $("#poslines").load("invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() { });
1390 return true;
1391}
1392
1393function SetNote() {
1394 $("#poslines").load("invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1395 return true;
1396}
1397
1398
1399$( document ).ready(function() {
1400 console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
1401
1402 <?php
1403 $s = $langs->trans("Customer");
1404 if ($invoice->id > 0 && ($invoice->socid != getDolGlobalString($constforcompanyid))) {
1405 $s = $soc->name;
1406 if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT')) {
1407 $contactids = $invoice->getIdContact('external', 'BILLING');
1408 $contactid = $contactids[0];
1409 if ($contactid > 0) {
1410 $contact = new Contact($db);
1411 $contact->fetch($contactid);
1412 $s .= " - " . $contact->getFullName($langs);
1413 }
1414 }
1415 }
1416 ?>
1417
1418 $("#customerandsales").html('');
1419 $("#shoppingcart").html('');
1420
1421 <?php if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT') == 0) { ?>
1422 $("#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>');
1423 <?php } else { ?>
1424 $("#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>');
1425 <?php } ?>
1426
1427 <?php
1428 $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
1429 $sql .= " WHERE entity IN (".getEntity('invoice').")";
1430 if (!getDolGlobalString('TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED')) {
1431 // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1432 $sql .= " AND ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%'";
1433 } else {
1434 // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1435 $sql .= " AND pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
1436 $sql .= " AND module_source = 'takepos'";
1437 }
1438
1439 $sql .= $db->order('datec', 'ASC');
1440 $resql = $db->query($sql);
1441 if ($resql) {
1442 $max_sale = 0;
1443 while ($obj = $db->fetch_object($resql)) {
1444 echo '$("#shoppingcart").append(\'';
1445 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=\\\'';
1446 $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
1447 echo $num_sale;
1448 if (str_replace("-", "", $num_sale) > $max_sale) {
1449 $max_sale = str_replace("-", "", $num_sale);
1450 }
1451 echo '\\\'; invoiceid=\\\'';
1452 echo $obj->rowid;
1453 echo '\\\'; Refresh();">';
1454 if ($placeid == $obj->rowid) {
1455 echo '<span class="basketselected">';
1456 } else {
1457 echo '<span class="basketnotselected">';
1458 }
1459 echo '<span class="fa fa-shopping-cart paddingright"></span>'.dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1460 echo '</span>';
1461 echo '</a>\');';
1462 }
1463 echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1464 echo $max_sale + 1;
1465 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>\');';
1466 } else {
1467 dol_print_error($db);
1468 }
1469
1470 $s = '';
1471
1472 $idwarehouse = 0;
1473 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1474 if (isModEnabled('stock')) {
1475 if (getDolGlobalString($constantforkey) != "1") {
1476 $constantforkey = 'CASHDESK_ID_WAREHOUSE'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1477 $idwarehouse = getDolGlobalString($constantforkey);
1478 if ($idwarehouse > 0) {
1479 $s = '<span class="small">';
1480 $warehouse = new Entrepot($db);
1481 $warehouse->fetch($idwarehouse);
1482 $s .= '<span class="hideonsmartphone">'.$langs->trans("Warehouse").'<br></span>'.$warehouse->ref;
1483 if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1484 $s .= ' ('.$langs->trans("Closed").')';
1485 }
1486 $s .= '</span>';
1487 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1488 print '$("#infowarehouse").css("display", "inline-block");';
1489 } else {
1490 $s = '<span class="small hideonsmartphone">';
1491 $s .= $langs->trans("StockChangeDisabled").'<br>'.$langs->trans("NoWarehouseDefinedForTerminal");
1492 $s .= '</span>';
1493 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1494 if (!empty($conf->dol_optimize_smallscreen)) {
1495 print '$("#infowarehouse").css("display", "none");';
1496 }
1497 }
1498 } else {
1499 $s = '<span class="small hideonsmartphone">'.$langs->trans("StockChangeDisabled").'</span>';
1500 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1501 if (!empty($conf->dol_optimize_smallscreen)) {
1502 print '$("#infowarehouse").css("display", "none");';
1503 }
1504 }
1505 }
1506
1507
1508 // Module Adherent
1509 $s = '';
1510 if (isModEnabled('adherent') && $invoice->socid > 0 && $invoice->socid != getDolGlobalInt($constforcompanyid)) {
1511 $s = '<span class="small">';
1512 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1513 $langs->load("members");
1514 $s .= $langs->trans("Member").': ';
1515 $adh = new Adherent($db);
1516 $result = $adh->fetch('', '', $invoice->socid);
1517 if ($result > 0) {
1518 $adh->ref = $adh->getFullName($langs);
1519 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1520 $s .= "<s>";
1521 }
1522 $s .= $adh->getFullName($langs);
1523 $s .= ' - '.$adh->type;
1524 if ($adh->datefin) {
1525 $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
1526 if ($adh->hasDelay()) {
1527 $s .= " ".img_warning($langs->trans("Late"));
1528 }
1529 } else {
1530 $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
1531 if ($adh->statut > 0) {
1532 $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1533 }
1534 }
1535 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1536 $s .= "</s>";
1537 }
1538 } else {
1539 $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
1540 }
1541 $s .= '</span>';
1542 }
1543 ?>
1544 $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1545
1546});
1547
1548
1549<?php
1550if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
1551 echo "function CustomerDisplay(){";
1552 echo "var line1='".$CUSTOMER_DISPLAY_line1."'.substring(0,20);";
1553 echo "line1=line1.padEnd(20);";
1554 echo "var line2='".$CUSTOMER_DISPLAY_line2."'.substring(0,20);";
1555 echo "line2=line2.padEnd(20);";
1556 echo "$.ajax({
1557 type: 'GET',
1558 data: { text: line1+line2 },
1559 url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
1560 });";
1561 echo "}";
1562}
1563?>
1564
1565</script>
1566
1567<?php
1568// Add again js for footer because this content is injected into index.php page so all init
1569// for tooltip and other js beautifiers must be reexecuted too.
1570if (!empty($conf->use_javascript_ajax)) {
1571 print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1572 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
1573}
1574
1575$usediv = (GETPOST('format') == 'div');
1576
1577print '<!-- 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";
1578print '<div class="div-table-responsive-no-min invoice">';
1579if ($usediv) {
1580 print '<div id="tablelines">';
1581} else {
1582 print '<table id="tablelines" class="noborder noshadow postablelines centpercent">';
1583}
1584if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1585 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1586 print '<tr><td colspan="5">'.$sectionwithinvoicelink.'</td></tr>';
1587 } else {
1588 print '<tr><td colspan="4">'.$sectionwithinvoicelink.'</td></tr>';
1589 }
1590}
1591
1592// Show the list of selected product
1593if (!$usediv) {
1594 print '<tr class="liste_titre nodrag nodrop">';
1595 print '<td class="linecoldescription">';
1596}
1597// In phone version only show when it is invoice page
1598if (empty($mobilepage) || $mobilepage == "invoice") {
1599 print '<!-- hidden var used by some js functions -->';
1600 print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
1601 print '<input type="hidden" name="thirdpartyid" id="thirdpartyid" value="'.$invoice->socid.'">';
1602}
1603if (!$usediv) {
1604 if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1605 $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1606 $resql = $db->query($sql);
1607 $obj = $db->fetch_object($resql);
1608 if ($obj) {
1609 $label = $obj->label;
1610 $floor = $obj->floor;
1611 }
1612 if ($mobilepage == "invoice" || $mobilepage == "") {
1613 // If not on smartphone version or if it is the invoice page
1614 //print 'mobilepage='.$mobilepage;
1615 print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
1616 print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
1617 }
1618 }
1619 print '</td>';
1620}
1621
1622// Complete header by hook
1623$parameters=array();
1624$reshook=$hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1625if ($reshook < 0) {
1626 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1627}
1628print $hookmanager->resPrint;
1629
1630if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1631 print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
1632 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1633 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1634 print '<td class="linecolht right nowraponall">';
1635 print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1636 // In phone version only show when it is invoice page
1637 if (empty($mobilepage) || $mobilepage == "invoice") {
1638 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>';
1639 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1640 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1641 include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
1642 $multicurrency = new MultiCurrency($db);
1643 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1644 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>';
1645 }
1646 }
1647 print '</td>';
1648 }
1649 print '<td class="linecolht right nowraponall">';
1650 print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
1651 // In phone version only show when it is invoice page
1652 if (empty($mobilepage) || $mobilepage == "invoice") {
1653 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>';
1654 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1655 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1656 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1657 $multicurrency = new MultiCurrency($db);
1658 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1659 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>';
1660 }
1661 }
1662 print '</td>';
1663} elseif ($mobilepage == "invoice") {
1664 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1665}
1666if (!$usediv) {
1667 print "</tr>\n";
1668}
1669
1670if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1671 if ($mobilepage == "cats") {
1672 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1673 $categorie = new Categorie($db);
1674 $categories = $categorie->get_full_arbo('product');
1675 foreach ($categories as $row) {
1676 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1677 $htmlforlines .= '<div class="leftcat"';
1678 } else {
1679 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1680 }
1681 $htmlforlines .= ' onclick="LoadProducts('.$row['id'].');">';
1682 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1683 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
1684 } else {
1685 $htmlforlines .= '<td class="left">';
1686 }
1687 $htmlforlines .= $row['label'];
1688 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1689 $htmlforlines .= '</div>'."\n";
1690 } else {
1691 $htmlforlines .= '</td></tr>'."\n";
1692 }
1693 }
1694 print $htmlforlines;
1695 }
1696
1697 if ($mobilepage == "products") {
1698 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1699 $object = new Categorie($db);
1700 $catid = GETPOST('catid', 'int');
1701 $result = $object->fetch($catid);
1702 $prods = $object->getObjectsInCateg("product");
1703 $htmlforlines = '';
1704 foreach ($prods as $row) {
1705 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1706 $htmlforlines .= '<div class="leftcat"';
1707 } else {
1708 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1709 }
1710 $htmlforlines .= ' onclick="AddProduct(\''.$place.'\', '.$row->id.')"';
1711 $htmlforlines .= '>';
1712 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1713 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
1714 $htmlforlines .= $row->label.' '.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1715 $htmlforlines .= '</div>'."\n";
1716 } else {
1717 $htmlforlines .= '<td class="left">';
1718 $htmlforlines .= $row->label;
1719 $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
1720 $htmlforlines .= '</td>';
1721 $htmlforlines .= '</tr>'."\n";
1722 }
1723 }
1724 print $htmlforlines;
1725 }
1726
1727 if ($mobilepage == "places") {
1728 $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
1729 $resql = $db->query($sql);
1730 $rows = array();
1731 $htmlforlines = '';
1732 while ($row = $db->fetch_array($resql)) {
1733 $rows[] = $row;
1734 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1735 $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
1736 $htmlforlines .= '<td class="left">';
1737 $htmlforlines .= $row['label'];
1738 $htmlforlines .= '</td>';
1739 $htmlforlines .= '</tr>'."\n";
1740 }
1741 print $htmlforlines;
1742 }
1743}
1744
1745if ($placeid > 0) {
1746 //In Phone basic layout hide some content depends situation
1747 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1748 return;
1749 }
1750
1751 // Loop on each lines on invoice
1752 if (is_array($invoice->lines) && count($invoice->lines)) {
1753 print '<!-- invoice.php show lines of invoices -->'."\n";
1754 $tmplines = array_reverse($invoice->lines);
1755 $htmlsupplements = array();
1756 foreach ($tmplines as $line) {
1757 if ($line->fk_parent_line != false) {
1758 $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1759 if ($line->special_code == "4") {
1760 $htmlsupplements[$line->fk_parent_line] .= ' order';
1761 }
1762 $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'"';
1763 if ($line->special_code == "4") {
1764 $htmlsupplements[$line->fk_parent_line] .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1765 }
1766 $htmlsupplements[$line->fk_parent_line] .= '>';
1767 $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1768 $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1769 if ($line->product_label) {
1770 $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1771 }
1772 if ($line->product_label && $line->desc) {
1773 $htmlsupplements[$line->fk_parent_line] .= '<br>';
1774 }
1775 if ($line->product_label != $line->desc) {
1776 $firstline = dolGetFirstLineOfText($line->desc);
1777 if ($firstline != $line->desc) {
1778 $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1779 } else {
1780 $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1781 }
1782 }
1783 $htmlsupplements[$line->fk_parent_line] .= '</td>';
1784
1785 // complete line by hook
1786 $parameters=array('line' => $line);
1787 $reshook=$hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1788 if ($reshook < 0) {
1789 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1790 }
1791 $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1792
1793 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1794 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1795 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
1796 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
1797 }
1798 $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
1799 continue;
1800 }
1801 $htmlforlines = '';
1802
1803 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1804 if ($line->special_code == "4") {
1805 $htmlforlines .= ' order';
1806 }
1807 $htmlforlines .= '" id="'.$line->id.'"';
1808 if ($line->special_code == "4") {
1809 $htmlforlines .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1810 }
1811 $htmlforlines .= '>';
1812 $htmlforlines .= '<td class="left">';
1813 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1814 $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
1815 }
1816 if (isset($line->product_type)) {
1817 if (empty($line->product_type)) {
1818 $htmlforlines .= img_object('', 'product').' ';
1819 } else {
1820 $htmlforlines .= img_object('', 'service').' ';
1821 }
1822 }
1823 if (!getDolGlobalString('TAKEPOS_SHOW_N_FIRST_LINES')) {
1824 $tooltiptext = '';
1825 if ($line->product_ref) {
1826 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1827 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1828 if (!empty($line->batch)) {
1829 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1830 }
1831 if (!empty($line->fk_warehouse)) {
1832 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1833 }
1834 if ($line->product_label != $line->desc) {
1835 if ($line->desc) {
1836 $tooltiptext .= '<br>';
1837 }
1838 $tooltiptext .= $line->desc;
1839 }
1840 }
1841 if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
1842 $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1843 } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
1844 $htmlforlines .= $form->textwithpicto($line->product_ref ? '<b>'.$line->product_ref.'<b>' : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1845 } else {
1846 $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
1847 }
1848 } else {
1849 if ($line->product_label) {
1850 $htmlforlines .= $line->product_label;
1851 }
1852 if (!empty($line->batch)) {
1853 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
1854 }
1855 if (!empty($line->fk_warehouse)) {
1856 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
1857 }
1858
1859 if ($line->product_label != $line->desc) {
1860 if ($line->product_label && $line->desc) {
1861 $htmlforlines .= '<br>';
1862 }
1863 $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
1864 if ($firstline != $line->desc) {
1865 $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1866 } else {
1867 $htmlforlines .= $line->desc;
1868 }
1869 }
1870 }
1871 if (!empty($line->array_options['options_order_notes'])) {
1872 $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
1873 }
1874 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1875 $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>';
1876 }
1877 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1878 $moreinfo = '';
1879 $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
1880 if ($line->vat_src_code) {
1881 $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
1882 }
1883 $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
1884 $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
1885 $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
1886 $moreinfo .= '<hr>';
1887 $moreinfo .= $langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
1888 //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
1889 if ($line->date_start || $line->date_end) {
1890 $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
1891 }
1892 $htmlforlines .= '</td>';
1893
1894 // complete line by hook
1895 $parameters=array('line' => $line);
1896 $reshook=$hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1897 if ($reshook < 0) {
1898 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1899 }
1900 $htmlforlines .= $hookmanager->resPrint;
1901
1902 $htmlforlines .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1903 $htmlforlines .= '<td class="right">';
1904 if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire')) {
1905 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1906 if (getDolGlobalString($constantforkey) && $line->fk_product > 0 && !getDolGlobalString('TAKEPOS_HIDE_STOCK_ON_LINE')) {
1907 $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
1908 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
1909 $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
1910 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
1911 $sql .= " WHERE ps.reel != 0";
1912 $sql .= " AND ps.fk_entrepot = ".((int) getDolGlobalString($constantforkey));
1913 $sql .= " AND e.entity IN (".getEntity('stock').")";
1914 $sql .= " AND ps.fk_product = ".((int) $line->fk_product);
1915 $resql = $db->query($sql);
1916 if ($resql) {
1917 $obj = $db->fetch_object($resql);
1918 if ($obj) {
1919 $stock_real = price2num($obj->reel, 'MS');
1920 } else {
1921 $stock_real = 0;
1922 }
1923 $htmlforlines .= $line->qty;
1924 if ($line->qty && $line->qty > $stock_real) {
1925 $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
1926 }
1927 $htmlforlines .= ' <span class="posstocktoolow">('.$langs->trans("Stock").' '.$stock_real.')</span>';
1928 if ($line->qty && $line->qty > $stock_real) {
1929 $htmlforlines .= "</span>";
1930 }
1931 } else {
1932 dol_print_error($db);
1933 }
1934 } else {
1935 $htmlforlines .= $line->qty;
1936 }
1937 } else {
1938 $htmlforlines .= $line->qty;
1939 }
1940
1941 $htmlforlines .= '</td>';
1942 if (getDolGlobalInt('TAKEPOS_SHOW_HT')) {
1943 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
1944 $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
1945 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1946 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1947 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1948 $multicurrency = new MultiCurrency($db);
1949 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1950 $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>';
1951 }
1952 $htmlforlines .= '</td>';
1953 }
1954 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
1955 $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
1956 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1957 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1958 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1959 $multicurrency = new MultiCurrency($db);
1960 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1961 $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>';
1962 }
1963 $htmlforlines .= '</td>';
1964 }
1965 $htmlforlines .= '</tr>'."\n";
1966 $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
1967
1968 print $htmlforlines;
1969 }
1970 } else {
1971 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
1972 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1973 print '<td></td><td></td>';
1974 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1975 print '<td></td>';
1976 }
1977 }
1978 print '</tr>';
1979 }
1980} else { // No invoice generated yet
1981 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
1982 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1983 print '<td></td><td></td>';
1984 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1985 print '<td></td>';
1986 }
1987 }
1988 print '</tr>';
1989}
1990
1991if ($usediv) {
1992 print '</div>';
1993} else {
1994 print '</table>';
1995}
1996
1997if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE && !getDolGlobalString('TAKEPOS_NO_CREDITNOTE')) {
1998 print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
1999 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
2000 print ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
2001 }
2002}
2003
2004
2005if ($action == "search") {
2006 print '<center>
2007 <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')).'">
2008 </center>';
2009}
2010
2011print '</div>';
2012
2013// llxFooter
2014if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
2015 print '</body></html>';
2016}
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:653
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:1907
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