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