dolibarr  19.0.0-dev
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-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
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  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <https://www.gnu.org/licenses/>.
25  */
26 
33 // Load Dolibarr environment
34 require '../../main.inc.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
38 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php';
42 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
43 
44 // Load translation files required by the page
45 $langs->loadLangs(array("commercial", "compta", "bills", "other", "accountancy", "errors"));
46 
47 $id_journal = GETPOST('id_journal', 'int');
48 $action = GETPOST('action', 'aZ09');
49 
50 $date_startmonth = GETPOST('date_startmonth');
51 $date_startday = GETPOST('date_startday');
52 $date_startyear = GETPOST('date_startyear');
53 $date_endmonth = GETPOST('date_endmonth');
54 $date_endday = GETPOST('date_endday');
55 $date_endyear = GETPOST('date_endyear');
56 $in_bookkeeping = GETPOST('in_bookkeeping');
57 if ($in_bookkeeping == '') {
58  $in_bookkeeping = 'notyet';
59 }
60 
61 $now = dol_now();
62 
63 $hookmanager->initHooks(array('sellsjournal'));
64 $parameters = array();
65 
66 // Security check
67 if (!isModEnabled('accounting')) {
69 }
70 if ($user->socid > 0) {
72 }
73 if (!$user->hasRight('accounting', 'mouvements', 'lire')) {
75 }
76 
77 
78 /*
79  * Actions
80  */
81 
82 $reshook = $hookmanager->executeHooks('doActions', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
83 
84 $accountingaccount = new AccountingAccount($db);
85 
86 // Get informations of journal
87 $accountingjournalstatic = new AccountingJournal($db);
88 $accountingjournalstatic->fetch($id_journal);
89 $journal = $accountingjournalstatic->code;
90 $journal_label = $accountingjournalstatic->label;
91 
92 $date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
93 $date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
94 
95 if (empty($date_startmonth) || empty($date_endmonth)) {
96  // Period by default on transfer
97  $dates = getDefaultDatesForTransfer();
98  $date_start = $dates['date_start'];
99  $date_end = $dates['date_end'];
100  $pastmonthyear = $dates['pastmonthyear'];
101  $pastmonth = $dates['pastmonth'];
102 }
103 if (getDolGlobalString('ACCOUNTANCY_JOURNAL_USE_CURRENT_MONTH')) {
104  $pastmonth+=1;
105 }
106 
107 if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end))) { // We define date_start and date_end, only if we did not submit the form
108  $date_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
109  $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
110 }
111 
112 $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,";
113 $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,";
114 $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur,";
115 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
116  $sql .= " spe.accountancy_code_customer as code_compta,";
117  $sql .= " spe.accountancy_code_supplier as code_compta_fournisseur,";
118 } else {
119  $sql .= " s.code_compta as code_compta,";
120  $sql .= " s.code_compta_fournisseur,";
121 }
122 $sql .= " p.rowid as pid, p.ref as pref, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte,";
123 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
124  $sql .= " ppe.accountancy_code_sell";
125 } else {
126  $sql .= " p.accountancy_code_sell";
127 }
128 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
129 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product";
130 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
131  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
132 }
133 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
134 $sql .= " JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture";
135 $sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
136 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
137  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity);
138 }
139 $sql .= " WHERE fd.fk_code_ventilation > 0";
140 $sql .= " AND f.entity IN (".getEntity('invoice', 0).')'; // We don't share object for accountancy, we use source object sharing
141 $sql .= " AND f.fk_statut > 0";
142 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) { // Non common setup
143  $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_SITUATION.")";
144 } else {
145  $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")";
146 }
147 $sql .= " AND fd.product_type IN (0,1)";
148 if ($date_start && $date_end) {
149  $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
150 }
151 // Define begin binding date
152 if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
153  $sql .= " AND f.datef >= '".$db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING'))."'";
154 }
155 // Already in bookkeeping or not
156 if ($in_bookkeeping == 'already') {
157  $sql .= " AND f.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
158  // $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
159 }
160 if ($in_bookkeeping == 'notyet') {
161  $sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
162  // $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
163 }
164 $sql .= " ORDER BY f.datef, f.ref";
165 //print $sql; exit;
166 
167 dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG);
168 $result = $db->query($sql);
169 if ($result) {
170  $tabfac = array();
171  $tabht = array();
172  $tabtva = array();
173  $def_tva = array();
174  $tabwarranty = array();
175  $tabttc = array();
176  $tablocaltax1 = array();
177  $tablocaltax2 = array();
178  $tabcompany = array();
179 
180  $num = $db->num_rows($result);
181 
182  // Variables
183  $cptcli = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER', 'NotDefined');
184  $cpttva = getDolGlobalString('ACCOUNTING_VAT_SOLD_ACCOUNT', 'NotDefined');
185 
186  $i = 0;
187  while ($i < $num) {
188  $obj = $db->fetch_object($result);
189 
190  // Controls
191  $compta_soc = (!empty($obj->code_compta)) ? $obj->code_compta : $cptcli;
192 
193  $compta_prod = $obj->compte;
194  if (empty($compta_prod)) {
195  if ($obj->product_type == 0) {
196  $compta_prod = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT', 'NotDefined');
197  } else {
198  $compta_prod = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT', 'NotDefined');
199  }
200  }
201 
202  $vatdata = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0);
203  $compta_tva = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
204  $compta_localtax1 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
205  $compta_localtax2 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
206 
207  // Define array to display all VAT rates that use this accounting account $compta_tva
208  if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) {
209  $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.')' : ''));
210  }
211 
212  // Create a compensation rate.
213  $situation_ratio = 1;
214  if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
215  if ($obj->situation_cycle_ref) {
216  // Avoid divide by 0
217  if ($obj->situation_percent == 0) {
218  $situation_ratio = 0;
219  } else {
220  $line = new FactureLigne($db);
221  $line->fetch($obj->fdid);
222 
223  // Situation invoices handling
224  $prev_progress = $line->get_prev_progress($obj->rowid);
225 
226  $situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
227  }
228  }
229  }
230 
231  // Invoice lines
232  $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
233  $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
234  $tabfac[$obj->rowid]["ref"] = $obj->ref;
235  $tabfac[$obj->rowid]["type"] = $obj->type;
236  $tabfac[$obj->rowid]["description"] = $obj->label_compte;
237  $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
238  //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
239 
240  // Avoid warnings
241  if (!isset($tabttc[$obj->rowid][$compta_soc])) {
242  $tabttc[$obj->rowid][$compta_soc] = 0;
243  }
244  if (!isset($tabht[$obj->rowid][$compta_prod])) {
245  $tabht[$obj->rowid][$compta_prod] = 0;
246  }
247  if (!isset($tabtva[$obj->rowid][$compta_tva])) {
248  $tabtva[$obj->rowid][$compta_tva] = 0;
249  }
250  if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
251  $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
252  }
253  if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
254  $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
255  }
256 
257  // Compensation of data for invoice situation by using $situation_ratio. This works (nearly) for invoice that was not correctly recorded
258  // but it may introduces an error for situation invoices that were correctly saved. There is still rounding problem that differs between
259  // real data we should have stored and result obtained with a compensation.
260  // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact).
261  // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes.
262  $total_ttc = $obj->total_ttc * $situation_ratio;
263  if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0) {
264  $retained_warranty = (double) price2num($total_ttc * $obj->retained_warranty / 100, 'MT');
265  $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty;
266  $total_ttc -= $retained_warranty;
267  }
268  $tabttc[$obj->rowid][$compta_soc] += $total_ttc;
269  $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
270  $tva_npr = (($obj->info_bits & 1 == 1) ? 1 : 0);
271  if (!$tva_npr) { // We ignore line if VAT is a NPR
272  $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
273  }
274  $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio;
275  $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio;
276 
277 
278  $tabcompany[$obj->rowid] = array(
279  'id' => $obj->socid,
280  'name' => $obj->name,
281  'code_client' => $obj->code_client,
282  'code_compta' => $compta_soc
283  );
284 
285  $i++;
286  }
287 } else {
288  dol_print_error($db);
289 }
290 
291 $errorforinvoice = array();
292 
293 // Loop in invoices to detect lines with not binding lines
294 foreach ($tabfac as $key => $val) { // Loop on each invoice
295  $sql = "SELECT COUNT(fd.rowid) as nb";
296  $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
297  $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
298  $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key);
299  $resql = $db->query($sql);
300  if ($resql) {
301  $obj = $db->fetch_object($resql);
302  if ($obj->nb > 0) {
303  $errorforinvoice[$key] = 'somelinesarenotbound';
304  }
305  } else {
306  dol_print_error($db);
307  }
308 }
309 //var_dump($errorforinvoice);exit;
310 
311 
312 // Bookkeeping Write
313 if ($action == 'writebookkeeping') {
314  $now = dol_now();
315  $error = 0;
316 
317  $companystatic = new Societe($db);
318  $invoicestatic = new Facture($db);
319  $accountingaccountcustomer = new AccountingAccount($db);
320 
321  $accountingaccountcustomer->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
322 
323  $accountingaccountcustomerwarranty = new AccountingAccount($db);
324 
325  $accountingaccountcustomerwarranty->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
326 
327  foreach ($tabfac as $key => $val) { // Loop on each invoice
328  $errorforline = 0;
329 
330  $totalcredit = 0;
331  $totaldebit = 0;
332 
333  $db->begin();
334 
335  $companystatic->id = $tabcompany[$key]['id'];
336  $companystatic->name = $tabcompany[$key]['name'];
337  $companystatic->code_compta = $tabcompany[$key]['code_compta'];
338  $companystatic->code_client = $tabcompany[$key]['code_client'];
339  $companystatic->client = 3;
340 
341  $invoicestatic->id = $key;
342  $invoicestatic->ref = (string) $val["ref"];
343  $invoicestatic->type = $val["type"];
344  $invoicestatic->close_code = $val["close_code"];
345 
346  $date = dol_print_date($val["date"], 'day');
347 
348  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
349  $replacedinvoice = 0;
350  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
351  $replacedinvoice = 1;
352  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
353  if ($alreadydispatched) {
354  $replacedinvoice = 2;
355  }
356  }
357 
358  // 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)
359  if ($replacedinvoice == 1) {
360  $db->rollback();
361  continue;
362  }
363 
364  // Error if some lines are not binded/ready to be journalized
365  if ($errorforinvoice[$key] == 'somelinesarenotbound') {
366  $error++;
367  $errorforline++;
368  setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
369  }
370 
371  // Warranty
372  if (!$errorforline) {
373  foreach ($tabwarranty[$key] as $k => $mt) {
374  $bookkeeping = new BookKeeping($db);
375  $bookkeeping->doc_date = $val["date"];
376  $bookkeeping->date_lim_reglement = $val["datereg"];
377  $bookkeeping->doc_ref = $val["ref"];
378  $bookkeeping->date_creation = $now;
379  $bookkeeping->doc_type = 'customer_invoice';
380  $bookkeeping->fk_doc = $key;
381  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
382  $bookkeeping->thirdparty_code = $companystatic->code_client;
383 
384  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
385  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
386 
387  $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
388  $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
389 
390  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty");
391  $bookkeeping->montant = $mt;
392  $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
393  $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
394  $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
395  $bookkeeping->code_journal = $journal;
396  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
397  $bookkeeping->fk_user_author = $user->id;
398  $bookkeeping->entity = $conf->entity;
399 
400  $totaldebit += $bookkeeping->debit;
401  $totalcredit += $bookkeeping->credit;
402 
403  $result = $bookkeeping->create($user);
404  if ($result < 0) {
405  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
406  $error++;
407  $errorforline++;
408  $errorforinvoice[$key] = 'alreadyjournalized';
409  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
410  } else {
411  $error++;
412  $errorforline++;
413  $errorforinvoice[$key] = 'other';
414  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
415  }
416  }
417  }
418  }
419 
420  // Thirdparty
421  if (!$errorforline) {
422  foreach ($tabttc[$key] as $k => $mt) {
423  $bookkeeping = new BookKeeping($db);
424  $bookkeeping->doc_date = $val["date"];
425  $bookkeeping->date_lim_reglement = $val["datereg"];
426  $bookkeeping->doc_ref = $val["ref"];
427  $bookkeeping->date_creation = $now;
428  $bookkeeping->doc_type = 'customer_invoice';
429  $bookkeeping->fk_doc = $key;
430  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
431  $bookkeeping->thirdparty_code = $companystatic->code_client;
432 
433  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
434  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
435 
436  $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
437  $bookkeeping->label_compte = $accountingaccountcustomer->label;
438 
439  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount");
440  $bookkeeping->montant = $mt;
441  $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
442  $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
443  $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
444  $bookkeeping->code_journal = $journal;
445  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
446  $bookkeeping->fk_user_author = $user->id;
447  $bookkeeping->entity = $conf->entity;
448 
449  $totaldebit += $bookkeeping->debit;
450  $totalcredit += $bookkeeping->credit;
451 
452  $result = $bookkeeping->create($user);
453  if ($result < 0) {
454  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
455  $error++;
456  $errorforline++;
457  $errorforinvoice[$key] = 'alreadyjournalized';
458  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
459  } else {
460  $error++;
461  $errorforline++;
462  $errorforinvoice[$key] = 'other';
463  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
464  }
465  } else {
466  if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
467  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
468  $lettering_static = new Lettering($db);
469 
470  $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
471  }
472  }
473  }
474  }
475 
476  // Product / Service
477  if (!$errorforline) {
478  foreach ($tabht[$key] as $k => $mt) {
479  $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache
480  $label_account = $accountingaccount->label;
481 
482  // get compte id and label
483  if ($resultfetch > 0) {
484  $bookkeeping = new BookKeeping($db);
485  $bookkeeping->doc_date = $val["date"];
486  $bookkeeping->date_lim_reglement = $val["datereg"];
487  $bookkeeping->doc_ref = $val["ref"];
488  $bookkeeping->date_creation = $now;
489  $bookkeeping->doc_type = 'customer_invoice';
490  $bookkeeping->fk_doc = $key;
491  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
492  $bookkeeping->thirdparty_code = $companystatic->code_client;
493 
494  if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
495  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
496  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
497  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
498  } else {
499  $bookkeeping->subledger_account = '';
500  $bookkeeping->subledger_label = '';
501  }
502  } else {
503  $bookkeeping->subledger_account = '';
504  $bookkeeping->subledger_label = '';
505  }
506 
507  $bookkeeping->numero_compte = $k;
508  $bookkeeping->label_compte = $label_account;
509 
510  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$label_account;
511  $bookkeeping->montant = $mt;
512  $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
513  $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
514  $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
515  $bookkeeping->code_journal = $journal;
516  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
517  $bookkeeping->fk_user_author = $user->id;
518  $bookkeeping->entity = $conf->entity;
519 
520  $totaldebit += $bookkeeping->debit;
521  $totalcredit += $bookkeeping->credit;
522 
523  $result = $bookkeeping->create($user);
524  if ($result < 0) {
525  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
526  $error++;
527  $errorforline++;
528  $errorforinvoice[$key] = 'alreadyjournalized';
529  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
530  } else {
531  $error++;
532  $errorforline++;
533  $errorforinvoice[$key] = 'other';
534  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
535  }
536  }
537  }
538  }
539  }
540 
541  // VAT
542  if (!$errorforline) {
543  $listoftax = array(0, 1, 2);
544  foreach ($listoftax as $numtax) {
545  $arrayofvat = $tabtva;
546  if ($numtax == 1) {
547  $arrayofvat = $tablocaltax1;
548  }
549  if ($numtax == 2) {
550  $arrayofvat = $tablocaltax2;
551  }
552 
553  foreach ($arrayofvat[$key] as $k => $mt) {
554  if ($mt) {
555  $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
556  $label_account = $accountingaccount->label;
557 
558  $bookkeeping = new BookKeeping($db);
559  $bookkeeping->doc_date = $val["date"];
560  $bookkeeping->date_lim_reglement = $val["datereg"];
561  $bookkeeping->doc_ref = $val["ref"];
562  $bookkeeping->date_creation = $now;
563  $bookkeeping->doc_type = 'customer_invoice';
564  $bookkeeping->fk_doc = $key;
565  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
566  $bookkeeping->thirdparty_code = $companystatic->code_client;
567 
568  $bookkeeping->subledger_account = '';
569  $bookkeeping->subledger_label = '';
570 
571  $bookkeeping->numero_compte = $k;
572  $bookkeeping->label_compte = $label_account;
573 
574  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").' '.join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
575  $bookkeeping->montant = $mt;
576  $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
577  $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
578  $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
579  $bookkeeping->code_journal = $journal;
580  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
581  $bookkeeping->fk_user_author = $user->id;
582  $bookkeeping->entity = $conf->entity;
583 
584  $totaldebit += $bookkeeping->debit;
585  $totalcredit += $bookkeeping->credit;
586 
587  $result = $bookkeeping->create($user);
588  if ($result < 0) {
589  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
590  $error++;
591  $errorforline++;
592  $errorforinvoice[$key] = 'alreadyjournalized';
593  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
594  } else {
595  $error++;
596  $errorforline++;
597  $errorforinvoice[$key] = 'other';
598  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
599  }
600  }
601  }
602  }
603  }
604  }
605 
606  // Protection against a bug on lines before
607  if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
608  $error++;
609  $errorforline++;
610  $errorforinvoice[$key] = 'amountsnotbalanced';
611  setEventMessages('Try to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
612  }
613 
614  if (!$errorforline) {
615  $db->commit();
616  } else {
617  $db->rollback();
618 
619  if ($error >= 10) {
620  setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
621  break; // Break in the foreach
622  }
623  }
624  }
625 
626  $tabpay = $tabfac;
627 
628  if (empty($error) && count($tabpay) > 0) {
629  setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
630  } elseif (count($tabpay) == $error) {
631  setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
632  } else {
633  setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
634  }
635 
636  $action = '';
637 
638  // Must reload data, so we make a redirect
639  if (count($tabpay) != $error) {
640  $param = 'id_journal='.$id_journal;
641  $param .= '&date_startday='.$date_startday;
642  $param .= '&date_startmonth='.$date_startmonth;
643  $param .= '&date_startyear='.$date_startyear;
644  $param .= '&date_endday='.$date_endday;
645  $param .= '&date_endmonth='.$date_endmonth;
646  $param .= '&date_endyear='.$date_endyear;
647  $param .= '&in_bookkeeping='.$in_bookkeeping;
648  header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
649  exit;
650  }
651 }
652 
653 
654 
655 /*
656  * View
657  */
658 
659 $form = new Form($db);
660 
661 // Export
662 if ($action == 'exportcsv') { // ISO and not UTF8 !
663  $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
664 
665  $filename = 'journal';
666  $type_export = 'journal';
667  include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
668 
669  $companystatic = new Client($db);
670  $invoicestatic = new Facture($db);
671 
672  foreach ($tabfac as $key => $val) {
673  $companystatic->id = $tabcompany[$key]['id'];
674  $companystatic->name = $tabcompany[$key]['name'];
675  $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
676  $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
677  $companystatic->code_client = $tabcompany[$key]['code_client'];
678  $companystatic->client = 3;
679 
680  $invoicestatic->id = $key;
681  $invoicestatic->ref = (string) $val["ref"];
682  $invoicestatic->type = $val["type"];
683  $invoicestatic->close_code = $val["close_code"];
684 
685  $date = dol_print_date($val["date"], 'day');
686 
687  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
688  $replacedinvoice = 0;
689  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
690  $replacedinvoice = 1;
691  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
692  if ($alreadydispatched) {
693  $replacedinvoice = 2;
694  }
695  }
696 
697  // 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)
698  if ($replacedinvoice == 1) {
699  continue;
700  }
701 
702  // Warranty
703  foreach ($tabwarranty[$key] as $k => $mt) {
704  //if ($mt) {
705  print '"'.$key.'"'.$sep;
706  print '"'.$date.'"'.$sep;
707  print '"'.$val["ref"].'"'.$sep;
708  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
709  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
710  print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
711  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
712  print '"'.$langs->trans("Thirdparty").'"'.$sep;
713  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").'"'.$sep;
714  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
715  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
716  print '"'.$journal.'"';
717  print "\n";
718  //}
719  }
720 
721  // Third party
722  foreach ($tabttc[$key] as $k => $mt) {
723  //if ($mt) {
724  print '"'.$key.'"'.$sep;
725  print '"'.$date.'"'.$sep;
726  print '"'.$val["ref"].'"'.$sep;
727  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
728  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
729  print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')).'"'.$sep;
730  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
731  print '"'.$langs->trans("Thirdparty").'"'.$sep;
732  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Thirdparty").'"'.$sep;
733  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
734  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
735  print '"'.$journal.'"';
736  print "\n";
737  //}
738  }
739 
740  // Product / Service
741  foreach ($tabht[$key] as $k => $mt) {
742  $accountingaccount = new AccountingAccount($db);
743  $accountingaccount->fetch(null, $k, true);
744  //if ($mt) {
745  print '"'.$key.'"'.$sep;
746  print '"'.$date.'"'.$sep;
747  print '"'.$val["ref"].'"'.$sep;
748  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
749  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
750  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
751  print '""'.$sep;
752  print '"'.utf8_decode(dol_trunc($accountingaccount->label, 32)).'"'.$sep;
753  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.dol_trunc($accountingaccount->label, 32).'"'.$sep;
754  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
755  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
756  print '"'.$journal.'"';
757  print "\n";
758  //}
759  }
760 
761  // VAT
762  $listoftax = array(0, 1, 2);
763  foreach ($listoftax as $numtax) {
764  $arrayofvat = $tabtva;
765  if ($numtax == 1) {
766  $arrayofvat = $tablocaltax1;
767  }
768  if ($numtax == 2) {
769  $arrayofvat = $tablocaltax2;
770  }
771 
772  foreach ($arrayofvat[$key] as $k => $mt) {
773  if ($mt) {
774  print '"'.$key.'"'.$sep;
775  print '"'.$date.'"'.$sep;
776  print '"'.$val["ref"].'"'.$sep;
777  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
778  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
779  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
780  print '""'.$sep;
781  print '"'.$langs->trans("VAT").' - '.join(', ', $def_tva[$key][$k]).' %"'.$sep;
782  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '').'"'.$sep;
783  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
784  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
785  print '"'.$journal.'"';
786  print "\n";
787  }
788  }
789  }
790  }
791 }
792 
793 
794 
795 if (empty($action) || $action == 'view') {
796  $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
797 
798  llxHeader('', dol_string_nohtmltag($title));
799 
800  $nom = $title;
801  $nomlink = '';
802  $periodlink = '';
803  $exportlink = '';
804  $builddate = dol_now();
805  $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
806  if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
807  $description .= $langs->trans("DepositsAreNotIncluded");
808  } else {
809  $description .= $langs->trans("DepositsAreIncluded");
810  }
811 
812  $listofchoices = array('notyet'=>$langs->trans("NotYetInGeneralLedger"), 'already'=>$langs->trans("AlreadyInGeneralLedger"));
813  $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);
814  $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
815 
816  $varlink = 'id_journal='.$id_journal;
817 
818  journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
819 
820  // Button to write into Ledger
821  $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
822  if ($acctCustomerNotConfigured) {
823  print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
824  $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
825  $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
826  print $desc;
827  print '</div>';
828  }
829  print '<div class="tabsAction tabsActionNoBottom centerimp">';
830  if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
831  print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
832  }
833  if ($acctCustomerNotConfigured) {
834  print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
835  } else {
836  if ($in_bookkeeping == 'notyet') {
837  print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
838  } else {
839  print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
840  }
841  }
842  print '</div>';
843 
844  // TODO Avoid using js. We can use a direct link with $param
845  print '
846  <script type="text/javascript">
847  function launch_export() {
848  $("div.fiche form input[name=\"action\"]").val("exportcsv");
849  $("div.fiche form input[type=\"submit\"]").click();
850  $("div.fiche form input[name=\"action\"]").val("");
851  }
852  function writebookkeeping() {
853  console.log("click on writebookkeeping");
854  $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
855  $("div.fiche form input[type=\"submit\"]").click();
856  $("div.fiche form input[name=\"action\"]").val("");
857  }
858  </script>';
859 
860  /*
861  * Show result array
862  */
863  print '<br>';
864 
865  print '<div class="div-table-responsive">';
866  print "<table class=\"noborder\" width=\"100%\">";
867  print "<tr class=\"liste_titre\">";
868  print "<td>".$langs->trans("Date")."</td>";
869  print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
870  print "<td>".$langs->trans("AccountAccounting")."</td>";
871  print "<td>".$langs->trans("SubledgerAccount")."</td>";
872  print "<td>".$langs->trans("LabelOperation")."</td>";
873  print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
874  print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
875  print "</tr>\n";
876 
877  $i = 0;
878 
879  $companystatic = new Client($db);
880  $invoicestatic = new Facture($db);
881 
882  foreach ($tabfac as $key => $val) {
883  $companystatic->id = $tabcompany[$key]['id'];
884  $companystatic->name = $tabcompany[$key]['name'];
885  $companystatic->code_compta = $tabcompany[$key]['code_compta'];
886  $companystatic->code_client = $tabcompany[$key]['code_client'];
887  $companystatic->client = 3;
888 
889  $invoicestatic->id = $key;
890  $invoicestatic->ref = (string) $val["ref"];
891  $invoicestatic->type = $val["type"];
892  $invoicestatic->close_code = $val["close_code"];
893 
894  $date = dol_print_date($val["date"], 'day');
895 
896  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
897  $replacedinvoice = 0;
898  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
899  $replacedinvoice = 1;
900  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
901  if ($alreadydispatched) {
902  $replacedinvoice = 2;
903  }
904  }
905 
906  // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
907  if ($replacedinvoice == 1) {
908  print '<tr class="oddeven">';
909  print "<!-- Replaced invoice -->";
910  print "<td>".$date."</td>";
911  print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
912  // Account
913  print "<td>";
914  print $langs->trans("Replaced");
915  print '</td>';
916  // Subledger account
917  print "<td>";
918  print '</td>';
919  print "<td>";
920  print "</td>";
921  print '<td class="right"></td>';
922  print '<td class="right"></td>';
923  print "</tr>";
924 
925  $i++;
926  continue;
927  }
928  if ($errorforinvoice[$key] == 'somelinesarenotbound') {
929  print '<tr class="oddeven">';
930  print "<!-- Some lines are not bound -->";
931  print "<td>".$date."</td>";
932  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
933  // Account
934  print "<td>";
935  print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
936  print '</td>';
937  // Subledger account
938  print "<td>";
939  print '</td>';
940  print "<td>";
941  print "</td>";
942  print '<td class="right"></td>';
943  print '<td class="right"></td>';
944  print "</tr>";
945 
946  $i++;
947  }
948 
949  // Warranty
950  foreach ($tabwarranty[$key] as $k => $mt) {
951  print '<tr class="oddeven">';
952  print "<!-- Thirdparty warranty -->";
953  print "<td>".$date."</td>";
954  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
955  // Account
956  print "<td>";
957  $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
958  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
959  print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
960  } else {
961  print $accountoshow;
962  }
963  print '</td>';
964  // Subledger account
965  print "<td>";
966  $accountoshow = length_accounta($k);
967  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
968  print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
969  } else {
970  print $accountoshow;
971  }
972  print '</td>';
973  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty")."</td>";
974  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
975  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
976  print "</tr>";
977  }
978 
979  // Third party
980  foreach ($tabttc[$key] as $k => $mt) {
981  print '<tr class="oddeven">';
982  print "<!-- Thirdparty -->";
983  print "<td>".$date."</td>";
984  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
985  // Account
986  print "<td>";
987  $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
988  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
989  print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
990  } else {
991  print $accountoshow;
992  }
993  print '</td>';
994  // Subledger account
995  print "<td>";
996  $accountoshow = length_accounta($k);
997  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
998  print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
999  } else {
1000  print $accountoshow;
1001  }
1002  print '</td>';
1003  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount")."</td>";
1004  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1005  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1006  print "</tr>";
1007 
1008  $i++;
1009  }
1010 
1011  // Product / Service
1012  foreach ($tabht[$key] as $k => $mt) {
1013  $accountingaccount = new AccountingAccount($db);
1014  $accountingaccount->fetch(null, $k, true);
1015 
1016  print '<tr class="oddeven">';
1017  print "<!-- Product -->";
1018  print "<td>".$date."</td>";
1019  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1020  // Account
1021  print "<td>";
1022  $accountoshow = length_accountg($k);
1023  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1024  print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1025  } else {
1026  print $accountoshow;
1027  }
1028  print "</td>";
1029  // Subledger account
1030  print "<td>";
1031  if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1032  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1033  print length_accounta($tabcompany[$key]['code_compta']);
1034  }
1035  } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1036  print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1037  }
1038  print '</td>';
1039  $companystatic->id = $tabcompany[$key]['id'];
1040  $companystatic->name = $tabcompany[$key]['name'];
1041  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$accountingaccount->label."</td>";
1042  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1043  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1044  print "</tr>";
1045 
1046  $i++;
1047  }
1048 
1049  // VAT
1050  $listoftax = array(0, 1, 2);
1051  foreach ($listoftax as $numtax) {
1052  $arrayofvat = $tabtva;
1053  if ($numtax == 1) {
1054  $arrayofvat = $tablocaltax1;
1055  }
1056  if ($numtax == 2) {
1057  $arrayofvat = $tablocaltax2;
1058  }
1059 
1060  foreach ($arrayofvat[$key] as $k => $mt) {
1061  if ($mt) {
1062  print '<tr class="oddeven">';
1063  print "<!-- VAT -->";
1064  print "<td>".$date."</td>";
1065  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1066  // Account
1067  print "<td>";
1068  $accountoshow = length_accountg($k);
1069  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1070  print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("Sale").')</span>';
1071  } else {
1072  print $accountoshow;
1073  }
1074  print "</td>";
1075  // Subledger account
1076  print "<td>";
1077  print '</td>';
1078  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").' '.join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
1079  print "</td>";
1080  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1081  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1082  print "</tr>";
1083 
1084  $i++;
1085  }
1086  }
1087  }
1088  }
1089 
1090  if (!$i) {
1091  print '<tr class="oddeven"><td colspan="6"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1092  }
1093 
1094  print "</table>";
1095  print '</div>';
1096 
1097  // End of page
1098  llxFooter();
1099 }
1100 
1101 $db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
journalHead($nom, $variante, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='')
Show header of a page used to transfer/dispatch data in accounting.
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:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
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...)
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition: date.lib.php:576
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:595
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages.
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 '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
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_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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.