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