dolibarr 20.0.5
sellsjournal.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2010 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2007-2010 Jean Heimburger <jean@tiaris.info>
4 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2013 Christophe Battarel <christophe.battarel@altairis.fr>
7 * Copyright (C) 2013-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
8 * Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
9 * Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
10 * Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
11 * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
12 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
34// Load Dolibarr environment
35require '../../main.inc.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
40require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
41require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
42require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php';
43require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
44
45// Load translation files required by the page
46$langs->loadLangs(array("commercial", "compta", "bills", "other", "accountancy", "errors"));
47
48$id_journal = GETPOSTINT('id_journal');
49$action = GETPOST('action', 'aZ09');
50
51$date_startmonth = GETPOST('date_startmonth');
52$date_startday = GETPOST('date_startday');
53$date_startyear = GETPOST('date_startyear');
54$date_endmonth = GETPOST('date_endmonth');
55$date_endday = GETPOST('date_endday');
56$date_endyear = GETPOST('date_endyear');
57$in_bookkeeping = GETPOST('in_bookkeeping');
58if ($in_bookkeeping == '') {
59 $in_bookkeeping = 'notyet';
60}
61
62$now = dol_now();
63
64$hookmanager->initHooks(array('sellsjournal'));
65$parameters = array();
66
67// Security check
68if (!isModEnabled('accounting')) {
70}
71if ($user->socid > 0) {
73}
74if (!$user->hasRight('accounting', 'bind', 'write')) {
76}
77
78$error = 0;
79
80
81/*
82 * Actions
83 */
84
85$reshook = $hookmanager->executeHooks('doActions', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
86
87$accountingaccount = new AccountingAccount($db);
88
89// Get information of journal
90$accountingjournalstatic = new AccountingJournal($db);
91$accountingjournalstatic->fetch($id_journal);
92$journal = $accountingjournalstatic->code;
93$journal_label = $accountingjournalstatic->label;
94
95$date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
96$date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
97
98if (empty($date_startmonth)) {
99 // Period by default on transfer
101 $date_start = $dates['date_start'];
102 $pastmonthyear = $dates['pastmonthyear'];
103 $pastmonth = $dates['pastmonth'];
104}
105if (empty($date_endmonth)) {
106 // Period by default on transfer
108 $date_end = $dates['date_end'];
109 $pastmonthyear = $dates['pastmonthyear'];
110 $pastmonth = $dates['pastmonth'];
111}
112if (getDolGlobalString('ACCOUNTANCY_JOURNAL_USE_CURRENT_MONTH')) {
113 $pastmonth += 1;
114}
115
116if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end))) { // We define date_start and date_end, only if we did not submit the form
117 $date_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
118 $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
119}
120
121$sql = "SELECT f.rowid, f.ref, f.type, f.situation_cycle_ref, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code, f.retained_warranty, f.revenuestamp,";
122$sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code, fd.info_bits,";
123$sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur,";
124if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
125 $sql .= " spe.accountancy_code_customer as code_compta,";
126 $sql .= " spe.accountancy_code_supplier as code_compta_fournisseur,";
127} else {
128 $sql .= " s.code_compta as code_compta,";
129 $sql .= " s.code_compta_fournisseur,";
130}
131$sql .= " p.rowid as pid, p.ref as pref, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte,";
132if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
133 $sql .= " ppe.accountancy_code_sell";
134} else {
135 $sql .= " p.accountancy_code_sell";
136}
137$parameters = array();
138$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
139$sql .= $hookmanager->resPrint;
140$sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
141$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product";
142if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
143 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
144}
145$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
146$sql .= " JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture";
147$sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
148if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
149 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity);
150}
151$parameters = array();
152$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
153$sql .= $hookmanager->resPrint;
154$sql .= " WHERE fd.fk_code_ventilation > 0";
155$sql .= " AND f.entity IN (".getEntity('invoice', 0).')'; // We don't share object for accountancy, we use source object sharing
156$sql .= " AND f.fk_statut > 0";
157if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) { // Non common setup
158 $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_SITUATION.")";
159} else {
160 $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")";
161}
162$sql .= " AND fd.product_type IN (0,1)";
163if ($date_start && $date_end) {
164 $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
165}
166// Define begin binding date
167if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
168 $sql .= " AND f.datef >= '".$db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING'))."'";
169}
170// Already in bookkeeping or not
171if ($in_bookkeeping == 'already') {
172 $sql .= " AND f.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
173 // $sql .= " AND fd.rowid IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account
174}
175if ($in_bookkeeping == 'notyet') {
176 $sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
177 // $sql .= " AND fd.rowid NOT IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account
178}
179$parameters = array();
180$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
181$sql .= $hookmanager->resPrint;
182$sql .= " ORDER BY f.datef, f.ref";
183//print $sql;
184
185dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG);
186$result = $db->query($sql);
187if ($result) {
188 $tabfac = array();
189 $tabht = array();
190 $tabtva = array();
191 $def_tva = array();
192 $tabwarranty = array();
193 $tabrevenuestamp = array();
194 $tabttc = array();
195 $tablocaltax1 = array();
196 $tablocaltax2 = array();
197 $tabcompany = array();
198 $vatdata_cache = array();
199
200 $num = $db->num_rows($result);
201
202 // Variables
203 $cptcli = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER', 'NotDefined');
204 $cpttva = getDolGlobalString('ACCOUNTING_VAT_SOLD_ACCOUNT', 'NotDefined');
205
206 $i = 0;
207 while ($i < $num) {
208 $obj = $db->fetch_object($result);
209
210 // Controls
211 $compta_soc = (!empty($obj->code_compta)) ? $obj->code_compta : $cptcli;
212
213 $compta_prod = $obj->compte;
214 if (empty($compta_prod)) {
215 if ($obj->product_type == 0) {
216 $compta_prod = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT', 'NotDefined');
217 } else {
218 $compta_prod = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT', 'NotDefined');
219 }
220 }
221
222 //$compta_revenuestamp = getDolGlobalString('ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT', 'NotDefined');
223
224 $tax_id = $obj->tva_tx . ($obj->vat_src_code ? ' (' . $obj->vat_src_code . ')' : '');
225 if (array_key_exists($tax_id, $vatdata_cache)) {
226 $vatdata = $vatdata_cache[$tax_id];
227 } else {
228 $vatdata = getTaxesFromId($tax_id, $mysoc, $mysoc, 0);
229 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) {
230 $buyer = new Societe($db);
231 $buyer->fetch($obj->socid);
232 } else {
233 $buyer = null; // We don't need the buyer in this case
234 }
235 $seller = $mysoc;
236 $vatdata = getTaxesFromId($tax_id, $buyer, $seller, 0);
237 $vatdata_cache[$tax_id] = $vatdata;
238 }
239 $compta_tva = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
240 $compta_localtax1 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
241 $compta_localtax2 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
242
243 // Define the array to store the detail of each vat rate and code for lines
244 if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) {
245 $def_tva[$obj->rowid][$compta_tva][vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '')] = (vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''));
246 }
247
248 // Create a compensation rate for situation invoice.
249 $situation_ratio = 1;
250 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
251 if ($obj->situation_cycle_ref) {
252 // Avoid divide by 0
253 if ($obj->situation_percent == 0) {
254 $situation_ratio = 0;
255 } else {
256 $line = new FactureLigne($db);
257 $line->fetch($obj->fdid);
258
259 // Situation invoices handling
260 $prev_progress = $line->get_prev_progress($obj->rowid);
261
262 $situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
263 }
264 }
265 }
266
267 $revenuestamp = (float) price2num($obj->revenuestamp, 'MT');
268
269 // Invoice lines
270 $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
271 $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
272 $tabfac[$obj->rowid]["ref"] = $obj->ref;
273 $tabfac[$obj->rowid]["type"] = $obj->type;
274 $tabfac[$obj->rowid]["description"] = $obj->label_compte;
275 $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
276 $tabfac[$obj->rowid]["revenuestamp"] = $revenuestamp;
277 //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
278
279 // Avoid warnings
280 if (!isset($tabttc[$obj->rowid][$compta_soc])) {
281 $tabttc[$obj->rowid][$compta_soc] = 0;
282 }
283 if (!isset($tabht[$obj->rowid][$compta_prod])) {
284 $tabht[$obj->rowid][$compta_prod] = 0;
285 }
286 if (!isset($tabtva[$obj->rowid][$compta_tva])) {
287 $tabtva[$obj->rowid][$compta_tva] = 0;
288 }
289 if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
290 $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
291 }
292 if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
293 $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
294 }
295
296 // Compensation of data for invoice situation by using $situation_ratio. This works (nearly) for invoice that was not correctly recorded
297 // but it may introduces an error for situation invoices that were correctly saved. There is still rounding problem that differs between
298 // real data we should have stored and result obtained with a compensation.
299 // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact).
300 // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes.
301 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
302 $total_ttc = $obj->total_ttc * $situation_ratio;
303 } else {
304 $total_ttc = $obj->total_ttc;
305 }
306
307 // Move a part of the retained warrenty into the account of warranty
308 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0) {
309 $retained_warranty = (float) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); // Calculate the amount of warrenty for this line (using the percent value)
310 $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty;
311 $total_ttc -= $retained_warranty;
312 }
313
314 $tabttc[$obj->rowid][$compta_soc] += $total_ttc;
315 $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
316 $tva_npr = ((($obj->info_bits & 1) == 1) ? 1 : 0);
317 if (!$tva_npr) { // We ignore line if VAT is a NPR
318 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) {
319 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
320 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
321 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
322 } else {
323 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
324 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio;
325 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio;
326 }
327 }
328
329 $compta_revenuestamp = 'NotDefined';
330 if (!empty($revenuestamp)) {
331 $sqlrevenuestamp = "SELECT accountancy_code_sell FROM ".MAIN_DB_PREFIX."c_revenuestamp";
332 $sqlrevenuestamp .= " WHERE fk_pays = ".((int) $mysoc->country_id);
333 $sqlrevenuestamp .= " AND taux = ".((float) $revenuestamp);
334 $sqlrevenuestamp .= " AND active = 1";
335 $resqlrevenuestamp = $db->query($sqlrevenuestamp);
336
337 if ($resqlrevenuestamp) {
338 $num_rows_revenuestamp = $db->num_rows($resqlrevenuestamp);
339 if ($num_rows_revenuestamp > 1) {
340 dol_print_error($db, 'Failed 2 or more lines for the revenue stamp of your country. Check the dictionary of revenue stamp.');
341 } else {
342 $objrevenuestamp = $db->fetch_object($resqlrevenuestamp);
343 if ($objrevenuestamp) {
344 $compta_revenuestamp = $objrevenuestamp->accountancy_code_sell;
345 }
346 }
347 }
348 }
349
350 if (empty($tabrevenuestamp[$obj->rowid][$compta_revenuestamp]) && !empty($revenuestamp)) {
351 // The revenue stamp was never seen for this invoice id=$obj->rowid
352 $tabttc[$obj->rowid][$compta_soc] += $obj->revenuestamp;
353 $tabrevenuestamp[$obj->rowid][$compta_revenuestamp] = $obj->revenuestamp;
354 }
355
356 $tabcompany[$obj->rowid] = array(
357 'id' => $obj->socid,
358 'name' => $obj->name,
359 'code_client' => $obj->code_client,
360 'code_compta' => $compta_soc
361 );
362
363 $i++;
364
365 // Check for too many lines.
366 if ($i > getDolGlobalInt('ACCOUNTANCY_MAX_TOO_MANY_LINES_TO_PROCESS', 10000)) {
367 $error++;
368 setEventMessages("ErrorTooManyLinesToProcessPleaseUseAMoreSelectiveFilter", null, 'errors');
369 break;
370 }
371 }
372
373 // After the loop on each line
374} else {
375 dol_print_error($db);
376}
377
378
379$errorforinvoice = array();
380
381/*
382// Old way, 1 query for each invoice
383// Loop on all invoices to detect lines without binded code (fk_code_ventilation <= 0)
384foreach ($tabfac as $key => $val) { // Loop on each invoice
385 $sql = "SELECT COUNT(fd.rowid) as nb";
386 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
387 $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
388 $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key);
389 $resql = $db->query($sql);
390 if ($resql) {
391 $obj = $db->fetch_object($resql);
392 if ($obj->nb > 0) {
393 $errorforinvoice[$key] = 'somelinesarenotbound';
394 }
395 } else {
396 dol_print_error($db);
397 }
398}
399*/
400// New way, single query, load all unbound lines
401if (!empty($tabfac)) {
402 $sql = "
403 SELECT
404 fk_facture,
405 COUNT(fd.rowid) as nb
406 FROM
407 ".MAIN_DB_PREFIX."facturedet as fd
408 WHERE
409 fd.product_type <= 2
410 AND fd.fk_code_ventilation <= 0
411 AND fd.total_ttc <> 0
412 AND fk_facture IN (".$db->sanitize(implode(",", array_keys($tabfac))).")
413 GROUP BY fk_facture
414 ";
415 $resql = $db->query($sql);
416 if ($resql) {
417 $num = $db->num_rows($resql);
418 $i = 0;
419 while ($i < $num) {
420 $obj = $db->fetch_object($resql);
421 if ($obj->nb > 0) {
422 $errorforinvoice[$obj->fk_facture] = 'somelinesarenotbound';
423 }
424 $i++;
425 }
426 }
427}
428//var_dump($errorforinvoice);exit;
429
430// Bookkeeping Write
431if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'bind', 'write')) {
432 $now = dol_now();
433 $error = 0;
434
435 $companystatic = new Societe($db);
436 $invoicestatic = new Facture($db);
437
438 $accountingaccountcustomer = new AccountingAccount($db);
439 $accountingaccountcustomer->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
440
441 $accountingaccountcustomerwarranty = new AccountingAccount($db);
442 $accountingaccountcustomerwarranty->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
443
444 foreach ($tabfac as $key => $val) { // Loop on each invoice
445 $errorforline = 0;
446
447 $totalcredit = 0;
448 $totaldebit = 0;
449
450 $db->begin(); // We accept transaction into loop so if we hang, we can continue transfer from last error
451
452 $companystatic->id = $tabcompany[$key]['id'];
453 $companystatic->name = $tabcompany[$key]['name'];
454 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
455 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
456 $companystatic->code_client = $tabcompany[$key]['code_client'];
457 $companystatic->client = 3;
458
459 $invoicestatic->id = $key;
460 $invoicestatic->ref = (string) $val["ref"];
461 $invoicestatic->type = $val["type"];
462 $invoicestatic->close_code = $val["close_code"];
463
464 $date = dol_print_date($val["date"], 'day');
465
466 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
467 $replacedinvoice = 0;
468 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
469 $replacedinvoice = 1;
470 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
471 if ($alreadydispatched) {
472 $replacedinvoice = 2;
473 }
474 }
475
476 // If not already into bookkeeping, we won't add it. If yes, do nothing (should not happen because creating replacement not possible if invoice is accounted)
477 if ($replacedinvoice == 1) {
478 $db->rollback();
479 continue;
480 }
481
482 // Error if some lines are not binded/ready to be journalized
483 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
484 $error++;
485 $errorforline++;
486 setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
487 }
488
489 // Warranty
490 if (!$errorforline && getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY')) {
491 if (isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
492 foreach ($tabwarranty[$key] as $k => $mt) {
493 $bookkeeping = new BookKeeping($db);
494 $bookkeeping->doc_date = $val["date"];
495 $bookkeeping->date_lim_reglement = $val["datereg"];
496 $bookkeeping->doc_ref = $val["ref"];
497 $bookkeeping->date_creation = $now;
498 $bookkeeping->doc_type = 'customer_invoice';
499 $bookkeeping->fk_doc = $key;
500 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
501 $bookkeeping->thirdparty_code = $companystatic->code_client;
502
503 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
504 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
505
506 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
507 $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
508
509 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RetainedWarranty");
510 $bookkeeping->montant = $mt;
511 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
512 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
513 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
514 $bookkeeping->code_journal = $journal;
515 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
516 $bookkeeping->fk_user_author = $user->id;
517 $bookkeeping->entity = $conf->entity;
518
519 $totaldebit += $bookkeeping->debit;
520 $totalcredit += $bookkeeping->credit;
521
522 $result = $bookkeeping->create($user);
523 if ($result < 0) {
524 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
525 $error++;
526 $errorforline++;
527 $errorforinvoice[$key] = 'alreadyjournalized';
528 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
529 } else {
530 $error++;
531 $errorforline++;
532 $errorforinvoice[$key] = 'other';
533 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
534 }
535 }
536 }
537 }
538 }
539
540 // Thirdparty
541 if (!$errorforline) {
542 foreach ($tabttc[$key] as $k => $mt) {
543 $bookkeeping = new BookKeeping($db);
544 $bookkeeping->doc_date = $val["date"];
545 $bookkeeping->date_lim_reglement = $val["datereg"];
546 $bookkeeping->doc_ref = $val["ref"];
547 $bookkeeping->date_creation = $now;
548 $bookkeeping->doc_type = 'customer_invoice';
549 $bookkeeping->fk_doc = $key;
550 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
551 $bookkeeping->thirdparty_code = $companystatic->code_client;
552
553 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
554 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
555
556 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
557 $bookkeeping->label_compte = $accountingaccountcustomer->label;
558
559 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount");
560 $bookkeeping->montant = $mt;
561 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
562 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
563 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
564 $bookkeeping->code_journal = $journal;
565 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
566 $bookkeeping->fk_user_author = $user->id;
567 $bookkeeping->entity = $conf->entity;
568
569 $totaldebit += $bookkeeping->debit;
570 $totalcredit += $bookkeeping->credit;
571
572 $result = $bookkeeping->create($user);
573 if ($result < 0) {
574 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
575 $error++;
576 $errorforline++;
577 $errorforinvoice[$key] = 'alreadyjournalized';
578 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
579 } else {
580 $error++;
581 $errorforline++;
582 $errorforinvoice[$key] = 'other';
583 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
584 }
585 } else {
586 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
587 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
588 $lettering_static = new Lettering($db);
589
590 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
591 }
592 }
593 }
594 }
595
596 // Product / Service
597 if (!$errorforline) {
598 foreach ($tabht[$key] as $k => $mt) {
599 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
600 $accountingaccount = new AccountingAccount($db);
601 $accountingaccount->fetch(0, $k, true);
602 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
603 } else {
604 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
605 }
606
607 $label_account = $accountingaccount->label;
608
609 // get compte id and label
610 if ($accountingaccount->id > 0) {
611 $bookkeeping = new BookKeeping($db);
612 $bookkeeping->doc_date = $val["date"];
613 $bookkeeping->date_lim_reglement = $val["datereg"];
614 $bookkeeping->doc_ref = $val["ref"];
615 $bookkeeping->date_creation = $now;
616 $bookkeeping->doc_type = 'customer_invoice';
617 $bookkeeping->fk_doc = $key;
618 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
619 $bookkeeping->thirdparty_code = $companystatic->code_client;
620
621 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
622 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
623 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
624 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
625 } else {
626 $bookkeeping->subledger_account = '';
627 $bookkeeping->subledger_label = '';
628 }
629 } else {
630 $bookkeeping->subledger_account = '';
631 $bookkeeping->subledger_label = '';
632 }
633
634 $bookkeeping->numero_compte = $k;
635 $bookkeeping->label_compte = $label_account;
636
637 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$label_account;
638 $bookkeeping->montant = $mt;
639 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
640 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
641 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
642 $bookkeeping->code_journal = $journal;
643 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
644 $bookkeeping->fk_user_author = $user->id;
645 $bookkeeping->entity = $conf->entity;
646
647 $totaldebit += $bookkeeping->debit;
648 $totalcredit += $bookkeeping->credit;
649
650 $result = $bookkeeping->create($user);
651 if ($result < 0) {
652 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
653 $error++;
654 $errorforline++;
655 $errorforinvoice[$key] = 'alreadyjournalized';
656 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
657 } else {
658 $error++;
659 $errorforline++;
660 $errorforinvoice[$key] = 'other';
661 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
662 }
663 }
664 }
665 }
666 }
667
668 // VAT
669 if (!$errorforline) {
670 $listoftax = array(0, 1, 2);
671 foreach ($listoftax as $numtax) {
672 $arrayofvat = $tabtva;
673 if ($numtax == 1) {
674 $arrayofvat = $tablocaltax1;
675 }
676 if ($numtax == 2) {
677 $arrayofvat = $tablocaltax2;
678 }
679
680 foreach ($arrayofvat[$key] as $k => $mt) {
681 if ($mt) {
682 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
683 $accountingaccount = new AccountingAccount($db);
684 $accountingaccount->fetch(0, $k, true);
685 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
686 } else {
687 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
688 }
689
690 $label_account = $accountingaccount->label;
691
692 $bookkeeping = new BookKeeping($db);
693 $bookkeeping->doc_date = $val["date"];
694 $bookkeeping->date_lim_reglement = $val["datereg"];
695 $bookkeeping->doc_ref = $val["ref"];
696 $bookkeeping->date_creation = $now;
697 $bookkeeping->doc_type = 'customer_invoice';
698 $bookkeeping->fk_doc = $key;
699 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
700 $bookkeeping->thirdparty_code = $companystatic->code_client;
701
702 $bookkeeping->subledger_account = '';
703 $bookkeeping->subledger_label = '';
704
705 $bookkeeping->numero_compte = $k;
706 $bookkeeping->label_compte = $label_account;
707
708
709 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref;
710 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
711 $bookkeeping->label_operation .= ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
712 $bookkeeping->label_operation .= ($numtax ? ' - Localtax '.$numtax : '');
713
714 $bookkeeping->montant = $mt;
715 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
716 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
717 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
718 $bookkeeping->code_journal = $journal;
719 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
720 $bookkeeping->fk_user_author = $user->id;
721 $bookkeeping->entity = $conf->entity;
722
723 $totaldebit += $bookkeeping->debit;
724 $totalcredit += $bookkeeping->credit;
725
726 $result = $bookkeeping->create($user);
727 if ($result < 0) {
728 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
729 $error++;
730 $errorforline++;
731 $errorforinvoice[$key] = 'alreadyjournalized';
732 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
733 } else {
734 $error++;
735 $errorforline++;
736 $errorforinvoice[$key] = 'other';
737 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
738 }
739 }
740 }
741 }
742 }
743 }
744
745 // Revenue stamp
746 if (!$errorforline) {
747 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
748 foreach ($tabrevenuestamp[$key] as $k => $mt) {
749 if ($mt) {
750 if (empty($conf->cache['accountingaccountincurrententity_rs'][$k])) {
751 $accountingaccount = new AccountingAccount($db);
752 $accountingaccount->fetch(0, $k, true);
753 $conf->cache['accountingaccountincurrententity_rs'][$k] = $accountingaccount;
754 } else {
755 $accountingaccount = $conf->cache['accountingaccountincurrententity_rs'][$k];
756 }
757
758 $label_account = $accountingaccount->label;
759
760 $bookkeeping = new BookKeeping($db);
761 $bookkeeping->doc_date = $val["date"];
762 $bookkeeping->date_lim_reglement = $val["datereg"];
763 $bookkeeping->doc_ref = $val["ref"];
764 $bookkeeping->date_creation = $now;
765 $bookkeeping->doc_type = 'customer_invoice';
766 $bookkeeping->fk_doc = $key;
767 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
768 $bookkeeping->thirdparty_code = $companystatic->code_client;
769
770 $bookkeeping->subledger_account = '';
771 $bookkeeping->subledger_label = '';
772
773 $bookkeeping->numero_compte = $k;
774 $bookkeeping->label_compte = $label_account;
775
776 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp");
777 $bookkeeping->montant = $mt;
778 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
779 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
780 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
781 $bookkeeping->code_journal = $journal;
782 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
783 $bookkeeping->fk_user_author = $user->id;
784 $bookkeeping->entity = $conf->entity;
785
786 $totaldebit += $bookkeeping->debit;
787 $totalcredit += $bookkeeping->credit;
788
789 $result = $bookkeeping->create($user);
790 if ($result < 0) {
791 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
792 $error++;
793 $errorforline++;
794 $errorforinvoice[$key] = 'alreadyjournalized';
795 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
796 } else {
797 $error++;
798 $errorforline++;
799 $errorforinvoice[$key] = 'other';
800 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
801 }
802 }
803 }
804 }
805 }
806 }
807
808 // Protection against a bug on lines before
809 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
810 $error++;
811 $errorforline++;
812 $errorforinvoice[$key] = 'amountsnotbalanced';
813 setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
814 }
815
816 if (!$errorforline) {
817 $db->commit();
818 } else {
819 $db->rollback();
820
821 if ($error >= 10) {
822 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
823 break; // Break in the foreach
824 }
825 }
826 }
827
828 $tabpay = $tabfac;
829
830 if (empty($error) && count($tabpay) > 0) {
831 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
832 } elseif (count($tabpay) == $error) {
833 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
834 } else {
835 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
836 }
837
838 $action = '';
839
840 // Must reload data, so we make a redirect
841 if (count($tabpay) != $error) {
842 $param = 'id_journal='.$id_journal;
843 $param .= '&date_startday='.$date_startday;
844 $param .= '&date_startmonth='.$date_startmonth;
845 $param .= '&date_startyear='.$date_startyear;
846 $param .= '&date_endday='.$date_endday;
847 $param .= '&date_endmonth='.$date_endmonth;
848 $param .= '&date_endyear='.$date_endyear;
849 $param .= '&in_bookkeeping='.$in_bookkeeping;
850 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
851 exit;
852 }
853}
854
855
856
857/*
858 * View
859 */
860
861$form = new Form($db);
862
863// Export
864if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
865 // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL
866 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
867
868 $filename = 'journal';
869 $type_export = 'journal';
870 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
871
872 $companystatic = new Client($db);
873 $invoicestatic = new Facture($db);
874
875 foreach ($tabfac as $key => $val) {
876 $companystatic->id = $tabcompany[$key]['id'];
877 $companystatic->name = $tabcompany[$key]['name'];
878 $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
879 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
880 $companystatic->code_client = $tabcompany[$key]['code_client'];
881 $companystatic->client = 3;
882
883 $invoicestatic->id = $key;
884 $invoicestatic->ref = (string) $val["ref"];
885 $invoicestatic->type = $val["type"];
886 $invoicestatic->close_code = $val["close_code"];
887
888 $date = dol_print_date($val["date"], 'day');
889
890 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
891 $replacedinvoice = 0;
892 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
893 $replacedinvoice = 1;
894 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
895 if ($alreadydispatched) {
896 $replacedinvoice = 2;
897 }
898 }
899
900 // If not already into bookkeeping, we won't add it. If yes, do nothing (should not happen because creating replacement not possible if invoice is accounted)
901 if ($replacedinvoice == 1) {
902 continue;
903 }
904
905 // Warranty
906 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) {
907 foreach ($tabwarranty[$key] as $k => $mt) {
908 //if ($mt) {
909 print '"'.$key.'"'.$sep;
910 print '"'.$date.'"'.$sep;
911 print '"'.$val["ref"].'"'.$sep;
912 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
913 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
914 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
915 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
916 print '"'.$langs->trans("Thirdparty").'"'.$sep;
917 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("RetainedWarranty").'"'.$sep;
918 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
919 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
920 print '"'.$journal.'"';
921 print "\n";
922 //}
923 }
924 }
925
926 // Third party
927 foreach ($tabttc[$key] as $k => $mt) {
928 //if ($mt) {
929 print '"'.$key.'"'.$sep;
930 print '"'.$date.'"'.$sep;
931 print '"'.$val["ref"].'"'.$sep;
932 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
933 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
934 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')).'"'.$sep;
935 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
936 print '"'.$langs->trans("Thirdparty").'"'.$sep;
937 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("Thirdparty").'"'.$sep;
938 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
939 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
940 print '"'.$journal.'"';
941 print "\n";
942 //}
943 }
944
945 // Product / Service
946 foreach ($tabht[$key] as $k => $mt) {
947 $accountingaccount = new AccountingAccount($db);
948 $accountingaccount->fetch(null, $k, true);
949 //if ($mt) {
950 print '"'.$key.'"'.$sep;
951 print '"'.$date.'"'.$sep;
952 print '"'.$val["ref"].'"'.$sep;
953 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
954 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
955 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
956 print '""'.$sep;
957 print '"'.mb_convert_encoding(dol_trunc($accountingaccount->label, 32), 'ISO-8859-1').'"'.$sep;
958 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.dol_trunc($accountingaccount->label, 32).'"'.$sep;
959 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
960 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
961 print '"'.$journal.'"';
962 print "\n";
963 //}
964 }
965
966 // VAT
967 $listoftax = array(0, 1, 2);
968 foreach ($listoftax as $numtax) {
969 $arrayofvat = $tabtva;
970 if ($numtax == 1) {
971 $arrayofvat = $tablocaltax1;
972 }
973 if ($numtax == 2) {
974 $arrayofvat = $tablocaltax2;
975 }
976
977 foreach ($arrayofvat[$key] as $k => $mt) {
978 if ($mt) {
979 print '"'.$key.'"'.$sep;
980 print '"'.$date.'"'.$sep;
981 print '"'.$val["ref"].'"'.$sep;
982 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
983 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
984 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
985 print '""'.$sep;
986 print '"'.$langs->trans("VAT").' - '.implode(', ', $def_tva[$key][$k]).' %"'.$sep;
987 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '').'"'.$sep;
988 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
989 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
990 print '"'.$journal.'"';
991 print "\n";
992 }
993 }
994 }
995
996 // Revenue stamp
997 if (isset($tabrevenuestamp[$key])) {
998 foreach ($tabrevenuestamp[$key] as $k => $mt) {
999 //if ($mt) {
1000 print '"'.$key.'"'.$sep;
1001 print '"'.$date.'"'.$sep;
1002 print '"'.$val["ref"].'"'.$sep;
1003 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
1004 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1005 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1006 print '""'.$sep;
1007 print '"'.$langs->trans("RevenueStamp").'"'.$sep;
1008 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").'"'.$sep;
1009 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1010 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1011 print '"'.$journal.'"';
1012 print "\n";
1013 //}
1014 }
1015 }
1016 }
1017}
1018
1019
1020
1021if (empty($action) || $action == 'view') {
1022 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
1023 $help_url ='EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double#G&eacute;n&eacute;ration_des_&eacute;critures_en_comptabilit&eacute;';
1024 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-sellsjournal');
1025
1026 $nom = $title;
1027 $nomlink = '';
1028 $periodlink = '';
1029 $exportlink = '';
1030 $builddate = dol_now();
1031 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
1032 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
1033 $description .= $langs->trans("DepositsAreNotIncluded");
1034 } else {
1035 $description .= $langs->trans("DepositsAreIncluded");
1036 }
1037
1038 $listofchoices = array('notyet' => $langs->trans("NotYetInGeneralLedger"), 'already' => $langs->trans("AlreadyInGeneralLedger"));
1039 $period = $form->selectDate($date_start ? $date_start : -1, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end ? $date_end : -1, 'date_end', 0, 0, 0, '', 1, 0);
1040 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
1041
1042 $varlink = 'id_journal='.$id_journal;
1043
1044 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
1045
1046 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
1047 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
1048 // Fiscal period test
1049 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
1050 $resql = $db->query($sql);
1051 if ($resql) {
1052 $obj = $db->fetch_object($resql);
1053 if ($obj->nb == 0) {
1054 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
1055 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
1056 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
1057 print $desc;
1058 print '</div>';
1059 }
1060 } else {
1061 dol_print_error($db);
1062 }
1063 }
1064
1065 // Button to write into Ledger
1066 $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
1067 if ($acctCustomerNotConfigured) {
1068 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1069 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
1070 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
1071 print $desc;
1072 print '</div>';
1073 }
1074 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1075 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
1076 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1077 }
1078 if ($acctCustomerNotConfigured) {
1079 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1080 } else {
1081 if ($in_bookkeeping == 'notyet') {
1082 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1083 } else {
1084 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1085 }
1086 }
1087 print '</div>';
1088
1089 // TODO Avoid using js. We can use a direct link with $param
1090 print '
1091 <script type="text/javascript">
1092 function launch_export() {
1093 $("div.fiche form input[name=\"action\"]").val("exportcsv");
1094 $("div.fiche form input[type=\"submit\"]").click();
1095 $("div.fiche form input[name=\"action\"]").val("");
1096 }
1097 function writebookkeeping() {
1098 console.log("click on writebookkeeping");
1099 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1100 $("div.fiche form input[type=\"submit\"]").click();
1101 $("div.fiche form input[name=\"action\"]").val("");
1102 }
1103 </script>';
1104
1105 /*
1106 * Show result array
1107 */
1108 print '<br>';
1109
1110 print '<div class="div-table-responsive">';
1111 print "<table class=\"noborder\" width=\"100%\">";
1112 print "<tr class=\"liste_titre\">";
1113 print "<td>".$langs->trans("Date")."</td>";
1114 print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1115 print "<td>".$langs->trans("AccountAccounting")."</td>";
1116 print "<td>".$langs->trans("SubledgerAccount")."</td>";
1117 print "<td>".$langs->trans("LabelOperation")."</td>";
1118 print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1119 print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1120 print "</tr>\n";
1121
1122 $i = 0;
1123
1124 $companystatic = new Client($db);
1125 $invoicestatic = new Facture($db);
1126
1127 foreach ($tabfac as $key => $val) {
1128 $companystatic->id = $tabcompany[$key]['id'];
1129 $companystatic->name = $tabcompany[$key]['name'];
1130 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
1131 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1132 $companystatic->code_client = $tabcompany[$key]['code_client'];
1133 $companystatic->client = 3;
1134
1135 $invoicestatic->id = $key;
1136 $invoicestatic->ref = (string) $val["ref"];
1137 $invoicestatic->type = $val["type"];
1138 $invoicestatic->close_code = $val["close_code"];
1139
1140 $date = dol_print_date($val["date"], 'day');
1141
1142 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1143 $replacedinvoice = 0;
1144 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1145 $replacedinvoice = 1;
1146 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1147 if ($alreadydispatched) {
1148 $replacedinvoice = 2;
1149 }
1150 }
1151
1152 // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1153 if ($replacedinvoice == 1) {
1154 print '<tr class="oddeven">';
1155 print "<!-- Replaced invoice -->";
1156 print "<td>".$date."</td>";
1157 print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1158 // Account
1159 print "<td>";
1160 print $langs->trans("Replaced");
1161 print '</td>';
1162 // Subledger account
1163 print "<td>";
1164 print '</td>';
1165 print "<td>";
1166 print "</td>";
1167 print '<td class="right"></td>';
1168 print '<td class="right"></td>';
1169 print "</tr>";
1170
1171 $i++;
1172 continue;
1173 }
1174 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
1175 print '<tr class="oddeven">';
1176 print "<!-- Some lines are not bound -->";
1177 print "<td>".$date."</td>";
1178 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1179 // Account
1180 print "<td>";
1181 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
1182 print '</td>';
1183 // Subledger account
1184 print "<td>";
1185 print '</td>';
1186 print "<td>";
1187 print "</td>";
1188 print '<td class="right"></td>';
1189 print '<td class="right"></td>';
1190 print "</tr>";
1191
1192 $i++;
1193 }
1194
1195 // Warranty
1196 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
1197 foreach ($tabwarranty[$key] as $k => $mt) {
1198 print '<tr class="oddeven">';
1199 print "<!-- Thirdparty warranty -->";
1200 print "<td>" . $date . "</td>";
1201 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1202 // Account
1203 print "<td>";
1204 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
1205 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1206 print '<span class="error">' . $langs->trans("MainAccountForRetainedWarrantyNotDefined") . '</span>';
1207 } else {
1208 print $accountoshow;
1209 }
1210 print '</td>';
1211 // Subledger account
1212 print "<td>";
1213 $accountoshow = length_accounta($k);
1214 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1215 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1216 } else {
1217 print $accountoshow;
1218 }
1219 print '</td>';
1220 print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RetainedWarranty") . "</td>";
1221 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1222 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1223 print "</tr>";
1224 }
1225 }
1226
1227 // Third party
1228 foreach ($tabttc[$key] as $k => $mt) {
1229 print '<tr class="oddeven">';
1230 print "<!-- Thirdparty -->";
1231 print "<td>".$date."</td>";
1232 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1233 // Account
1234 print "<td>";
1235 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
1236 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1237 print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
1238 } else {
1239 print $accountoshow;
1240 }
1241 print '</td>';
1242 // Subledger account
1243 print "<td>";
1244 $accountoshow = length_accounta($k);
1245 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1246 print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1247 } else {
1248 print $accountoshow;
1249 }
1250 print '</td>';
1251 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount")."</td>";
1252 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1253 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1254 print "</tr>";
1255
1256 $i++;
1257 }
1258
1259 // Product / Service
1260 foreach ($tabht[$key] as $k => $mt) {
1261 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1262 $accountingaccount = new AccountingAccount($db);
1263 $accountingaccount->fetch(0, $k, true);
1264 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1265 } else {
1266 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1267 }
1268
1269 print '<tr class="oddeven">';
1270 print "<!-- Product -->";
1271 print "<td>".$date."</td>";
1272 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1273 // Account
1274 print "<td>";
1275 $accountoshow = length_accountg($k);
1276 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1277 print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1278 } else {
1279 print $accountoshow;
1280 }
1281 print "</td>";
1282 // Subledger account
1283 print "<td>";
1284 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1285 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1286 print length_accounta($tabcompany[$key]['code_compta']);
1287 }
1288 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1289 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1290 }
1291 print '</td>';
1292 $companystatic->id = $tabcompany[$key]['id'];
1293 $companystatic->name = $tabcompany[$key]['name'];
1294 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$accountingaccount->label."</td>";
1295 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1296 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1297 print "</tr>";
1298
1299 $i++;
1300 }
1301
1302 // VAT
1303 $listoftax = array(0, 1, 2);
1304 foreach ($listoftax as $numtax) {
1305 $arrayofvat = $tabtva;
1306 if ($numtax == 1) {
1307 $arrayofvat = $tablocaltax1;
1308 }
1309 if ($numtax == 2) {
1310 $arrayofvat = $tablocaltax2;
1311 }
1312
1313 // $key is id of invoice
1314 foreach ($arrayofvat[$key] as $k => $mt) {
1315 if ($mt) {
1316 print '<tr class="oddeven">';
1317 print "<!-- VAT -->";
1318 print "<td>".$date."</td>";
1319 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1320 // Account
1321 print "<td>";
1322 $accountoshow = length_accountg($k);
1323 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1324 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType2").')</span>';
1325 } else {
1326 print $accountoshow;
1327 }
1328 print "</td>";
1329 // Subledger account
1330 print "<td>";
1331 print '</td>';
1332 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref;
1333 // $def_tva is array[invoiceid][accountancy_code_sell_of_vat_rate_found][vatrate]=vatrate
1334 //var_dump($arrayofvat[$key]); //var_dump($key); //var_dump($k);
1335 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1336 print ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
1337 print($numtax ? ' - Localtax '.$numtax : '');
1338 print "</td>";
1339 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1340 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1341 print "</tr>";
1342
1343 $i++;
1344 }
1345 }
1346 }
1347
1348 // Revenue stamp
1349 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
1350 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1351 print '<tr class="oddeven">';
1352 print "<!-- Thirdparty revenuestamp -->";
1353 print "<td>" . $date . "</td>";
1354 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1355 // Account
1356 print "<td>";
1357 $accountoshow = length_accountg($k);
1358 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1359 print '<span class="error">' . $langs->trans("MainAccountForRevenueStampSaleNotDefined") . '</span>';
1360 } else {
1361 print $accountoshow;
1362 }
1363 print '</td>';
1364 // Subledger account
1365 print "<td>";
1366 print '</td>';
1367 print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp") . "</td>";
1368 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1369 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1370 print "</tr>";
1371 }
1372 }
1373 }
1374
1375 if (!$i) {
1376 print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1377 }
1378
1379 print "</table>";
1380 print '</div>';
1381
1382 // End of page
1383 llxFooter();
1384}
1385
1386$db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
journalHead($nom, $variant, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='', $moreoptions=array())
Show header of a page used to transfer/dispatch data in accounting.
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage accounting accounts.
Class to manage accounting journals.
Class to manage Ledger (General Ledger and Subledger)
Class to manage customers or prospects.
Class to manage invoices.
const TYPE_REPLACEMENT
Replacement invoice.
const TYPE_SITUATION
Situation invoice.
const TYPE_DEPOSIT
Deposit invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
Class to manage invoice lines.
Class to manage generation of HTML components Only common components must be here.
Class Lettering.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:595
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:614
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getTaxesFromId($vatrate, $buyer=null, $seller=null, $firstparamisid=1)
Get tax (VAT) main information from Id.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.