Passed
Push — EXTRACT_CLASSES ( c53232...d3ffdd )
by Rafael
39:58
created

fail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copyright (C) 2018       Andreu Bisquerra            <[email protected]>
5
 * Copyright (C) 2021       Nicolas ZABOURI             <[email protected]>
6
 * Copyright (C) 2022-2023  Christophe Battarel         <[email protected]>
7
 * Copyright (C) 2024       MDW                         <[email protected]>
8
 * Copyright (C) 2024       Rafael San José             <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
use Dolibarr\Code\Adherents\Classes\Adherent;
25
use Dolibarr\Code\Categories\Classes\Categorie;
26
use Dolibarr\Code\Compta\Classes\Facture;
27
use Dolibarr\Code\Contact\Classes\Contact;
28
use Dolibarr\Code\Core\Classes\Form;
29
use Dolibarr\Code\Fourn\Classes\ProductFournisseur;
30
use Dolibarr\Code\MultiCurrency\Classes\MultiCurrency;
31
use Dolibarr\Code\Product\Classes\Entrepot;
32
use Dolibarr\Code\Product\Classes\MouvementStock;
33
use Dolibarr\Code\Product\Classes\Product;
34
use Dolibarr\Code\Product\Classes\Productbatch;
35
use Dolibarr\Code\Societe\Classes\Societe;
36
37
/**
38
 *    \file       htdocs/takepos/invoice.php
39
 *    \ingroup    takepos
40
 *    \brief      Page to generate section with list of lines
41
 */
42
43
// if (! defined('NOREQUIREUSER'))      define('NOREQUIREUSER', '1');       // Not disabled cause need to load personalized language
44
// if (! defined('NOREQUIREDB'))        define('NOREQUIREDB', '1');         // Not disabled cause need to load personalized language
45
// if (! defined('NOREQUIRESOC'))       define('NOREQUIRESOC', '1');
46
// if (! defined('NOREQUIRETRAN'))      define('NOREQUIRETRAN', '1');
47
48
49
if (!defined('NOTOKENRENEWAL')) {
50
    define('NOTOKENRENEWAL', '1');
51
}
52
if (!defined('NOREQUIREMENU')) {
53
    define('NOREQUIREMENU', '1');
54
}
55
if (!defined('NOREQUIREHTML')) {
56
    define('NOREQUIREHTML', '1');
57
}
58
if (!defined('NOREQUIREAJAX')) {
59
    define('NOREQUIREAJAX', '1');
60
}
61
62
// Load Dolibarr environment
63
if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
64
    require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
65
}
66
67
$hookmanager->initHooks(array('takeposinvoice'));
68
69
$langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks", "banks"));
70
71
$action = GETPOST('action', 'aZ09');
72
$idproduct = GETPOSTINT('idproduct');
73
$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
74
$placeid = 0; // $placeid is ID of invoice
75
$mobilepage = GETPOST('mobilepage', 'alpha');
76
77
// Terminal is stored into $_SESSION["takeposterminal"];
78
79
if (!$user->hasRight('takepos', 'run') && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
80
    accessforbidden('No permission to use the TakePOS');
81
}
82
83
if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
84
    // DIRECT LINK TO THIS PAGE FROM MOBILE AND NO TERMINAL SELECTED
85
    if ($_SESSION["takeposterminal"] == "") {
86
        if (getDolGlobalString('TAKEPOS_NUM_TERMINALS') == "1") {
87
            $_SESSION["takeposterminal"] = 1;
88
        } else {
89
            header("Location: " . constant('BASE_URL') . "/takepos/index.php");
90
            exit;
91
        }
92
    }
93
}
94
95
$takeposterminal = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '';
96
97
/**
98
 * Abort invoice creation with a given error message
99
 *
100
 * @param   string  $message        Message explaining the error to the user
101
 * @return  void
102
 */
103
function fail($message)
104
{
105
    header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
106
    die($message);
107
}
108
109
110
111
$number = GETPOST('number', 'alpha');
112
$idline = GETPOSTINT('idline');
113
$selectedline = GETPOSTINT('selectedline');
114
$desc = GETPOST('desc', 'alphanohtml');
115
$pay = GETPOST('pay', 'aZ09');
116
$amountofpayment = GETPOSTFLOAT('amount');
117
118
$invoiceid = GETPOSTINT('invoiceid');
119
120
$paycode = $pay;
121
if ($pay == 'cash') {
122
    $paycode = 'LIQ'; // For backward compatibility
123
}
124
if ($pay == 'card') {
125
    $paycode = 'CB'; // For backward compatibility
126
}
127
if ($pay == 'cheque') {
128
    $paycode = 'CHQ'; // For backward compatibility
129
}
130
131
// Retrieve paiementid
132
$paiementid = 0;
133
if ($paycode) {
134
    $sql = "SELECT id FROM " . MAIN_DB_PREFIX . "c_paiement";
135
    $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
136
    $sql .= " AND code = '" . $db->escape($paycode) . "'";
137
    $resql = $db->query($sql);
138
    if ($resql) {
139
        $obj = $db->fetch_object($resql);
140
        if ($obj) {
141
            $paiementid = $obj->id;
142
        }
143
    }
144
}
145
146
$invoice = new Facture($db);
147
if ($invoiceid > 0) {
148
    $ret = $invoice->fetch($invoiceid);
149
} else {
150
    $ret = $invoice->fetch('', '(PROV-POS' . $takeposterminal . '-' . $place . ')');
151
}
152
if ($ret > 0) {
153
    $placeid = $invoice->id;
154
}
155
156
$constforcompanyid = 'CASHDESK_ID_THIRDPARTY' . $takeposterminal;
157
158
$soc = new Societe($db);
159
if ($invoice->socid > 0) {
160
    $soc->fetch($invoice->socid);
161
} else {
162
    $soc->fetch(getDolGlobalString($constforcompanyid));
163
}
164
165
// Assign a default project, if relevant
166
if (isModEnabled('project') && getDolGlobalInt("CASHDESK_ID_PROJECT" . $takeposterminal)) {
167
    $invoice->fk_project = getDolGlobalInt("CASHDESK_ID_PROJECT" . $takeposterminal);
168
}
169
170
// Change the currency of invoice if it was modified
171
if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"])) {
172
    if ($invoice->multicurrency_code != $_SESSION["takeposcustomercurrency"]) {
173
        $invoice->setMulticurrencyCode($_SESSION["takeposcustomercurrency"]);
174
    }
175
}
176
177
$term = empty($_SESSION["takeposterminal"]) ? 1 : $_SESSION["takeposterminal"];
178
179
180
/*
181
 * Actions
182
 */
183
184
$parameters = array();
185
$reshook = $hookmanager->executeHooks('doActions', $parameters, $invoice, $action);    // Note that $action and $object may have been modified by some hooks
186
if ($reshook < 0) {
187
    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
188
}
189
190
if (empty($reshook)) {
191
    // Action to record a payment on a TakePOS invoice
192
    if ($action == 'valid' && $user->hasRight('facture', 'creer')) {
193
        $bankaccount = 0;
194
        $error = 0;
195
196
        if (getDolGlobalString('TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT')) {
197
            $bankaccount = GETPOSTINT('accountid');
198
        } else {
199
            if ($pay == 'LIQ') {
200
                $bankaccount = getDolGlobalInt('CASHDESK_ID_BANKACCOUNT_CASH' . $_SESSION["takeposterminal"]);            // For backward compatibility
201
            } elseif ($pay == "CHQ") {
202
                $bankaccount = getDolGlobalInt('CASHDESK_ID_BANKACCOUNT_CHEQUE' . $_SESSION["takeposterminal"]);    // For backward compatibility
203
            } else {
204
                $accountname = "CASHDESK_ID_BANKACCOUNT_" . $pay . $_SESSION["takeposterminal"];
205
                $bankaccount = getDolGlobalInt($accountname);
206
            }
207
        }
208
209
        if ($bankaccount <= 0 && $pay != "delayed" && isModEnabled("bank")) {
210
            $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount"));
211
            $error++;
212
        }
213
214
        $now = dol_now();
215
        $res = 0;
216
217
        $invoice = new Facture($db);
218
        $invoice->fetch($placeid);
219
220
        $db->begin();
221
222
        if ($invoice->total_ttc < 0) {
223
            $invoice->type = $invoice::TYPE_CREDIT_NOTE;
224
225
            $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "facture";
226
            $sql .= " WHERE entity IN (" . getEntity('invoice') . ")";
227
            $sql .= " AND fk_soc = " . ((int) $invoice->socid);
228
            $sql .= " AND type <> " . Facture::TYPE_CREDIT_NOTE;
229
            $sql .= " AND fk_statut >= " . $invoice::STATUS_VALIDATED;
230
            $sql .= " ORDER BY rowid DESC";
231
232
            $resql = $db->query($sql);
233
            if ($resql) {
234
                $obj = $db->fetch_object($resql);
235
                $fk_source = $obj->rowid;
236
                if ($fk_source == null) {
237
                    fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
238
                }
239
            } else {
240
                fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
241
            }
242
            $invoice->fk_facture_source = $fk_source;
243
            $invoice->update($user);
244
        }
245
246
        $constantforkey = 'CASHDESK_NO_DECREASE_STOCK' . (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
247
        if ($error) {
248
            dol_htmloutput_errors($errormsg, null, 1);
249
        } elseif ($invoice->status != Facture::STATUS_DRAFT) {
250
            //If invoice is validated but it is not fully paid is not error and make the payment
251
            if ($invoice->getRemainToPay() > 0) {
252
                $res = 1;
253
            } else {
254
                dol_syslog("Sale already validated");
255
                dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1);
256
            }
257
        } elseif (count($invoice->lines) == 0) {
258
            $error++;
259
            dol_syslog('Sale without lines');
260
            dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1);
261
        } elseif (isModEnabled('stock') && !isModEnabled('productbatch') && getDolGlobalString($constantforkey) != "1") {
262
            // Validation of invoice with change into stock when produt/lot module is not enabled and stock change not disabled.
263
            // The case for isModEnabled('productbatch') is processed few lines later.
264
            $savconst = getDolGlobalString('STOCK_CALCULATE_ON_BILL');
265
266
            if (isModEnabled('productbatch') && !getDolGlobalInt('CASHDESK_FORCE_DECREASE_STOCK')) {
267
                $conf->global->STOCK_CALCULATE_ON_BILL = 0; // To not change the stock (this will be done later)
268
            } else {
269
                // Deprecated: CASHDESK_FORCE_DECREASE_STOCK is now always false. No more required/used.
270
                $conf->global->STOCK_CALCULATE_ON_BILL = 1; // To force the change of stock
271
            }
272
273
            $constantforkey = 'CASHDESK_ID_WAREHOUSE' . $_SESSION["takeposterminal"];
274
            dol_syslog("Validate invoice with stock change into warehouse defined into constant " . $constantforkey . " = " . getDolGlobalString($constantforkey));
275
276
            $batch_rule = 0;
277
            if (isModEnabled('productbatch') && getDolGlobalString('CASHDESK_FORCE_DECREASE_STOCK')) {
278
                $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST;
279
            }
280
            $res = $invoice->validate($user, '', getDolGlobalInt($constantforkey), 0, $batch_rule);
281
282
            $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
283
        } else {
284
            // Validation of invoice with no change into stock
285
            $res = $invoice->validate($user);
286
            if ($res < 0) {
287
                $error++;
288
                $langs->load("admin");
289
                dol_htmloutput_errors($invoice->error == 'NotConfigured' ? $langs->trans("NotConfigured") . ' (TakePos numbering module)' : $invoice->error, $invoice->errors, 1);
290
            }
291
        }
292
293
        // Add the payment
294
        if (!$error && $res >= 0) {
295
            $remaintopay = $invoice->getRemainToPay();
296
            if ($remaintopay > 0) {
297
                $payment = new Paiement($db);
298
                $payment->datepaye = $now;
299
                $payment->fk_account = $bankaccount;
300
                $payment->amounts[$invoice->id] = $amountofpayment;
301
                if ($pay == 'LIQ') {
302
                    $payment->pos_change = GETPOSTFLOAT('excess');
303
                }
304
305
                // If user has not used change control, add total invoice payment
306
                // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay
307
                if ($amountofpayment <= 0 || $amountofpayment > $remaintopay) {
308
                    $payment->amounts[$invoice->id] = $remaintopay;
309
                }
310
311
                $payment->paiementid = $paiementid;
312
                $payment->num_payment = $invoice->ref;
313
314
                if ($pay != "delayed") {
315
                    $payment->create($user);
316
                    $res = $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', '');
317
                    if ($res < 0) {
318
                        $error++;
319
                        dol_htmloutput_errors($langs->trans('ErrorNoPaymentDefined'), $payment->errors, 1);
320
                    }
321
                    $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded
322
                } elseif (getDolGlobalInt("TAKEPOS_DELAYED_TERMS")) {
323
                    $invoice->setPaymentTerms(getDolGlobalInt("TAKEPOS_DELAYED_TERMS"));
324
                }
325
            }
326
327
            if ($remaintopay == 0) {
328
                dol_syslog("Invoice is paid, so we set it to status Paid");
329
                $result = $invoice->setPaid($user);
330
                if ($result > 0) {
331
                    $invoice->paye = 1;
332
                }
333
                // set payment method
334
                $invoice->setPaymentMethods($paiementid);
335
            } else {
336
                dol_syslog("Invoice is not paid, remain to pay = " . $remaintopay);
337
            }
338
        } else {
339
            dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
340
        }
341
342
        // Update stock for batch products
343
        if (!$error && $res >= 0) {
344
            if (isModEnabled('stock') && isModEnabled('productbatch')) {    // The case !isModEnabled('productbatch') was processed few lines before.
345
                require_once DOL_DOCUMENT_ROOT . "/product/stock/class/mouvementstock.class.php";
346
                $constantforkey = 'CASHDESK_ID_WAREHOUSE' . $_SESSION["takeposterminal"];
347
                $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
348
                $labeltakeposmovement = 'TakePOS - ' . $langs->trans("Invoice") . ' ' . $invoice->ref;
349
350
                foreach ($invoice->lines as $line) {
351
                    $warehouseid = ($line->fk_warehouse ? $line->fk_warehouse : getDolGlobalInt($constantforkey));
352
353
                    // var_dump('fk_product='.$line->fk_product.' batch='.$line->batch.' warehouse='.$line->fk_warehouse.' qty='.$line->qty);
354
                    if ($line->batch != '' && $warehouseid > 0) {
355
                        $prod_batch = new Productbatch($db);
356
                        $prod_batch->find(0, '', '', $line->batch, $warehouseid);
357
                        $mouvP = new MouvementStock($db);
358
                        $mouvP->origin = $invoice;
359
                        $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', $prod_batch->batch, $prod_batch->id, $inventorycode);
360
                        if ($res < 0) {
361
                            setEventMessages($mouvP->error, $mouvP->errors, 'errors');
362
                            $error++;
363
                        }
364
                    } else {
365
                        $mouvP = new MouvementStock($db);
366
                        $mouvP->origin = $invoice;
367
                        $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', '', 0, $inventorycode);
368
                        if ($res < 0) {
369
                            setEventMessages($mouvP->error, $mouvP->errors, 'errors');
370
                            $error++;
371
                        }
372
                    }
373
                }
374
            }
375
        }
376
377
        if (!$error && $res >= 0) {
378
            $db->commit();
379
        } else {
380
            $db->rollback();
381
        }
382
    }
383
    if ($action == 'creditnote' && $user->hasRight('facture', 'creer')) {
384
        $db->begin();
385
386
        $creditnote = new Facture($db);
387
        $creditnote->socid = $invoice->socid;
388
        $creditnote->date = dol_now();
389
        $creditnote->module_source = 'takepos';
390
        $creditnote->pos_source =  isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
391
        $creditnote->type = Facture::TYPE_CREDIT_NOTE;
392
        $creditnote->fk_facture_source = $placeid;
393
        //$creditnote->remise_absolue = $invoice->remise_absolue;
394
        //$creditnote->remise_percent = $invoice->remise_percent;
395
        $creditnote->create($user);
396
397
        foreach ($invoice->lines as $line) {
398
            // Extrafields
399
            if (method_exists($line, 'fetch_optionals')) {
400
                // load extrafields
401
                $line->fetch_optionals();
402
            }
403
            // Reset fk_parent_line for no child products and special product
404
            if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
405
                $fk_parent_line = 0;
406
            }
407
408
            if (getDolGlobalInt('INVOICE_USE_SITUATION')) {
409
                if (!empty($invoice->situation_counter)) {
410
                    $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
411
                    $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
412
                    if (!empty($invoice->tab_previous_situation_invoice)) {
413
                        // search the last standard invoice in cycle and the possible credit note between this last and invoice
414
                        // TODO Move this out of loop of $invoice->lines
415
                        $tab_jumped_credit_notes = array();
416
                        $lineIndex = count($invoice->tab_previous_situation_invoice) - 1;
417
                        $searchPreviousInvoice = true;
418
                        while ($searchPreviousInvoice) {
419
                            if ($invoice->tab_previous_situation_invoice[$lineIndex]->situation_cycle_ref || $lineIndex < 1) {
420
                                $searchPreviousInvoice = false; // find, exit;
421
                                break;
422
                            } else {
423
                                if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) {
424
                                    $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id;
425
                                }
426
                                $lineIndex--; // go to previous invoice in cycle
427
                            }
428
                        }
429
430
                        $maxPrevSituationPercent = 0;
431
                        foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) {
432
                            if ($prevLine->id == $source_fk_prev_id) {
433
                                $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent);
434
435
                                //$line->subprice  = $line->subprice - $prevLine->subprice;
436
                                $line->total_ht  = $line->total_ht - $prevLine->total_ht;
437
                                $line->total_tva = $line->total_tva - $prevLine->total_tva;
438
                                $line->total_ttc = $line->total_ttc - $prevLine->total_ttc;
439
                                $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1;
440
                                $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2;
441
442
                                $line->multicurrency_subprice  = $line->multicurrency_subprice - $prevLine->multicurrency_subprice;
443
                                $line->multicurrency_total_ht  = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht;
444
                                $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva;
445
                                $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc;
446
                            }
447
                        }
448
449
                        // prorata
450
                        $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
451
452
                        //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>';
453
454
                        // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta)
455
                        $maxPrevSituationPercent = 0;
456
                        foreach ($tab_jumped_credit_notes as $index => $creditnoteid) {
457
                            foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) {
458
                                if ($prevLine->fk_prev_id == $source_fk_prev_id) {
459
                                    $maxPrevSituationPercent = $prevLine->situation_percent;
460
461
                                    $line->total_ht  -= $prevLine->total_ht;
462
                                    $line->total_tva -= $prevLine->total_tva;
463
                                    $line->total_ttc -= $prevLine->total_ttc;
464
                                    $line->total_localtax1 -= $prevLine->total_localtax1;
465
                                    $line->total_localtax2 -= $prevLine->total_localtax2;
466
467
                                    $line->multicurrency_subprice  -= $prevLine->multicurrency_subprice;
468
                                    $line->multicurrency_total_ht  -= $prevLine->multicurrency_total_ht;
469
                                    $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
470
                                    $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
471
                                }
472
                            }
473
                        }
474
475
                        // prorata
476
                        $line->situation_percent += $maxPrevSituationPercent;
477
478
                        //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>';
479
                    }
480
                }
481
            }
482
483
            $line->fk_facture = $creditnote->id;
484
            $line->fk_parent_line = $fk_parent_line;
485
486
            $line->subprice = -$line->subprice; // invert price for object
487
            // $line->pa_ht = $line->pa_ht; // we chose to have the buy/cost price always positive, so no inversion of the sign here
488
            $line->total_ht = -$line->total_ht;
489
            $line->total_tva = -$line->total_tva;
490
            $line->total_ttc = -$line->total_ttc;
491
            $line->total_localtax1 = -$line->total_localtax1;
492
            $line->total_localtax2 = -$line->total_localtax2;
493
494
            $line->multicurrency_subprice = -$line->multicurrency_subprice;
495
            $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
496
            $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
497
            $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
498
499
            $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount already linked
500
501
            $creditnote->lines[] = $line; // insert new line in current object
502
503
            // Defined the new fk_parent_line
504
            if ($result > 0 && $line->product_type == 9) {
505
                $fk_parent_line = $result;
506
            }
507
        }
508
        $creditnote->update_price(1);
509
510
        $constantforkey = 'CASHDESK_NO_DECREASE_STOCK' . (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
511
        if (isModEnabled('stock') && getDolGlobalString($constantforkey) != "1") {
512
            $savconst = getDolGlobalString('STOCK_CALCULATE_ON_BILL');
513
            $conf->global->STOCK_CALCULATE_ON_BILL = 1;
514
            $constantforkey = 'CASHDESK_ID_WAREHOUSE' . (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
515
            dol_syslog("Validate invoice with stock change into warehouse defined into constant " . $constantforkey . " = " . getDolGlobalString($constantforkey));
516
            $batch_rule = 0;
517
            if (isModEnabled('productbatch') && getDolGlobalString('CASHDESK_FORCE_DECREASE_STOCK')) {
518
                $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST;
519
            }
520
            $res = $creditnote->validate($user, '', getDolGlobalString($constantforkey), 0, $batch_rule);
521
            $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
522
        } else {
523
            $res = $creditnote->validate($user);
524
        }
525
526
        if (!$error && $res >= 0) {
527
            $db->commit();
528
        } else {
529
            $db->rollback();
530
        }
531
    }
532
533
    if (($action == 'history' || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
534
        if ($action == 'creditnote') {
535
            $placeid = $creditnote->id;
536
        } else {
537
            $placeid = GETPOSTINT('placeid');
538
        }
539
        $invoice = new Facture($db);
540
        $invoice->fetch($placeid);
541
    }
542
543
    // If we add a line and no invoice yet, we create the invoice
544
    if (($action == "addline" || $action == "freezone") && $placeid == 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
545
        $invoice->socid = getDolGlobalInt($constforcompanyid);
546
        $invoice->date = dol_now('tzuserrel');      // We use the local date, only the day will be saved.
547
        $invoice->module_source = 'takepos';
548
        $invoice->pos_source =  isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
549
        $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
550
551
        if ($invoice->socid <= 0) {
552
            $langs->load('errors');
553
            dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1);
554
        } else {
555
            $db->begin();
556
557
            // Create invoice
558
            $placeid = $invoice->create($user);
559
            if ($placeid < 0) {
560
                dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
561
            }
562
            $sql = "UPDATE " . MAIN_DB_PREFIX . "facture set ref='(PROV-POS" . $_SESSION["takeposterminal"] . "-" . $place . ")' where rowid = " . ((int) $placeid);
563
            $resql = $db->query($sql);
564
            if (!$resql) {
565
                $error++;
566
            }
567
568
            if (!$error) {
569
                $db->commit();
570
            } else {
571
                $db->rollback();
572
            }
573
        }
574
    }
575
576
    // If we add a line by click on product (invoice exists here because it was created juste before if it didn't exists)
577
    if ($action == "addline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
578
        $prod = new Product($db);
579
        $prod->fetch($idproduct);
580
581
        $customer = new Societe($db);
582
        $customer->fetch($invoice->socid);
583
584
        $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
585
586
        $qty = GETPOSTISSET('qty') ? GETPOSTINT('qty') : 1;
587
        $price = $datapriceofproduct['pu_ht'];
588
        $price_ttc = $datapriceofproduct['pu_ttc'];
589
        //$price_min = $datapriceofproduct['price_min'];
590
        $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
591
        $tva_tx = $datapriceofproduct['tva_tx'];
592
        $tva_npr = $datapriceofproduct['tva_npr'];
593
594
        // Local Taxes
595
        $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
596
        $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
597
598
599
        if (isModEnabled('productbatch') && isModEnabled('stock')) {
600
            $batch = GETPOST('batch', 'alpha');
601
602
            if (!empty($batch)) {   // We have just clicked on the batch number
603
                $action = "setbatch";
604
            } elseif ($prod->status_batch > 0) {
605
                // If product need a lot/serial, we show the list of lot/serial available for the product...
606
607
                // Set nb of suggested with nb of batch into the warehouse of the terminal
608
                $nbofsuggested = 0;
609
                $prod->load_stock('warehouseopen');
610
611
                $constantforkey = 'CASHDESK_ID_WAREHOUSE' . $_SESSION["takeposterminal"];
612
                $warehouseid = getDolGlobalInt($constantforkey);
613
614
                //var_dump($prod->stock_warehouse);
615
                foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
616
                    if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
617
                        // Not on the forced warehous, so we ignore this warehous
618
                        continue;
619
                    }
620
                    if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
621
                        if (is_object($prod->stock_warehouse[$tmpwarehouseid]) && count($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
622
                            foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) {
623
                                $nbofsuggested++;
624
                            }
625
                        }
626
                    }
627
                }
628
                //var_dump($prod->stock_warehouse);
629
630
                echo "<script>\n";
631
                echo "function addbatch(batch, warehouseid) {\n";
632
                echo "console.log('We add batch '+batch+' from warehouse id '+warehouseid);\n";
633
                echo '$("#poslines").load("invoice.php?action=addline&batch="+batch+"&warehouseid="+warehouseid+"&place=' . $place . '&idproduct=' . $idproduct . '&token=' . newToken() . '", function() {});' . "\n";
634
                echo "}\n";
635
                echo "</script>\n";
636
637
                $suggestednb = 1;
638
                echo "<center>" . $langs->trans("SearchIntoBatch") . ": <b> $nbofsuggested </b></center><br><table>";
639
                foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
640
                    if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
641
                        // Not on the forced warehouse, so we ignore this warehouse
642
                        continue;
643
                    }
644
                    if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
645
                        foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) {    // $dbatch is instance of Productbatch
646
                            $batchStock = + $dbatch->qty; // To get a numeric
647
                            $quantityToBeDelivered = 1;
648
                            $deliverableQty = min($quantityToBeDelivered, $batchStock);
649
                            print '<tr>';
650
                            print '<!-- subj=' . $suggestednb . '/' . $nbofsuggested . ' -->';
651
                            print '<!-- Show details of lot -->';
652
                            print '<td class="left">';
653
                            $detail = '';
654
                            $detail .= '<span class="opacitymedium">' . $langs->trans("LotSerial") . ':</span> ' . $dbatch->batch;
655
                            if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
656
                                //$detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
657
                            }
658
                            if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
659
                                //$detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
660
                            }
661
                            $detail .= '</td><td>';
662
                            $detail .= '<span class="opacitymedium">' . $langs->trans("Qty") . ':</span> ' . $dbatch->qty;
663
                            $detail .= '</td><td>';
664
                            $detail .= ' <button class="marginleftonly" onclick="addbatch(\'' . dol_escape_js($dbatch->batch) . '\', ' . $tmpwarehouseid . ')">' . $langs->trans("Select") . "</button>";
665
                            $detail .= '<br>';
666
                            print $detail;
667
668
                            $quantityToBeDelivered -= $deliverableQty;
669
                            if ($quantityToBeDelivered < 0) {
670
                                $quantityToBeDelivered = 0;
671
                            }
672
                            $suggestednb++;
673
                            print '</td></tr>';
674
                        }
675
                    }
676
                }
677
                print "</table>";
678
679
                print '</body></html>';
680
                exit;
681
            }
682
        }
683
684
685
        if (getDolGlobalString('TAKEPOS_SUPPLEMENTS')) {
686
            $cat = new Categorie($db);
687
            $categories = $cat->containing($idproduct, 'product');
688
            $found = (array_search(getDolGlobalInt('TAKEPOS_SUPPLEMENTS_CATEGORY'), array_column($categories, 'id')));
689
            if ($found !== false) { // If this product is a supplement
690
                $sql = "SELECT fk_parent_line FROM " . MAIN_DB_PREFIX . "facturedet where rowid = " . ((int) $selectedline);
691
                $resql = $db->query($sql);
692
                $row = $db->fetch_array($resql);
693
                if ($row[0] == null) {
694
                    $parent_line = $selectedline;
695
                } else {
696
                    $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main  product
697
                }
698
            }
699
        }
700
701
        $idoflineadded = 0;
702
        $err = 0;
703
        // Group if enabled. Skip group if line already sent to the printer
704
        if (getDolGlobalString('TAKEPOS_GROUP_SAME_PRODUCT')) {
705
            foreach ($invoice->lines as $line) {
706
                if ($line->product_ref == $prod->ref) {
707
                    if ($line->special_code == 4) {
708
                        continue;
709
                    } // If this line is sended to printer create new line
710
                    // check if qty in stock
711
                    if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && (($line->qty + $qty) > $prod->stock_reel)) {
712
                        $invoice->error = $langs->trans("ErrorStockIsNotEnough");
713
                        dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
714
                        $err++;
715
                        break;
716
                    }
717
                    $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);
718
                    if ($result < 0) {
719
                        dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
720
                    } else {
721
                        $idoflineadded = $line->id;
722
                    }
723
                    break;
724
                }
725
            }
726
        }
727
        if ($idoflineadded <= 0 && empty($err)) {
728
            $invoice->fetch_thirdparty();
729
            $array_options = array();
730
731
            $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);
732
733
            /* setup of margin calculation */
734
            if (isset($conf->global->MARGIN_TYPE)) {
735
                if (getDolGlobalString('MARGIN_TYPE') == 'pmp' && !empty($prod->pmp)) {
736
                    $line['fk_fournprice'] = null;
737
                    $line['pa_ht'] = $prod->pmp;
738
                } elseif (getDolGlobalString('MARGIN_TYPE') == 'costprice' && !empty($prod->cost_price)) {
739
                    $line['fk_fournprice'] = null;
740
                    $line['pa_ht'] = $prod->cost_price;
741
                } else {
742
                    // default is fournprice
743
                    $pf = new ProductFournisseur($db);
744
                    if ($pf->find_min_price_product_fournisseur($idproduct, $qty) > 0) {
745
                        $line['fk_fournprice'] = $pf->product_fourn_price_id;
746
                        $line['pa_ht'] = $pf->fourn_unitprice_with_discount;
747
                        if (getDolGlobalString('PRODUCT_CHARGES') && $pf->fourn_charges > 0) {
748
                            $line['pa_ht'] += $pf->fourn_charges / $pf->fourn_qty;
749
                        }
750
                    }
751
                }
752
            }
753
754
            // complete line by hook
755
            $parameters = array('prod' => $prod, 'line' => $line);
756
            $reshook = $hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action);    // Note that $action and $line may have been modified by some hooks
757
            if ($reshook < 0) {
758
                setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
759
            }
760
761
762
            if (empty($reshook)) {
763
                if (!empty($hookmanager->resArray)) {
764
                    $line = $hookmanager->resArray;
765
                }
766
767
                // check if qty in stock
768
                if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && $qty > $prod->stock_reel) {
769
                    $invoice->error = $langs->trans("ErrorStockIsNotEnough");
770
                    dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
771
                    $err++;
772
                }
773
774
                if (empty($err)) {
775
                    $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);
776
                }
777
            }
778
779
            if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
780
                $CUSTOMER_DISPLAY_line1 = $prod->label;
781
                $CUSTOMER_DISPLAY_line2 = price($price_ttc);
782
            }
783
        }
784
785
        $invoice->fetch($placeid);
786
    }
787
788
    // If we add a line by submitting freezone form (invoice exists here because it was created juste before if it didn't exists)
789
    if ($action == "freezone" && $user->hasRight('takepos', 'run')) {
790
        $customer = new Societe($db);
791
        $customer->fetch($invoice->socid);
792
793
        $tva_tx = GETPOST('tva_tx', 'alpha');
794
        if ($tva_tx != '') {
795
            if (!preg_match('/\((.*)\)/', $tva_tx)) {
796
                $tva_tx = price2num($tva_tx);
797
            }
798
        } else {
799
            $tva_tx = get_default_tva($mysoc, $customer);
800
        }
801
802
        // Local Taxes
803
        $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
804
        $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
805
806
        $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);
807
        if ($res < 0) {
808
            dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
809
        }
810
        $invoice->fetch($placeid);
811
    }
812
813
    if ($action == "addnote" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
814
        $desc = GETPOST('addnote', 'alpha');
815
        if ($idline == 0) {
816
            $invoice->update_note($desc, '_public');
817
        } else {
818
            foreach ($invoice->lines as $line) {
819
                if ($line->id == $idline) {
820
                    $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);
821
                }
822
            }
823
        }
824
        $invoice->fetch($placeid);
825
    }
826
827
    if ($action == "deleteline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
828
        /*
829
        $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
830
        if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
831
            if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
832
                $permissiontoupdateline = true;
833
                // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
834
                // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
835
            }
836
        }*/
837
838
        if ($idline > 0 && $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
839
            $invoice->deleteLine($idline);
840
            $invoice->fetch($placeid);
841
        } elseif ($placeid > 0) {             // If invoice exists but no line selected, proceed to delete last line.
842
            $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "facturedet where fk_facture = " . ((int) $placeid) . " ORDER BY rowid DESC";
843
            $resql = $db->query($sql);
844
            $row = $db->fetch_array($resql);
845
            $deletelineid = $row[0];
846
            $invoice->deleteLine($deletelineid);
847
            $invoice->fetch($placeid);
848
        }
849
850
        if (count($invoice->lines) == 0) {
851
            $invoice->delete($user);
852
853
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
854
                header("Location: " . constant('BASE_URL') . "/takepos/public/auto_order.php");
855
            } else {
856
                header("Location: " . constant('BASE_URL') . "/takepos/invoice.php");
857
            }
858
            exit;
859
        }
860
    }
861
862
    // Action to delete or discard an invoice
863
    if ($action == "delete" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
864
        // $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.
865
        if ($placeid > 0) {
866
            $result = $invoice->fetch($placeid);
867
868
            if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

868
            if ($result > 0 && /** @scrutinizer ignore-deprecated */ $invoice->statut == Facture::STATUS_DRAFT) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
869
                $db->begin();
870
871
                // We delete the lines
872
                $resdeletelines = 1;
873
                foreach ($invoice->lines as $line) {
874
                    // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
875
                    $tmpres = $invoice->deleteLine($line->id);
876
                    if ($tmpres < 0) {
877
                        $resdeletelines = 0;
878
                        break;
879
                    }
880
                }
881
882
                $sql = "UPDATE " . MAIN_DB_PREFIX . "facture";
883
                $varforconst = 'CASHDESK_ID_THIRDPARTY' . $_SESSION["takeposterminal"];
884
                $sql .= " SET fk_soc = " . ((int) getDolGlobalString($varforconst)) . ", ";
885
                $sql .= " datec = '" . $db->idate(dol_now()) . "'";
886
                $sql .= " WHERE entity IN (" . getEntity('invoice') . ")";
887
                $sql .= " AND ref = '(PROV-POS" . $db->escape($_SESSION["takeposterminal"] . "-" . $place) . ")'";
888
                $resql1 = $db->query($sql);
889
890
                if ($resdeletelines && $resql1) {
891
                    $db->commit();
892
                } else {
893
                    $db->rollback();
894
                }
895
896
                $invoice->fetch($placeid);
897
            }
898
        }
899
    }
900
901
    if ($action == "updateqty") {   // Test on permission is done later
902
        foreach ($invoice->lines as $line) {
903
            if ($line->id == $idline) {
904
                $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
905
                if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
906
                    if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
907
                        $permissiontoupdateline = true;
908
                        // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
909
                        // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
910
                    }
911
                }
912
                if (!$permissiontoupdateline) {
913
                    dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos") . ' - No permission to updateqty', null, 1);
914
                } else {
915
                    $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);
916
                }
917
            }
918
        }
919
920
        $invoice->fetch($placeid);
921
    }
922
923
    if ($action == "updateprice") { // Test on permission is done later
924
        $customer = new Societe($db);
925
        $customer->fetch($invoice->socid);
926
927
        foreach ($invoice->lines as $line) {
928
            if ($line->id == $idline) {
929
                $prod = new Product($db);
930
                $prod->fetch($line->fk_product);
931
                $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
932
                $price_min = $datapriceofproduct['price_min'];
933
                $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
934
                $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
935
                //Check min price
936
                if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) {
937
                    $langs->load("products");
938
                    dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
939
                    //echo $langs->trans("CantBeLessThanMinPrice");
940
                } else {
941
                    $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
942
                    if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
943
                        if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
944
                            $permissiontoupdateline = true;
945
                            // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
946
                            // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
947
                        }
948
                    }
949
                    if (!$permissiontoupdateline) {
950
                        dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos") . ' - No permission to updateprice', null, 1);
951
                    } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT')  == 1) {
952
                        $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);
953
                    } else {
954
                        $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);
955
                    }
956
                }
957
            }
958
        }
959
960
        // Reload data
961
        $invoice->fetch($placeid);
962
    }
963
964
    if ($action == "updatereduction") { // Test on permission is done later
965
        $customer = new Societe($db);
966
        $customer->fetch($invoice->socid);
967
968
        foreach ($invoice->lines as $line) {
969
            if ($line->id == $idline) {
970
                dol_syslog("updatereduction Process line " . $line->id . ' to apply discount of ' . $number . '%');
971
972
                $prod = new Product($db);
973
                $prod->fetch($line->fk_product);
974
975
                $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
976
                $price_min = $datapriceofproduct['price_min'];
977
                $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
978
979
                $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
980
981
                // Check min price
982
                if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) {
983
                    $langs->load("products");
984
                    dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
985
                } else {
986
                    $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
987
                    if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
988
                        if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
989
                            $permissiontoupdateline = true;
990
                            // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
991
                            // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the invoice ID
992
                        }
993
                    }
994
                    if (!$permissiontoupdateline) {
995
                        dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
996
                    } else {
997
                        $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);
998
                    }
999
                }
1000
            }
1001
        }
1002
1003
        // Reload data
1004
        $invoice->fetch($placeid);
1005
    } elseif ($action == 'update_reduction_global' && $user->hasRight('takepos', 'editlines')) {
1006
        foreach ($invoice->lines as $line) {
1007
            $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);
1008
        }
1009
1010
        $invoice->fetch($placeid);
1011
    }
1012
1013
    if ($action == "setbatch" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1014
        $constantforkey = 'CASHDESK_ID_WAREHOUSE' . $_SESSION["takeposterminal"];
1015
        $warehouseid = getDolGlobalInt($constantforkey);    // TODO Get the wrehouse id from GETPOSTINT('warehouseid');
1016
        $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet SET batch = '" . $db->escape($batch) . "', fk_warehouse = " . ((int) $warehouseid);
1017
        $sql .= " WHERE rowid=" . ((int) $idoflineadded);
1018
        $db->query($sql);
1019
    }
1020
1021
    if ($action == "order" && $placeid != 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1022
        include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1023
        if ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE' . $term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1024
            require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/dolreceiptprinter.class.php';
1025
            $printer = new dolReceiptPrinter($db);
1026
        }
1027
1028
        $sql = "SELECT label FROM " . MAIN_DB_PREFIX . "takepos_floor_tables where rowid=" . ((int) $place);
1029
        $resql = $db->query($sql);
1030
        $row = $db->fetch_object($resql);
1031
        $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>';
1032
        $footerorder = '</tbody></table>' . dol_print_date(dol_now(), 'dayhour') . '<br></html>';
1033
        $order_receipt_printer1 = "";
1034
        $order_receipt_printer2 = "";
1035
        $order_receipt_printer3 = "";
1036
        $catsprinter1 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_1'));
1037
        $catsprinter2 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_2'));
1038
        $catsprinter3 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_3'));
1039
        $linestoprint = 0;
1040
        foreach ($invoice->lines as $line) {
1041
            if ($line->special_code == "4") {
1042
                continue;
1043
            }
1044
            $c = new Categorie($db);
1045
            $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1046
            $result = array_intersect($catsprinter1, $existing);
1047
            $count = count($result);
1048
            if (!$line->fk_product) {
1049
                $count++; // Print Free-text item (Unassigned printer) to Printer 1
1050
            }
1051
            if ($count > 0) {
1052
                $linestoprint++;
1053
                $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='1' where rowid=" . $line->id; //Set to print on printer 1
1054
                $db->query($sql);
1055
                $order_receipt_printer1 .= '<tr><td class="left">';
1056
                if ($line->fk_product) {
1057
                    $order_receipt_printer1 .= $line->product_label;
1058
                } else {
1059
                    $order_receipt_printer1 .= $line->description;
1060
                }
1061
                $order_receipt_printer1 .= '</td><td class="right">' . $line->qty;
1062
                if (!empty($line->array_options['options_order_notes'])) {
1063
                    $order_receipt_printer1 .= "<br>(" . $line->array_options['options_order_notes'] . ")";
1064
                }
1065
                $order_receipt_printer1 .= '</td></tr>';
1066
            }
1067
        }
1068
        if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE' . $term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (isModEnabled('receiptpr...') && $linestoprint > 0, Probably Intended Meaning: isModEnabled('receiptpri...' && $linestoprint > 0)
Loading history...
1069
            $invoice->fetch($placeid); //Reload object before send to printer
1070
            $printer->orderprinter = 1;
1071
            echo "<script>";
1072
            echo "var orderprinter1esc='";
1073
            $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
1074
            echo "';</script>";
1075
        }
1076
        $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='4' where special_code='1' and fk_facture=" . $invoice->id; // Set as printed
1077
        $db->query($sql);
1078
        $invoice->fetch($placeid); //Reload object after set lines as printed
1079
        $linestoprint = 0;
1080
1081
        foreach ($invoice->lines as $line) {
1082
            if ($line->special_code == "4") {
1083
                continue;
1084
            }
1085
            $c = new Categorie($db);
1086
            $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1087
            $result = array_intersect($catsprinter2, $existing);
1088
            $count = count($result);
1089
            if ($count > 0) {
1090
                $linestoprint++;
1091
                $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='2' where rowid=" . $line->id; //Set to print on printer 2
1092
                $db->query($sql);
1093
                $order_receipt_printer2 .= '<tr>' . $line->product_label . '<td class="right">' . $line->qty;
1094
                if (!empty($line->array_options['options_order_notes'])) {
1095
                    $order_receipt_printer2 .= "<br>(" . $line->array_options['options_order_notes'] . ")";
1096
                }
1097
                $order_receipt_printer2 .= '</td></tr>';
1098
            }
1099
        }
1100
        if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE' . $term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (isModEnabled('receiptpr...') && $linestoprint > 0, Probably Intended Meaning: isModEnabled('receiptpri...' && $linestoprint > 0)
Loading history...
1101
            $invoice->fetch($placeid); //Reload object before send to printer
1102
            $printer->orderprinter = 2;
1103
            echo "<script>";
1104
            echo "var orderprinter2esc='";
1105
            $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
1106
            echo "';</script>";
1107
        }
1108
        $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='4' where special_code='2' and fk_facture=" . $invoice->id; // Set as printed
1109
        $db->query($sql);
1110
        $invoice->fetch($placeid); //Reload object after set lines as printed
1111
        $linestoprint = 0;
1112
1113
        foreach ($invoice->lines as $line) {
1114
            if ($line->special_code == "4") {
1115
                continue;
1116
            }
1117
            $c = new Categorie($db);
1118
            $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1119
            $result = array_intersect($catsprinter3, $existing);
1120
            $count = count($result);
1121
            if ($count > 0) {
1122
                $linestoprint++;
1123
                $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='3' where rowid=" . $line->id; //Set to print on printer 3
1124
                $db->query($sql);
1125
                $order_receipt_printer3 .= '<tr>' . $line->product_label . '<td class="right">' . $line->qty;
1126
                if (!empty($line->array_options['options_order_notes'])) {
1127
                    $order_receipt_printer3 .= "<br>(" . $line->array_options['options_order_notes'] . ")";
1128
                }
1129
                $order_receipt_printer3 .= '</td></tr>';
1130
            }
1131
        }
1132
        if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE' . $term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (isModEnabled('receiptpr...') && $linestoprint > 0, Probably Intended Meaning: isModEnabled('receiptpri...' && $linestoprint > 0)
Loading history...
1133
            $invoice->fetch($placeid); //Reload object before send to printer
1134
            $printer->orderprinter = 3;
1135
            echo "<script>";
1136
            echo "var orderprinter3esc='";
1137
            $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
1138
            echo "';</script>";
1139
        }
1140
        $sql = "UPDATE " . MAIN_DB_PREFIX . "facturedet set special_code='4' where special_code='3' and fk_facture=" . $invoice->id; // Set as printed
1141
        $db->query($sql);
1142
        $invoice->fetch($placeid); //Reload object after set lines as printed
1143
    }
1144
1145
    $sectionwithinvoicelink = '';
1146
    if (($action == "valid" || $action == "history" || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
1147
        $sectionwithinvoicelink .= '<!-- Section with invoice link -->' . "\n";
1148
        $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
1149
        $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice') . " - ";
1150
        $remaintopay = $invoice->getRemainToPay();
1151
        if ($remaintopay > 0) {
1152
            $sectionwithinvoicelink .= $langs->trans('RemainToPay') . ': <span class="amountremaintopay" style="font-size: unset">' . price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency) . '</span>';
1153
        } else {
1154
            if ($invoice->paye) {
1155
                $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">' . $langs->trans("Paid") . '</span>';
1156
            } else {
1157
                $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
1158
            }
1159
        }
1160
1161
        $sectionwithinvoicelink .= '</span><br>';
1162
        if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1163
            $sectionwithinvoicelink .= ' <a target="_blank" class="button" href="' . constant('BASE_URL') . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
1164
        } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1165
            if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1166
                $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector(' . $placeid . ')">' . $langs->trans('PrintTicket') . '</button>';
1167
            } else {
1168
                $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting(' . $placeid . ')">' . $langs->trans('PrintTicket') . '</button>';
1169
            }
1170
        } elseif ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE' . $term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
1171
            $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting(' . $placeid . ')">' . $langs->trans('PrintTicket') . '</button>';
1172
        } else {
1173
            $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print(' . $placeid . ')">' . $langs->trans('PrintTicket') . '</button>';
1174
            if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
1175
                $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox(' . $placeid . ', \'without_details\')">' . $langs->trans('PrintWithoutDetails') . '</button>';
1176
            }
1177
            if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
1178
                $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print(' . $placeid . ', 1)">' . $langs->trans('GiftReceipt') . '</button>';
1179
            }
1180
        }
1181
        if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && getDolGlobalInt('TAKEPOS_EMAIL_TEMPLATE_INVOICE') > 0) {
1182
            $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket(' . $placeid . ')">' . $langs->trans('SendTicket') . '</button>';
1183
        }
1184
1185
        if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
1186
            $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
1187
        }
1188
    }
1189
}
1190
1191
1192
/*
1193
 * View
1194
 */
1195
1196
$form = new Form($db);
1197
1198
// llxHeader
1199
if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1200
    $title = 'TakePOS - Dolibarr ' . DOL_VERSION;
1201
    if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
1202
        $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
1203
    }
1204
    $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
1205
	<meta name="apple-mobile-web-app-capable" content="yes">
1206
	<meta name="mobile-web-app-capable" content="yes">
1207
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
1208
    $arrayofcss = array(
1209
        '/takepos/css/pos.css.php',
1210
    );
1211
    $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
1212
    $disablejs = 0;
1213
    $disablehead = 0;
1214
    top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1215
1216
    print '<body>' . "\n";
1217
} else {
1218
    top_httphead('text/html', 1);
1219
}
1220
1221
?>
1222
<!-- invoice.php -->
1223
<script type="text/javascript">
1224
var selectedline=0;
1225
var selectedtext="";
1226
<?php if ($action == "valid") {
1227
    echo "var place=0;";
1228
}?> // Set to default place after close sale
1229
var placeid=<?php echo($placeid > 0 ? $placeid : 0); ?>;
1230
$(document).ready(function() {
1231
    var idoflineadded = <?php echo(empty($idoflineadded) ? 0 : $idoflineadded); ?>;
1232
1233
    $('.posinvoiceline').click(function(){
1234
        console.log("Click done on "+this.id);
1235
        $('.posinvoiceline').removeClass("selected");
1236
        $(this).addClass("selected");
1237
        if (!this.id) {
1238
            return;
1239
        }
1240
        if (selectedline == this.id) {
1241
            return; // If is already selected
1242
        } else {
1243
            selectedline = this.id;
1244
        }
1245
        selectedtext=$('#'+selectedline).find("td:first").html();
1246
        <?php
1247
        if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1248
            print '$("#phonediv1").load("' . constant('BASE_URL') . '/takepos/public/auto_order.php?action=editline&token=' . newToken() . '&placeid="+placeid+"&selectedline="+selectedline, function() {
1249
			});';
1250
        }
1251
        ?>
1252
    });
1253
1254
    /* Autoselect the line */
1255
    if (idoflineadded > 0)
1256
    {
1257
        console.log("Auto select "+idoflineadded);
1258
        $('.posinvoiceline#'+idoflineadded).click();
1259
    }
1260
<?php
1261
1262
if ($action == "order" && !empty($order_receipt_printer1)) {
1263
    if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1264
        ?>
1265
        $.ajax({
1266
            type: "POST",
1267
            url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
1268
            data: 'invoice='+orderprinter1esc
1269
        });
1270
        <?php
1271
    } else {
1272
        ?>
1273
        $.ajax({
1274
            type: "POST",
1275
            url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1276
            data: '<?php
1277
            print $headerorder . $order_receipt_printer1 . $footerorder; ?>'
1278
        });
1279
        <?php
1280
    }
1281
}
1282
1283
if ($action == "order" && !empty($order_receipt_printer2)) {
1284
    if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1285
        ?>
1286
        $.ajax({
1287
            type: "POST",
1288
            url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
1289
            data: 'invoice='+orderprinter2esc
1290
        });
1291
        <?php
1292
    } else {
1293
        ?>
1294
        $.ajax({
1295
            type: "POST",
1296
            url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
1297
            data: '<?php
1298
            print $headerorder . $order_receipt_printer2 . $footerorder; ?>'
1299
        });
1300
        <?php
1301
    }
1302
}
1303
1304
if ($action == "order" && !empty($order_receipt_printer3)) {
1305
    if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1306
        ?>
1307
        $.ajax({
1308
            type: "POST",
1309
            url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
1310
            data: 'invoice='+orderprinter3esc
1311
        });
1312
        <?php
1313
    }
1314
}
1315
1316
// Set focus to search field
1317
if ($action == "search" || $action == "valid") {
1318
    ?>
1319
    parent.ClearSearch(true);
1320
    <?php
1321
}
1322
1323
1324
if ($action == "temp" && !empty($ticket_printer1)) {
1325
    ?>
1326
    $.ajax({
1327
        type: "POST",
1328
        url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1329
        data: '<?php
1330
        print $header_soc . $header_ticket . $body_ticket . $ticket_printer1 . $ticket_total . $footer_ticket; ?>'
1331
    });
1332
    <?php
1333
}
1334
1335
if ($action == "search") {
1336
    ?>
1337
    $('#search').focus();
1338
    <?php
1339
}
1340
1341
?>
1342
1343
});
1344
1345
function SendTicket(id)
1346
{
1347
    console.log("Open box to select the Print/Send form");
1348
    $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1349
    return true;
1350
}
1351
1352
function PrintBox(id, action) {
1353
    console.log("Open box before printing");
1354
    $.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"); ?>"});
1355
    return true;
1356
}
1357
1358
function Print(id, gift){
1359
    console.log("Call Print() to generate the receipt.");
1360
    $.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")); ?>'});
1361
    return true;
1362
}
1363
1364
function TakeposPrinting(id){
1365
    var receipt;
1366
    console.log("TakeposPrinting" + id);
1367
    $.get("receipt.php?facid="+id, function(data, status) {
1368
        receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1369
        $.ajax({
1370
            type: "POST",
1371
            url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1372
            data: receipt
1373
        });
1374
    });
1375
    return true;
1376
}
1377
1378
function TakeposConnector(id){
1379
    console.log("TakeposConnector" + id);
1380
    $.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) {
1381
        $.ajax({
1382
            type: "POST",
1383
            url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1384
            data: 'invoice='+data
1385
        });
1386
    });
1387
    return true;
1388
}
1389
1390
// Call the ajax to execute the print.
1391
// With some external module another method may be called.
1392
function DolibarrTakeposPrinting(id) {
1393
    console.log("DolibarrTakeposPrinting Printing invoice ticket " + id);
1394
    $.ajax({
1395
        type: "GET",
1396
        data: { token: '<?php echo currentToken(); ?>' },
1397
        url: "<?php print constant('BASE_URL') . '/takepos/ajax/ajax.php?action=printinvoiceticket&token=' . newToken() . '&term=' . urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '') . '&id='; ?>" + id,
1398
1399
    });
1400
    return true;
1401
}
1402
1403
function CreditNote() {
1404
    $("#poslines").load("invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() { });
1405
    return true;
1406
}
1407
1408
function SetNote() {
1409
    $("#poslines").load("invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1410
    return true;
1411
}
1412
1413
1414
$( document ).ready(function() {
1415
    console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1415
    console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo /** @scrutinizer ignore-deprecated */ $invoice->statut; ?>");

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1416
1417
    <?php
1418
    $s = $langs->trans("Customer");
1419
    if ($invoice->id > 0 && ($invoice->socid != getDolGlobalString($constforcompanyid))) {
1420
        $s = $soc->name;
1421
        if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT')) {
1422
            $contactids = $invoice->getIdContact('external', 'BILLING');
1423
            $contactid = $contactids[0];
1424
            if ($contactid > 0) {
1425
                $contact = new Contact($db);
1426
                $contact->fetch($contactid);
1427
                $s .= " - " . $contact->getFullName($langs);
1428
            }
1429
        }
1430
    }
1431
    ?>
1432
1433
    $("#customerandsales").html('');
1434
    $("#shoppingcart").html('');
1435
1436
    <?php if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT') == 0) { ?>
1437
        $("#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>');
1438
    <?php } else { ?>
1439
        $("#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>');
1440
    <?php } ?>
1441
1442
    <?php
1443
    $sql = "SELECT rowid, datec, ref FROM " . MAIN_DB_PREFIX . "facture";
1444
    $sql .= " WHERE entity IN (" . getEntity('invoice') . ")";
1445
    if (!getDolGlobalString('TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED')) {
1446
        // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1447
        $sql .= " AND ref LIKE '(PROV-POS" . $db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '') . "-0%'";
1448
    } else {
1449
        // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1450
        $sql .= " AND pos_source = '" . $db->escape($_SESSION["takeposterminal"]) . "'";
1451
        $sql .= " AND module_source = 'takepos'";
1452
    }
1453
1454
    $sql .= $db->order('datec', 'ASC');
1455
    $resql = $db->query($sql);
1456
    if ($resql) {
1457
        $max_sale = 0;
1458
        while ($obj = $db->fetch_object($resql)) {
1459
            echo '$("#shoppingcart").append(\'';
1460
            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=\\\'';
1461
            $num_sale = str_replace(")", "", str_replace("(PROV-POS" . $_SESSION["takeposterminal"] . "-", "", $obj->ref));
1462
            echo $num_sale;
1463
            if (str_replace("-", "", $num_sale) > $max_sale) {
1464
                $max_sale = str_replace("-", "", $num_sale);
1465
            }
1466
            echo '\\\'; invoiceid=\\\'';
1467
            echo $obj->rowid;
1468
            echo '\\\'; Refresh();">';
1469
            if ($placeid == $obj->rowid) {
1470
                echo '<span class="basketselected">';
1471
            } else {
1472
                echo '<span class="basketnotselected">';
1473
            }
1474
            echo '<span class="fa fa-shopping-cart paddingright"></span>' . dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1475
            echo '</span>';
1476
            echo '</a>\');';
1477
        }
1478
        echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1479
        echo $max_sale + 1;
1480
        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>\');';
1481
    } else {
1482
        dol_print_error($db);
1483
    }
1484
1485
    $s = '';
1486
1487
    $idwarehouse = 0;
1488
    $constantforkey = 'CASHDESK_NO_DECREASE_STOCK' . (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1489
    if (isModEnabled('stock')) {
1490
        if (getDolGlobalString($constantforkey) != "1") {
1491
            $constantforkey = 'CASHDESK_ID_WAREHOUSE' . (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1492
            $idwarehouse = getDolGlobalString($constantforkey);
1493
            if ($idwarehouse > 0) {
1494
                $s = '<span class="small">';
1495
                $warehouse = new Entrepot($db);
1496
                $warehouse->fetch($idwarehouse);
1497
                $s .= '<span class="hideonsmartphone">' . $langs->trans("Warehouse") . '<br></span>' . $warehouse->ref;
1498
                if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1499
                    $s .= ' (' . $langs->trans("Closed") . ')';
1500
                }
1501
                $s .= '</span>';
1502
                print "$('#infowarehouse').html('" . dol_escape_js($s) . "');";
1503
                print '$("#infowarehouse").css("display", "inline-block");';
1504
            } else {
1505
                $s = '<span class="small hideonsmartphone">';
1506
                $s .= $langs->trans("StockChangeDisabled") . '<br>' . $langs->trans("NoWarehouseDefinedForTerminal");
1507
                $s .= '</span>';
1508
                print "$('#infowarehouse').html('" . dol_escape_js($s) . "');";
1509
                if (!empty($conf->dol_optimize_smallscreen)) {
1510
                    print '$("#infowarehouse").css("display", "none");';
1511
                }
1512
            }
1513
        } else {
1514
            $s = '<span class="small hideonsmartphone">' . $langs->trans("StockChangeDisabled") . '</span>';
1515
            print "$('#infowarehouse').html('" . dol_escape_js($s) . "');";
1516
            if (!empty($conf->dol_optimize_smallscreen)) {
1517
                print '$("#infowarehouse").css("display", "none");';
1518
            }
1519
        }
1520
    }
1521
1522
1523
    // Module Adherent
1524
    $s = '';
1525
    if (isModEnabled('member') && $invoice->socid > 0 && $invoice->socid != getDolGlobalInt($constforcompanyid)) {
1526
        $s = '<span class="small">';
1527
        $langs->load("members");
1528
        $s .= $langs->trans("Member") . ': ';
1529
        $adh = new Adherent($db);
1530
        $result = $adh->fetch('', '', $invoice->socid);
1531
        if ($result > 0) {
1532
            $adh->ref = $adh->getFullName($langs);
1533
            if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1533
            if (empty(/** @scrutinizer ignore-deprecated */ $adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1534
                $s .= "<s>";
1535
            }
1536
            $s .= $adh->getFullName($langs);
1537
            $s .= ' - ' . $adh->type;
1538
            if ($adh->datefin) {
1539
                $s .= '<br>' . $langs->trans("SubscriptionEndDate") . ': ' . dol_print_date($adh->datefin, 'day');
1540
                if ($adh->hasDelay()) {
1541
                    $s .= " " . img_warning($langs->trans("Late"));
1542
                }
1543
            } else {
1544
                $s .= '<br>' . $langs->trans("SubscriptionNotReceived");
1545
                if ($adh->statut > 0) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1545
                if (/** @scrutinizer ignore-deprecated */ $adh->statut > 0) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1546
                    $s .= " " . img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1547
                }
1548
            }
1549
            if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$statut has been deprecated: Use $status instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1549
            if (empty(/** @scrutinizer ignore-deprecated */ $adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1550
                $s .= "</s>";
1551
            }
1552
        } else {
1553
            $s .= '<br>' . $langs->trans("ThirdpartyNotLinkedToMember");
1554
        }
1555
        $s .= '</span>';
1556
    }
1557
    ?>
1558
    $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1559
1560
});
1561
1562
1563
<?php
1564
if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
1565
    echo "function CustomerDisplay(){";
1566
    echo "var line1='" . $CUSTOMER_DISPLAY_line1 . "'.substring(0,20);";
1567
    echo "line1=line1.padEnd(20);";
1568
    echo "var line2='" . $CUSTOMER_DISPLAY_line2 . "'.substring(0,20);";
1569
    echo "line2=line2.padEnd(20);";
1570
    echo "$.ajax({
1571
		type: 'GET',
1572
		data: { text: line1+line2 },
1573
		url: '" . getDolGlobalString('TAKEPOS_PRINT_SERVER') . "/display/index.php',
1574
	});";
1575
    echo "}";
1576
}
1577
?>
1578
1579
</script>
1580
1581
<?php
1582
// Add again js for footer because this content is injected into index.php page so all init
1583
// for tooltip and other js beautifiers must be reexecuted too.
1584
if (!empty($conf->use_javascript_ajax)) {
1585
    print "\n" . '<!-- Includes JS Footer of Dolibarr -->' . "\n";
1586
    print '<script src="' . constant('BASE_URL') . '/core/js/lib_foot.js.php?lang=' . $langs->defaultlang . '"></script>' . "\n";
1587
}
1588
1589
$usediv = (GETPOST('format') == 'div');
1590
1591
print '<!-- 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";
1592
print '<div class="div-table-responsive-no-min invoice">';
1593
if ($usediv) {
1594
    print '<div id="tablelines">';
1595
} else {
1596
    print '<table id="tablelines" class="noborder noshadow postablelines centpercent">';
1597
}
1598
if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1599
    if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1600
        print '<tr><td colspan="5">' . $sectionwithinvoicelink . '</td></tr>';
1601
    } else {
1602
        print '<tr><td colspan="4">' . $sectionwithinvoicelink . '</td></tr>';
1603
    }
1604
}
1605
1606
// Show the list of selected product
1607
if (!$usediv) {
1608
    print '<tr class="liste_titre nodrag nodrop">';
1609
    print '<td class="linecoldescription">';
1610
}
1611
// In phone version only show when it is invoice page
1612
if (empty($mobilepage) || $mobilepage == "invoice") {
1613
    print '<!-- hidden var used by some js functions -->';
1614
    print '<input type="hidden" name="invoiceid" id="invoiceid" value="' . $invoice->id . '">';
1615
    print '<input type="hidden" name="thirdpartyid" id="thirdpartyid" value="' . $invoice->socid . '">';
1616
}
1617
if (!$usediv) {
1618
    if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1619
        $sql = "SELECT floor, label FROM " . MAIN_DB_PREFIX . "takepos_floor_tables where rowid=" . ((int) $place);
1620
        $resql = $db->query($sql);
1621
        $obj = $db->fetch_object($resql);
1622
        if ($obj) {
1623
            $label = $obj->label;
1624
            $floor = $obj->floor;
1625
        }
1626
        if ($mobilepage == "invoice" || $mobilepage == "") {
1627
            // If not on smartphone version or if it is the invoice page
1628
            //print 'mobilepage='.$mobilepage;
1629
            print '<span class="opacitymedium">' . $langs->trans('Place') . "</span> <b>" . (empty($label) ? '?' : $label) . "</b><br>";
1630
            print '<span class="opacitymedium">' . $langs->trans('Floor') . "</span> <b>" . (empty($floor) ? '?' : $floor) . "</b>";
1631
        }
1632
    }
1633
    print '</td>';
1634
}
1635
1636
// Complete header by hook
1637
$parameters = array();
1638
$reshook = $hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action);    // Note that $action and $object may have been modified by some hooks
1639
if ($reshook < 0) {
1640
    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1641
}
1642
print $hookmanager->resPrint;
1643
1644
if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1645
    if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
1646
        print '<td class="linecolqty right">' . $langs->trans('PriceUHT') . '</td>';
1647
    }
1648
    print '<td class="linecolqty right">' . $langs->trans('ReductionShort') . '</td>';
1649
    print '<td class="linecolqty right">' . $langs->trans('Qty') . '</td>';
1650
    if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1651
        print '<td class="linecolht right nowraponall">';
1652
        print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1653
        // In phone version only show when it is invoice page
1654
        if (empty($mobilepage) || $mobilepage == "invoice") {
1655
            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>';
1656
            if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1657
                //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1658
                $multicurrency = new MultiCurrency($db);
1659
                $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1660
                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>';
1661
            }
1662
        }
1663
        print '</td>';
1664
    }
1665
    print '<td class="linecolht right nowraponall">';
1666
    print '<span class="opacitymedium small">' . $langs->trans('TotalTTCShort') . '</span><br>';
1667
    // In phone version only show when it is invoice page
1668
    if (empty($mobilepage) || $mobilepage == "invoice") {
1669
        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>';
1670
        if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1671
            //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1672
            $multicurrency = new MultiCurrency($db);
1673
            $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1674
            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>';
1675
        }
1676
    }
1677
    print '</td>';
1678
} elseif ($mobilepage == "invoice") {
1679
    print '<td class="linecolqty right">' . $langs->trans('Qty') . '</td>';
1680
}
1681
if (!$usediv) {
1682
    print "</tr>\n";
1683
}
1684
1685
if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1686
    if ($mobilepage == "cats") {
1687
        $categorie = new Categorie($db);
1688
        $categories = $categorie->get_full_arbo('product');
1689
        $htmlforlines = '';
1690
        foreach ($categories as $row) {
0 ignored issues
show
Bug introduced by
The expression $categories of type integer is not traversable.
Loading history...
1691
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1692
                $htmlforlines .= '<div class="leftcat"';
1693
            } else {
1694
                $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1695
            }
1696
            $htmlforlines .= ' onclick="LoadProducts(' . $row['id'] . ');">';
1697
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1698
                $htmlforlines .= '<img class="imgwrapper" width="33%" src="' . constant('BASE_URL') . '/takepos/public/auto_order.php?genimg=cat&query=cat&id=' . $row['id'] . '"><br>';
1699
            } else {
1700
                $htmlforlines .= '<td class="left">';
1701
            }
1702
            $htmlforlines .= $row['label'];
1703
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1704
                $htmlforlines .= '</div>' . "\n";
1705
            } else {
1706
                $htmlforlines .= '</td></tr>' . "\n";
1707
            }
1708
        }
1709
        print $htmlforlines;
1710
    }
1711
1712
    if ($mobilepage == "products") {
1713
        $object = new Categorie($db);
1714
        $catid = GETPOSTINT('catid');
1715
        $result = $object->fetch($catid);
1716
        $prods = $object->getObjectsInCateg("product");
1717
        $htmlforlines = '';
1718
        foreach ($prods as $row) {
0 ignored issues
show
Bug introduced by
The expression $prods of type integer is not traversable.
Loading history...
1719
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1720
                $htmlforlines .= '<div class="leftcat"';
1721
            } else {
1722
                $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1723
            }
1724
            $htmlforlines .= ' onclick="AddProduct(\'' . $place . '\', ' . $row->id . ')"';
1725
            $htmlforlines .= '>';
1726
            if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1727
                $htmlforlines .= '<img class="imgwrapper" width="33%" src="' . constant('BASE_URL') . '/takepos/public/auto_order.php?genimg=pro&query=pro&id=' . $row->id . '"><br>';
1728
                $htmlforlines .= $row->label . ' ' . price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1729
                $htmlforlines .= '</div>' . "\n";
1730
            } else {
1731
                $htmlforlines .= '<td class="left">';
1732
                $htmlforlines .= $row->label;
1733
                $htmlforlines .= '<div class="right">' . price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency) . '</div>';
1734
                $htmlforlines .= '</td>';
1735
                $htmlforlines .= '</tr>' . "\n";
1736
            }
1737
        }
1738
        print $htmlforlines;
1739
    }
1740
1741
    if ($mobilepage == "places") {
1742
        $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM " . MAIN_DB_PREFIX . "takepos_floor_tables";
1743
        $resql = $db->query($sql);
1744
        $rows = array();
1745
        $htmlforlines = '';
1746
        while ($row = $db->fetch_array($resql)) {
1747
            $rows[] = $row;
1748
            $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1749
            $htmlforlines .= '" onclick="LoadPlace(\'' . $row['label'] . '\')">';
1750
            $htmlforlines .= '<td class="left">';
1751
            $htmlforlines .= $row['label'];
1752
            $htmlforlines .= '</td>';
1753
            $htmlforlines .= '</tr>' . "\n";
1754
        }
1755
        print $htmlforlines;
1756
    }
1757
}
1758
1759
if ($placeid > 0) {
1760
    //In Phone basic layout hide some content depends situation
1761
    if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1762
        return;
1763
    }
1764
1765
    // Loop on each lines on invoice
1766
    if (is_array($invoice->lines) && count($invoice->lines)) {
1767
        print '<!-- invoice.php show lines of invoices -->' . "\n";
1768
        $tmplines = array_reverse($invoice->lines);
1769
        $htmlsupplements = array();
1770
        foreach ($tmplines as $line) {
1771
            if ($line->fk_parent_line != false) {
1772
                $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1773
                if ($line->special_code == "4") {
1774
                    $htmlsupplements[$line->fk_parent_line] .= ' order';
1775
                }
1776
                $htmlsupplements[$line->fk_parent_line] .= '" id="' . $line->id . '"';
1777
                if ($line->special_code == "4") {
1778
                    $htmlsupplements[$line->fk_parent_line] .= ' title="' . dol_escape_htmltag($langs->trans("AlreadyPrinted")) . '"';
1779
                }
1780
                $htmlsupplements[$line->fk_parent_line] .= '>';
1781
                $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1782
                $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1783
                if ($line->product_label) {
1784
                    $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1785
                }
1786
                if ($line->product_label && $line->desc) {
1787
                    $htmlsupplements[$line->fk_parent_line] .= '<br>';
1788
                }
1789
                if ($line->product_label != $line->desc) {
1790
                    $firstline = dolGetFirstLineOfText($line->desc);
1791
                    if ($firstline != $line->desc) {
1792
                        $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1793
                    } else {
1794
                        $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1795
                    }
1796
                }
1797
                $htmlsupplements[$line->fk_parent_line] .= '</td>';
1798
1799
                // complete line by hook
1800
                $parameters = array('line' => $line);
1801
                $reshook = $hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action);    // Note that $action and $object may have been modified by some hooks
1802
                if ($reshook < 0) {
1803
                    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1804
                }
1805
                $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1806
1807
                if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1808
                    $htmlsupplements[$line->fk_parent_line] .= '<td class="right">' . vatrate($line->remise_percent, true) . '</td>';
1809
                    $htmlsupplements[$line->fk_parent_line] .= '<td class="right">' . $line->qty . '</td>';
1810
                    $htmlsupplements[$line->fk_parent_line] .= '<td class="right">' . price($line->total_ttc) . '</td>';
1811
                }
1812
                $htmlsupplements[$line->fk_parent_line] .= '</tr>' . "\n";
1813
                continue;
1814
            }
1815
            $htmlforlines = '';
1816
1817
            $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1818
            if ($line->special_code == "4") {
1819
                $htmlforlines .= ' order';
1820
            }
1821
            $htmlforlines .= '" id="' . $line->id . '"';
1822
            if ($line->special_code == "4") {
1823
                $htmlforlines .= ' title="' . dol_escape_htmltag($langs->trans("AlreadyPrinted")) . '"';
1824
            }
1825
            $htmlforlines .= '>';
1826
            $htmlforlines .= '<td class="left">';
1827
            if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1828
                $htmlforlines .= '<span class="phoneqty">' . $line->qty . "</span> x ";
1829
            }
1830
            if (isset($line->product_type)) {
1831
                if (empty($line->product_type)) {
1832
                    $htmlforlines .= img_object('', 'product') . ' ';
1833
                } else {
1834
                    $htmlforlines .= img_object('', 'service') . ' ';
1835
                }
1836
            }
1837
            $tooltiptext = '';
1838
            if (!getDolGlobalString('TAKEPOS_SHOW_N_FIRST_LINES')) {
1839
                if ($line->product_ref) {
1840
                    $tooltiptext .= '<b>' . $langs->trans("Ref") . '</b> : ' . $line->product_ref . '<br>';
1841
                    $tooltiptext .= '<b>' . $langs->trans("Label") . '</b> : ' . $line->product_label . '<br>';
1842
                    if (!empty($line->batch)) {
1843
                        $tooltiptext .= '<br><b>' . $langs->trans("LotSerial") . '</b> : ' . $line->batch . '<br>';
1844
                    }
1845
                    if (!empty($line->fk_warehouse)) {
1846
                        $tooltiptext .= '<b>' . $langs->trans("Warehouse") . '</b> : ' . $line->fk_warehouse . '<br>';
1847
                    }
1848
                    if ($line->product_label != $line->desc) {
1849
                        if ($line->desc) {
1850
                            $tooltiptext .= '<br>';
1851
                        }
1852
                        $tooltiptext .= $line->desc;
1853
                    }
1854
                }
1855
                if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
1856
                    $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1857
                } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
1858
                    $htmlforlines .= $form->textwithpicto($line->product_ref ? '<b>' . $line->product_ref . '<b>' : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1859
                } else {
1860
                    $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
1861
                }
1862
            } else {
1863
                if ($line->product_ref) {
1864
                    $tooltiptext .= '<b>' . $langs->trans("Ref") . '</b> : ' . $line->product_ref . '<br>';
1865
                    $tooltiptext .= '<b>' . $langs->trans("Label") . '</b> : ' . $line->product_label . '<br>';
1866
                }
1867
                if (!empty($line->batch)) {
1868
                    $tooltiptext .= '<br><b>' . $langs->trans("LotSerial") . '</b> : ' . $line->batch . '<br>';
1869
                }
1870
                if (!empty($line->fk_warehouse)) {
1871
                    $tooltiptext .= '<b>' . $langs->trans("Warehouse") . '</b> : ' . $line->fk_warehouse . '<br>';
1872
                }
1873
1874
                if ($line->product_label) {
1875
                    $htmlforlines .= $line->product_label;
1876
                }
1877
                if ($line->product_label != $line->desc) {
1878
                    if ($line->product_label && $line->desc) {
1879
                        $htmlforlines .= '<br>';
1880
                    }
1881
                    $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
1882
                    if ($firstline != $line->desc) {
1883
                        $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1884
                    } else {
1885
                        $htmlforlines .= $line->desc;
1886
                    }
1887
                }
1888
            }
1889
            if (!empty($line->array_options['options_order_notes'])) {
1890
                $htmlforlines .= "<br>(" . $line->array_options['options_order_notes'] . ")";
1891
            }
1892
            if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1893
                $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>';
1894
            }
1895
            if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1896
                $moreinfo = '';
1897
                $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code) . ': ' . price($line->total_ht);
1898
                if ($line->vat_src_code) {
1899
                    $moreinfo .= '<br>' . $langs->trans("VATCode") . ': ' . $line->vat_src_code;
1900
                }
1901
                $moreinfo .= '<br>' . $langs->transcountry("TotalVAT", $mysoc->country_code) . ': ' . price($line->total_tva);
1902
                $moreinfo .= '<br>' . $langs->transcountry("TotalLT1", $mysoc->country_code) . ': ' . price($line->total_localtax1);
1903
                $moreinfo .= '<br>' . $langs->transcountry("TotalLT2", $mysoc->country_code) . ': ' . price($line->total_localtax2);
1904
                $moreinfo .= '<hr>';
1905
                $moreinfo .= $langs->transcountry("TotalTTC", $mysoc->country_code) . ': ' . price($line->total_ttc);
1906
                //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
1907
                if ($line->date_start || $line->date_end) {
1908
                    $htmlforlines .= '<br><div class="clearboth nowraponall">' . get_date_range($line->date_start, $line->date_end) . '</div>';
1909
                }
1910
                $htmlforlines .= '</td>';
1911
1912
                // complete line by hook
1913
                $parameters = array('line' => $line);
1914
                $reshook = $hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action);    // Note that $action and $object may have been modified by some hooks
1915
                if ($reshook < 0) {
1916
                    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1917
                }
1918
                $htmlforlines .= $hookmanager->resPrint;
1919
1920
                if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
1921
                    $htmlforlines .= '<td class="right">' . price($line->subprice) . '</td>';
1922
                }
1923
                $htmlforlines .= '<td class="right">' . vatrate($line->remise_percent, true) . '</td>';
1924
                $htmlforlines .= '<td class="right">';
1925
                if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire')) {
1926
                    $constantforkey = 'CASHDESK_ID_WAREHOUSE' . $_SESSION["takeposterminal"];
1927
                    if (getDolGlobalString($constantforkey) && $line->fk_product > 0 && !getDolGlobalString('TAKEPOS_HIDE_STOCK_ON_LINE')) {
1928
                        $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
1929
                        $sql .= " FROM " . MAIN_DB_PREFIX . "entrepot as e,";
1930
                        $sql .= " " . MAIN_DB_PREFIX . "product_stock as ps";
1931
                        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = ps.fk_product";
1932
                        $sql .= " WHERE ps.reel != 0";
1933
                        $sql .= " AND ps.fk_entrepot = " . ((int) getDolGlobalString($constantforkey));
1934
                        $sql .= " AND e.entity IN (" . getEntity('stock') . ")";
1935
                        $sql .= " AND ps.fk_product = " . ((int) $line->fk_product);
1936
                        $resql = $db->query($sql);
1937
                        if ($resql) {
1938
                            $stock_real = 0;
1939
                            $obj = $db->fetch_object($resql);
1940
                            if ($obj) {
1941
                                $stock_real = price2num($obj->reel, 'MS');
1942
                            }
1943
                            $htmlforlines .= $line->qty;
1944
                            if ($line->qty && $line->qty > $stock_real) {
1945
                                $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
1946
                            }
1947
                            $htmlforlines .= ' <span class="posstocktoolow">(' . $langs->trans("Stock") . ' ' . $stock_real . ')</span>';
1948
                            if ($line->qty && $line->qty > $stock_real) {
1949
                                $htmlforlines .= "</span>";
1950
                            }
1951
                        } else {
1952
                            dol_print_error($db);
1953
                        }
1954
                    } else {
1955
                        $htmlforlines .= $line->qty;
1956
                    }
1957
                } else {
1958
                    $htmlforlines .= $line->qty;
1959
                }
1960
1961
                $htmlforlines .= '</td>';
1962
                if (getDolGlobalInt('TAKEPOS_SHOW_HT')) {
1963
                    $htmlforlines .= '<td class="right classfortooltip" title="' . $moreinfo . '">';
1964
                    $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
1965
                    if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1966
                        //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1967
                        $multicurrency = new MultiCurrency($db);
1968
                        $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1969
                        $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>';
1970
                    }
1971
                    $htmlforlines .= '</td>';
1972
                }
1973
                $htmlforlines .= '<td class="right classfortooltip" title="' . $moreinfo . '">';
1974
                $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
1975
                if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1976
                    //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1977
                    $multicurrency = new MultiCurrency($db);
1978
                    $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1979
                    $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>';
1980
                }
1981
                $htmlforlines .= '</td>';
1982
            }
1983
            $htmlforlines .= '</tr>' . "\n";
1984
            $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
1985
1986
            print $htmlforlines;
1987
        }
1988
    } else {
1989
        print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">' . $langs->trans("Empty") . '</span></td><td></td>';
1990
        if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1991
            print '<td></td><td></td>';
1992
            if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1993
                print '<td></td>';
1994
            }
1995
        }
1996
        print '</tr>';
1997
    }
1998
} else {      // No invoice generated yet
1999
    print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">' . $langs->trans("Empty") . '</span></td><td></td>';
2000
    if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2001
        print '<td></td><td></td>';
2002
        if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2003
            print '<td></td>';
2004
        }
2005
    }
2006
    print '</tr>';
2007
}
2008
2009
if ($usediv) {
2010
    print '</div>';
2011
} else {
2012
    print '</table>';
2013
}
2014
2015
if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE && !getDolGlobalString('TAKEPOS_NO_CREDITNOTE')) {
2016
    print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">' . $langs->trans('CreateCreditNote') . '</button>';
2017
    if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
2018
        print ' <a target="_blank" class="button" href="' . constant('BASE_URL') . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
2019
    }
2020
}
2021
2022
2023
if ($action == "search") {
2024
    print '<center>
2025
	<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')) . '">
2026
	</center>';
2027
}
2028
2029
print '</div>';
2030
2031
// llxFooter
2032
if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
2033
    print '</body></html>';
2034
}
2035