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