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