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