dolibarr  18.0.6
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 
104 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
105  $date_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
106  $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
107 }
108 
109 $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,";
110 $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,";
111 $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur,";
112 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
113  $sql .= " spe.accountancy_code_customer as code_compta,";
114  $sql .= " spe.accountancy_code_supplier as code_compta_fournisseur,";
115 } else {
116  $sql .= " s.code_compta as code_compta,";
117  $sql .= " s.code_compta_fournisseur,";
118 }
119 $sql .= " p.rowid as pid, p.ref as pref, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte,";
120 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
121  $sql .= " ppe.accountancy_code_sell";
122 } else {
123  $sql .= " p.accountancy_code_sell";
124 }
125 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
126 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product";
127 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
128  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
129 }
130 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
131 $sql .= " JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture";
132 $sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
133 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
134  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity);
135 }
136 $sql .= " WHERE fd.fk_code_ventilation > 0";
137 $sql .= " AND f.entity IN (".getEntity('invoice', 0).')'; // We don't share object for accountancy, we use source object sharing
138 $sql .= " AND f.fk_statut > 0";
139 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) { // Non common setup
140  $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_SITUATION.")";
141 } else {
142  $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")";
143 }
144 $sql .= " AND fd.product_type IN (0,1)";
145 if ($date_start && $date_end) {
146  $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
147 }
148 // Define begin binding date
149 if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
150  $sql .= " AND f.datef >= '".$db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING'))."'";
151 }
152 // Already in bookkeeping or not
153 if ($in_bookkeeping == 'already') {
154  $sql .= " AND f.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
155  // $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
156 }
157 if ($in_bookkeeping == 'notyet') {
158  $sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
159  // $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
160 }
161 $sql .= " ORDER BY f.datef, f.ref";
162 //print $sql;
163 
164 dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG);
165 $result = $db->query($sql);
166 if ($result) {
167  $tabfac = array();
168  $tabht = array();
169  $tabtva = array();
170  $def_tva = array();
171  $tabwarranty = array();
172  $tabrevenuestamp = array();
173  $tabttc = array();
174  $tablocaltax1 = array();
175  $tablocaltax2 = array();
176  $tabcompany = array();
177 
178  $num = $db->num_rows($result);
179 
180  // Variables
181  $cptcli = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER', 'NotDefined');
182  $cpttva = getDolGlobalString('ACCOUNTING_VAT_SOLD_ACCOUNT', 'NotDefined');
183 
184  $i = 0;
185  while ($i < $num) {
186  $obj = $db->fetch_object($result);
187 
188  // Controls
189  $compta_soc = (!empty($obj->code_compta)) ? $obj->code_compta : $cptcli;
190 
191  $compta_prod = $obj->compte;
192  if (empty($compta_prod)) {
193  if ($obj->product_type == 0) {
194  $compta_prod = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT', 'NotDefined');
195  } else {
196  $compta_prod = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT', 'NotDefined');
197  }
198  }
199 
200  //$compta_revenuestamp = getDolGlobalString('ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT', 'NotDefined');
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 the array to store the detail of each vat rate and code for lines
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 for situation invoice.
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  $revenuestamp = (double) price2num($obj->revenuestamp, 'MT');
232 
233  // Invoice lines
234  $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
235  $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
236  $tabfac[$obj->rowid]["ref"] = $obj->ref;
237  $tabfac[$obj->rowid]["type"] = $obj->type;
238  $tabfac[$obj->rowid]["description"] = $obj->label_compte;
239  $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
240  $tabfac[$obj->rowid]["revenuestamp"] = $revenuestamp;
241  //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
242 
243  // Avoid warnings
244  if (!isset($tabttc[$obj->rowid][$compta_soc])) {
245  $tabttc[$obj->rowid][$compta_soc] = 0;
246  }
247  if (!isset($tabht[$obj->rowid][$compta_prod])) {
248  $tabht[$obj->rowid][$compta_prod] = 0;
249  }
250  if (!isset($tabtva[$obj->rowid][$compta_tva])) {
251  $tabtva[$obj->rowid][$compta_tva] = 0;
252  }
253  if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
254  $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
255  }
256  if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
257  $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
258  }
259 
260  // Compensation of data for invoice situation by using $situation_ratio. This works (nearly) for invoice that was not correctly recorded
261  // but it may introduces an error for situation invoices that were correctly saved. There is still rounding problem that differs between
262  // real data we should have stored and result obtained with a compensation.
263  // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact).
264  // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes.
265  if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
266  $total_ttc = $obj->total_ttc * $situation_ratio;
267  } else {
268  $total_ttc = $obj->total_ttc;
269  }
270 
271  // Move a part of the retained warrenty into the account of warranty
272  if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0) {
273  $retained_warranty = (double) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); // Calculate the amount of warrenty for this line (using the percent value)
274  $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty;
275  $total_ttc -= $retained_warranty;
276  }
277 
278  $tabttc[$obj->rowid][$compta_soc] += $total_ttc;
279  $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
280  $tva_npr = (($obj->info_bits & 1 == 1) ? 1 : 0);
281  if (!$tva_npr) { // We ignore line if VAT is a NPR
282  $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
283  }
284  $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio;
285  $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio;
286 
287  $compta_revenuestamp = 'NotDefined';
288  if (!empty($revenuestamp)) {
289  $sqlrevenuestamp = "SELECT accountancy_code_sell FROM ".MAIN_DB_PREFIX."c_revenuestamp";
290  $sqlrevenuestamp .= " WHERE fk_pays = ".((int) $mysoc->country_id);
291  $sqlrevenuestamp .= " AND taux = ".((double) $revenuestamp);
292  $sqlrevenuestamp .= " AND active = 1";
293  $resqlrevenuestamp = $db->query($sqlrevenuestamp);
294 
295  if ($resqlrevenuestamp) {
296  $num_rows_revenuestamp = $db->num_rows($resqlrevenuestamp);
297  if ($num_rows_revenuestamp > 1) {
298  dol_print_error($db, 'Failed 2 or more lines for the revenue stamp of your country. Check the dictionary of revenue stamp.');
299  } else {
300  $objrevenuestamp = $db->fetch_object($resqlrevenuestamp);
301  if ($objrevenuestamp) {
302  $compta_revenuestamp = $objrevenuestamp->accountancy_code_sell;
303  }
304  }
305  }
306  }
307 
308  if (empty($tabrevenuestamp[$obj->rowid][$compta_revenuestamp]) && !empty($revenuestamp)) {
309  // The revenue stamp was never seen for this invoice id=$obj->rowid
310  $tabttc[$obj->rowid][$compta_soc] += $obj->revenuestamp;
311  $tabrevenuestamp[$obj->rowid][$compta_revenuestamp] = $obj->revenuestamp;
312  }
313 
314  $tabcompany[$obj->rowid] = array(
315  'id' => $obj->socid,
316  'name' => $obj->name,
317  'code_client' => $obj->code_client,
318  'code_compta' => $compta_soc
319  );
320 
321  $i++;
322  }
323 
324  // After the loop on each line
325 } else {
326  dol_print_error($db);
327 }
328 
329 $errorforinvoice = array();
330 
331 // Loop on all invoices to detect lines without binded code (fk_code_ventilation <= 0)
332 foreach ($tabfac as $key => $val) { // Loop on each invoice
333  $sql = "SELECT COUNT(fd.rowid) as nb";
334  $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
335  $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
336  $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key);
337  $resql = $db->query($sql);
338  if ($resql) {
339  $obj = $db->fetch_object($resql);
340  if ($obj->nb > 0) {
341  $errorforinvoice[$key] = 'somelinesarenotbound';
342  }
343  } else {
344  dol_print_error($db);
345  }
346 }
347 //var_dump($errorforinvoice);exit;
348 
349 
350 // Bookkeeping Write
351 if ($action == 'writebookkeeping') {
352  $now = dol_now();
353  $error = 0;
354 
355  $companystatic = new Societe($db);
356  $invoicestatic = new Facture($db);
357  $accountingaccountcustomer = new AccountingAccount($db);
358 
359  $accountingaccountcustomer->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
360 
361  $accountingaccountcustomerwarranty = new AccountingAccount($db);
362 
363  $accountingaccountcustomerwarranty->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
364 
365  foreach ($tabfac as $key => $val) { // Loop on each invoice
366  $errorforline = 0;
367 
368  $totalcredit = 0;
369  $totaldebit = 0;
370 
371  $db->begin();
372 
373  $companystatic->id = $tabcompany[$key]['id'];
374  $companystatic->name = $tabcompany[$key]['name'];
375  $companystatic->code_compta = $tabcompany[$key]['code_compta'];
376  $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
377  $companystatic->code_client = $tabcompany[$key]['code_client'];
378  $companystatic->client = 3;
379 
380  $invoicestatic->id = $key;
381  $invoicestatic->ref = (string) $val["ref"];
382  $invoicestatic->type = $val["type"];
383  $invoicestatic->close_code = $val["close_code"];
384 
385  $date = dol_print_date($val["date"], 'day');
386 
387  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
388  $replacedinvoice = 0;
389  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
390  $replacedinvoice = 1;
391  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
392  if ($alreadydispatched) {
393  $replacedinvoice = 2;
394  }
395  }
396 
397  // 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)
398  if ($replacedinvoice == 1) {
399  $db->rollback();
400  continue;
401  }
402 
403  // Error if some lines are not binded/ready to be journalized
404  if ($errorforinvoice[$key] == 'somelinesarenotbound') {
405  $error++;
406  $errorforline++;
407  setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
408  }
409 
410  // Warranty
411  if (!$errorforline) {
412  foreach ($tabwarranty[$key] as $k => $mt) {
413  $bookkeeping = new BookKeeping($db);
414  $bookkeeping->doc_date = $val["date"];
415  $bookkeeping->date_lim_reglement = $val["datereg"];
416  $bookkeeping->doc_ref = $val["ref"];
417  $bookkeeping->date_creation = $now;
418  $bookkeeping->doc_type = 'customer_invoice';
419  $bookkeeping->fk_doc = $key;
420  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
421  $bookkeeping->thirdparty_code = $companystatic->code_client;
422 
423  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
424  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
425 
426  $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
427  $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
428 
429  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty");
430  $bookkeeping->montant = $mt;
431  $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
432  $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
433  $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
434  $bookkeeping->code_journal = $journal;
435  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
436  $bookkeeping->fk_user_author = $user->id;
437  $bookkeeping->entity = $conf->entity;
438 
439  $totaldebit += $bookkeeping->debit;
440  $totalcredit += $bookkeeping->credit;
441 
442  $result = $bookkeeping->create($user);
443  if ($result < 0) {
444  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
445  $error++;
446  $errorforline++;
447  $errorforinvoice[$key] = 'alreadyjournalized';
448  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
449  } else {
450  $error++;
451  $errorforline++;
452  $errorforinvoice[$key] = 'other';
453  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
454  }
455  }
456  }
457  }
458 
459  // Thirdparty
460  if (!$errorforline) {
461  foreach ($tabttc[$key] as $k => $mt) {
462  $bookkeeping = new BookKeeping($db);
463  $bookkeeping->doc_date = $val["date"];
464  $bookkeeping->date_lim_reglement = $val["datereg"];
465  $bookkeeping->doc_ref = $val["ref"];
466  $bookkeeping->date_creation = $now;
467  $bookkeeping->doc_type = 'customer_invoice';
468  $bookkeeping->fk_doc = $key;
469  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
470  $bookkeeping->thirdparty_code = $companystatic->code_client;
471 
472  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
473  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
474 
475  $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
476  $bookkeeping->label_compte = $accountingaccountcustomer->label;
477 
478  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount");
479  $bookkeeping->montant = $mt;
480  $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
481  $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
482  $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
483  $bookkeeping->code_journal = $journal;
484  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
485  $bookkeeping->fk_user_author = $user->id;
486  $bookkeeping->entity = $conf->entity;
487 
488  $totaldebit += $bookkeeping->debit;
489  $totalcredit += $bookkeeping->credit;
490 
491  $result = $bookkeeping->create($user);
492  if ($result < 0) {
493  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
494  $error++;
495  $errorforline++;
496  $errorforinvoice[$key] = 'alreadyjournalized';
497  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
498  } else {
499  $error++;
500  $errorforline++;
501  $errorforinvoice[$key] = 'other';
502  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
503  }
504  } else {
505  if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
506  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
507  $lettering_static = new Lettering($db);
508 
509  $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
510  }
511  }
512  }
513  }
514 
515  // Product / Service
516  if (!$errorforline) {
517  foreach ($tabht[$key] as $k => $mt) {
518  $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache
519  $label_account = $accountingaccount->label;
520 
521  // get compte id and label
522  if ($resultfetch > 0) {
523  $bookkeeping = new BookKeeping($db);
524  $bookkeeping->doc_date = $val["date"];
525  $bookkeeping->date_lim_reglement = $val["datereg"];
526  $bookkeeping->doc_ref = $val["ref"];
527  $bookkeeping->date_creation = $now;
528  $bookkeeping->doc_type = 'customer_invoice';
529  $bookkeeping->fk_doc = $key;
530  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
531  $bookkeeping->thirdparty_code = $companystatic->code_client;
532 
533  if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
534  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
535  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
536  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
537  } else {
538  $bookkeeping->subledger_account = '';
539  $bookkeeping->subledger_label = '';
540  }
541  } else {
542  $bookkeeping->subledger_account = '';
543  $bookkeeping->subledger_label = '';
544  }
545 
546  $bookkeeping->numero_compte = $k;
547  $bookkeeping->label_compte = $label_account;
548 
549  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$label_account;
550  $bookkeeping->montant = $mt;
551  $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
552  $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
553  $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
554  $bookkeeping->code_journal = $journal;
555  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
556  $bookkeeping->fk_user_author = $user->id;
557  $bookkeeping->entity = $conf->entity;
558 
559  $totaldebit += $bookkeeping->debit;
560  $totalcredit += $bookkeeping->credit;
561 
562  $result = $bookkeeping->create($user);
563  if ($result < 0) {
564  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
565  $error++;
566  $errorforline++;
567  $errorforinvoice[$key] = 'alreadyjournalized';
568  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
569  } else {
570  $error++;
571  $errorforline++;
572  $errorforinvoice[$key] = 'other';
573  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
574  }
575  }
576  }
577  }
578  }
579 
580  // VAT
581  if (!$errorforline) {
582  $listoftax = array(0, 1, 2);
583  foreach ($listoftax as $numtax) {
584  $arrayofvat = $tabtva;
585  if ($numtax == 1) {
586  $arrayofvat = $tablocaltax1;
587  }
588  if ($numtax == 2) {
589  $arrayofvat = $tablocaltax2;
590  }
591 
592  foreach ($arrayofvat[$key] as $k => $mt) {
593  if ($mt) {
594  $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
595  $label_account = $accountingaccount->label;
596 
597  $bookkeeping = new BookKeeping($db);
598  $bookkeeping->doc_date = $val["date"];
599  $bookkeeping->date_lim_reglement = $val["datereg"];
600  $bookkeeping->doc_ref = $val["ref"];
601  $bookkeeping->date_creation = $now;
602  $bookkeeping->doc_type = 'customer_invoice';
603  $bookkeeping->fk_doc = $key;
604  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
605  $bookkeeping->thirdparty_code = $companystatic->code_client;
606 
607  $bookkeeping->subledger_account = '';
608  $bookkeeping->subledger_label = '';
609 
610  $bookkeeping->numero_compte = $k;
611  $bookkeeping->label_compte = $label_account;
612 
613 
614  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref;
615  $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : join(', ', $def_tva[$key][$k]));
616  $bookkeeping->label_operation .= ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
617  $bookkeeping->label_operation .= ($numtax ? ' - Localtax '.$numtax : '');
618 
619  $bookkeeping->montant = $mt;
620  $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
621  $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
622  $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
623  $bookkeeping->code_journal = $journal;
624  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
625  $bookkeeping->fk_user_author = $user->id;
626  $bookkeeping->entity = $conf->entity;
627 
628  $totaldebit += $bookkeeping->debit;
629  $totalcredit += $bookkeeping->credit;
630 
631  $result = $bookkeeping->create($user);
632  if ($result < 0) {
633  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
634  $error++;
635  $errorforline++;
636  $errorforinvoice[$key] = 'alreadyjournalized';
637  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
638  } else {
639  $error++;
640  $errorforline++;
641  $errorforinvoice[$key] = 'other';
642  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
643  }
644  }
645  }
646  }
647  }
648  }
649 
650  // Revenue stamp
651  if (!$errorforline) {
652  foreach ($tabrevenuestamp[$key] as $k => $mt) {
653  if ($mt) {
654  $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
655  $label_account = $accountingaccount->label;
656 
657  $bookkeeping = new BookKeeping($db);
658  $bookkeeping->doc_date = $val["date"];
659  $bookkeeping->date_lim_reglement = $val["datereg"];
660  $bookkeeping->doc_ref = $val["ref"];
661  $bookkeeping->date_creation = $now;
662  $bookkeeping->doc_type = 'customer_invoice';
663  $bookkeeping->fk_doc = $key;
664  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
665  $bookkeeping->thirdparty_code = $companystatic->code_client;
666 
667  $bookkeeping->subledger_account = '';
668  $bookkeeping->subledger_label = '';
669 
670  $bookkeeping->numero_compte = $k;
671  $bookkeeping->label_compte = $label_account;
672 
673  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp");
674  $bookkeeping->montant = $mt;
675  $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
676  $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
677  $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
678  $bookkeeping->code_journal = $journal;
679  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
680  $bookkeeping->fk_user_author = $user->id;
681  $bookkeeping->entity = $conf->entity;
682 
683  $totaldebit += $bookkeeping->debit;
684  $totalcredit += $bookkeeping->credit;
685 
686  $result = $bookkeeping->create($user);
687  if ($result < 0) {
688  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
689  $error++;
690  $errorforline++;
691  $errorforinvoice[$key] = 'alreadyjournalized';
692  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
693  } else {
694  $error++;
695  $errorforline++;
696  $errorforinvoice[$key] = 'other';
697  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
698  }
699  }
700  }
701  }
702  }
703 
704  // Protection against a bug on lines before
705  if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
706  $error++;
707  $errorforline++;
708  $errorforinvoice[$key] = 'amountsnotbalanced';
709  setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
710  }
711 
712  if (!$errorforline) {
713  $db->commit();
714  } else {
715  $db->rollback();
716 
717  if ($error >= 10) {
718  setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
719  break; // Break in the foreach
720  }
721  }
722  }
723 
724  $tabpay = $tabfac;
725 
726  if (empty($error) && count($tabpay) > 0) {
727  setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
728  } elseif (count($tabpay) == $error) {
729  setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
730  } else {
731  setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
732  }
733 
734  $action = '';
735 
736  // Must reload data, so we make a redirect
737  if (count($tabpay) != $error) {
738  $param = 'id_journal='.$id_journal;
739  $param .= '&date_startday='.$date_startday;
740  $param .= '&date_startmonth='.$date_startmonth;
741  $param .= '&date_startyear='.$date_startyear;
742  $param .= '&date_endday='.$date_endday;
743  $param .= '&date_endmonth='.$date_endmonth;
744  $param .= '&date_endyear='.$date_endyear;
745  $param .= '&in_bookkeeping='.$in_bookkeeping;
746  header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
747  exit;
748  }
749 }
750 
751 
752 
753 /*
754  * View
755  */
756 
757 $form = new Form($db);
758 
759 // Export
760 if ($action == 'exportcsv') { // ISO and not UTF8 !
761  // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL
762  $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
763 
764  $filename = 'journal';
765  $type_export = 'journal';
766  include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
767 
768  $companystatic = new Client($db);
769  $invoicestatic = new Facture($db);
770 
771  foreach ($tabfac as $key => $val) {
772  $companystatic->id = $tabcompany[$key]['id'];
773  $companystatic->name = $tabcompany[$key]['name'];
774  $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
775  $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
776  $companystatic->code_client = $tabcompany[$key]['code_client'];
777  $companystatic->client = 3;
778 
779  $invoicestatic->id = $key;
780  $invoicestatic->ref = (string) $val["ref"];
781  $invoicestatic->type = $val["type"];
782  $invoicestatic->close_code = $val["close_code"];
783 
784  $date = dol_print_date($val["date"], 'day');
785 
786  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
787  $replacedinvoice = 0;
788  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
789  $replacedinvoice = 1;
790  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
791  if ($alreadydispatched) {
792  $replacedinvoice = 2;
793  }
794  }
795 
796  // 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)
797  if ($replacedinvoice == 1) {
798  continue;
799  }
800 
801  // Warranty
802  foreach ($tabwarranty[$key] as $k => $mt) {
803  //if ($mt) {
804  print '"'.$key.'"'.$sep;
805  print '"'.$date.'"'.$sep;
806  print '"'.$val["ref"].'"'.$sep;
807  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
808  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
809  print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
810  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
811  print '"'.$langs->trans("Thirdparty").'"'.$sep;
812  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").'"'.$sep;
813  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
814  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
815  print '"'.$journal.'"';
816  print "\n";
817  //}
818  }
819 
820  // Third party
821  foreach ($tabttc[$key] as $k => $mt) {
822  //if ($mt) {
823  print '"'.$key.'"'.$sep;
824  print '"'.$date.'"'.$sep;
825  print '"'.$val["ref"].'"'.$sep;
826  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
827  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
828  print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')).'"'.$sep;
829  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
830  print '"'.$langs->trans("Thirdparty").'"'.$sep;
831  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Thirdparty").'"'.$sep;
832  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
833  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
834  print '"'.$journal.'"';
835  print "\n";
836  //}
837  }
838 
839  // Product / Service
840  foreach ($tabht[$key] as $k => $mt) {
841  $accountingaccount = new AccountingAccount($db);
842  $accountingaccount->fetch(null, $k, true);
843  //if ($mt) {
844  print '"'.$key.'"'.$sep;
845  print '"'.$date.'"'.$sep;
846  print '"'.$val["ref"].'"'.$sep;
847  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
848  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
849  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
850  print '""'.$sep;
851  print '"'.utf8_decode(dol_trunc($accountingaccount->label, 32)).'"'.$sep;
852  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.dol_trunc($accountingaccount->label, 32).'"'.$sep;
853  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
854  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
855  print '"'.$journal.'"';
856  print "\n";
857  //}
858  }
859 
860  // VAT
861  $listoftax = array(0, 1, 2);
862  foreach ($listoftax as $numtax) {
863  $arrayofvat = $tabtva;
864  if ($numtax == 1) {
865  $arrayofvat = $tablocaltax1;
866  }
867  if ($numtax == 2) {
868  $arrayofvat = $tablocaltax2;
869  }
870 
871  foreach ($arrayofvat[$key] as $k => $mt) {
872  if ($mt) {
873  print '"'.$key.'"'.$sep;
874  print '"'.$date.'"'.$sep;
875  print '"'.$val["ref"].'"'.$sep;
876  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
877  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
878  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
879  print '""'.$sep;
880  print '"'.$langs->trans("VAT").' - '.join(', ', $def_tva[$key][$k]).' %"'.$sep;
881  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("VAT").join(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '').'"'.$sep;
882  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
883  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
884  print '"'.$journal.'"';
885  print "\n";
886  }
887  }
888  }
889 
890  // Revenue stamp
891  foreach ($tabrevenuestamp[$key] as $k => $mt) {
892  //if ($mt) {
893  print '"'.$key.'"'.$sep;
894  print '"'.$date.'"'.$sep;
895  print '"'.$val["ref"].'"'.$sep;
896  print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep;
897  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
898  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
899  print '""'.$sep;
900  print '"'.$langs->trans("RevenueStamp").'"'.$sep;
901  print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").'"'.$sep;
902  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
903  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
904  print '"'.$journal.'"';
905  print "\n";
906  //}
907  }
908  }
909 }
910 
911 
912 
913 if (empty($action) || $action == 'view') {
914  $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
915 
916  llxHeader('', dol_string_nohtmltag($title));
917 
918  $nom = $title;
919  $nomlink = '';
920  $periodlink = '';
921  $exportlink = '';
922  $builddate = dol_now();
923  $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
924  if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
925  $description .= $langs->trans("DepositsAreNotIncluded");
926  } else {
927  $description .= $langs->trans("DepositsAreIncluded");
928  }
929 
930  $listofchoices = array('notyet'=>$langs->trans("NotYetInGeneralLedger"), 'already'=>$langs->trans("AlreadyInGeneralLedger"));
931  $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);
932  $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
933 
934  $varlink = 'id_journal='.$id_journal;
935 
936  journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
937 
938  // Button to write into Ledger
939  $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
940  if ($acctCustomerNotConfigured) {
941  print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
942  $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
943  $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
944  print $desc;
945  print '</div>';
946  }
947  print '<div class="tabsAction tabsActionNoBottom centerimp">';
948  if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
949  print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
950  }
951  if ($acctCustomerNotConfigured) {
952  print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
953  } else {
954  if ($in_bookkeeping == 'notyet') {
955  print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
956  } else {
957  print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
958  }
959  }
960  print '</div>';
961 
962  // TODO Avoid using js. We can use a direct link with $param
963  print '
964  <script type="text/javascript">
965  function launch_export() {
966  $("div.fiche form input[name=\"action\"]").val("exportcsv");
967  $("div.fiche form input[type=\"submit\"]").click();
968  $("div.fiche form input[name=\"action\"]").val("");
969  }
970  function writebookkeeping() {
971  console.log("click on writebookkeeping");
972  $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
973  $("div.fiche form input[type=\"submit\"]").click();
974  $("div.fiche form input[name=\"action\"]").val("");
975  }
976  </script>';
977 
978  /*
979  * Show result array
980  */
981  print '<br>';
982 
983  print '<div class="div-table-responsive">';
984  print "<table class=\"noborder\" width=\"100%\">";
985  print "<tr class=\"liste_titre\">";
986  print "<td>".$langs->trans("Date")."</td>";
987  print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
988  print "<td>".$langs->trans("AccountAccounting")."</td>";
989  print "<td>".$langs->trans("SubledgerAccount")."</td>";
990  print "<td>".$langs->trans("LabelOperation")."</td>";
991  print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
992  print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
993  print "</tr>\n";
994 
995  $i = 0;
996 
997  $companystatic = new Client($db);
998  $invoicestatic = new Facture($db);
999 
1000  foreach ($tabfac as $key => $val) {
1001  $companystatic->id = $tabcompany[$key]['id'];
1002  $companystatic->name = $tabcompany[$key]['name'];
1003  $companystatic->code_compta = $tabcompany[$key]['code_compta'];
1004  $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1005  $companystatic->code_client = $tabcompany[$key]['code_client'];
1006  $companystatic->client = 3;
1007 
1008  $invoicestatic->id = $key;
1009  $invoicestatic->ref = (string) $val["ref"];
1010  $invoicestatic->type = $val["type"];
1011  $invoicestatic->close_code = $val["close_code"];
1012 
1013  $date = dol_print_date($val["date"], 'day');
1014 
1015  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1016  $replacedinvoice = 0;
1017  if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1018  $replacedinvoice = 1;
1019  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1020  if ($alreadydispatched) {
1021  $replacedinvoice = 2;
1022  }
1023  }
1024 
1025  // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1026  if ($replacedinvoice == 1) {
1027  print '<tr class="oddeven">';
1028  print "<!-- Replaced invoice -->";
1029  print "<td>".$date."</td>";
1030  print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1031  // Account
1032  print "<td>";
1033  print $langs->trans("Replaced");
1034  print '</td>';
1035  // Subledger account
1036  print "<td>";
1037  print '</td>';
1038  print "<td>";
1039  print "</td>";
1040  print '<td class="right"></td>';
1041  print '<td class="right"></td>';
1042  print "</tr>";
1043 
1044  $i++;
1045  continue;
1046  }
1047  if ($errorforinvoice[$key] == 'somelinesarenotbound') {
1048  print '<tr class="oddeven">';
1049  print "<!-- Some lines are not bound -->";
1050  print "<td>".$date."</td>";
1051  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1052  // Account
1053  print "<td>";
1054  print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
1055  print '</td>';
1056  // Subledger account
1057  print "<td>";
1058  print '</td>';
1059  print "<td>";
1060  print "</td>";
1061  print '<td class="right"></td>';
1062  print '<td class="right"></td>';
1063  print "</tr>";
1064 
1065  $i++;
1066  }
1067 
1068  // Warranty
1069  foreach ($tabwarranty[$key] as $k => $mt) {
1070  print '<tr class="oddeven">';
1071  print "<!-- Thirdparty warranty -->";
1072  print "<td>".$date."</td>";
1073  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1074  // Account
1075  print "<td>";
1076  $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
1077  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1078  print '<span class="error">'.$langs->trans("MainAccountForRetainedWarrantyNotDefined").'</span>';
1079  } else {
1080  print $accountoshow;
1081  }
1082  print '</td>';
1083  // Subledger account
1084  print "<td>";
1085  $accountoshow = length_accounta($k);
1086  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1087  print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1088  } else {
1089  print $accountoshow;
1090  }
1091  print '</td>';
1092  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty")."</td>";
1093  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1094  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1095  print "</tr>";
1096  }
1097 
1098  // Third party
1099  foreach ($tabttc[$key] as $k => $mt) {
1100  print '<tr class="oddeven">';
1101  print "<!-- Thirdparty -->";
1102  print "<td>".$date."</td>";
1103  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1104  // Account
1105  print "<td>";
1106  $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
1107  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1108  print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
1109  } else {
1110  print $accountoshow;
1111  }
1112  print '</td>';
1113  // Subledger account
1114  print "<td>";
1115  $accountoshow = length_accounta($k);
1116  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1117  print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1118  } else {
1119  print $accountoshow;
1120  }
1121  print '</td>';
1122  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount")."</td>";
1123  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1124  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1125  print "</tr>";
1126 
1127  $i++;
1128  }
1129 
1130  // Product / Service
1131  foreach ($tabht[$key] as $k => $mt) {
1132  $accountingaccount = new AccountingAccount($db);
1133  $accountingaccount->fetch(null, $k, true);
1134 
1135  print '<tr class="oddeven">';
1136  print "<!-- Product -->";
1137  print "<td>".$date."</td>";
1138  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1139  // Account
1140  print "<td>";
1141  $accountoshow = length_accountg($k);
1142  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1143  print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1144  } else {
1145  print $accountoshow;
1146  }
1147  print "</td>";
1148  // Subledger account
1149  print "<td>";
1150  if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1151  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1152  print length_accounta($tabcompany[$key]['code_compta']);
1153  }
1154  } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1155  print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1156  }
1157  print '</td>';
1158  $companystatic->id = $tabcompany[$key]['id'];
1159  $companystatic->name = $tabcompany[$key]['name'];
1160  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$accountingaccount->label."</td>";
1161  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1162  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1163  print "</tr>";
1164 
1165  $i++;
1166  }
1167 
1168  // VAT
1169  $listoftax = array(0, 1, 2);
1170  foreach ($listoftax as $numtax) {
1171  $arrayofvat = $tabtva;
1172  if ($numtax == 1) {
1173  $arrayofvat = $tablocaltax1;
1174  }
1175  if ($numtax == 2) {
1176  $arrayofvat = $tablocaltax2;
1177  }
1178 
1179  // $key is id of invoice
1180  foreach ($arrayofvat[$key] as $k => $mt) {
1181  if ($mt) {
1182  print '<tr class="oddeven">';
1183  print "<!-- VAT -->";
1184  print "<td>".$date."</td>";
1185  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1186  // Account
1187  print "<td>";
1188  $accountoshow = length_accountg($k);
1189  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1190  print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType2").')</span>';
1191  } else {
1192  print $accountoshow;
1193  }
1194  print "</td>";
1195  // Subledger account
1196  print "<td>";
1197  print '</td>';
1198  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref;
1199  // $def_tva is array[invoiceid][accountancy_code_sell_of_vat_rate_found][vatrate]=vatrate
1200  //var_dump($arrayofvat[$key]); var_dump($key); var_dump($k);
1201  $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : join(', ', $def_tva[$key][$k]));
1202  print ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
1203  print ($numtax ? ' - Localtax '.$numtax : '');
1204  print "</td>";
1205  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1206  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1207  print "</tr>";
1208 
1209  $i++;
1210  }
1211  }
1212  }
1213 
1214  // Warranty
1215  foreach ($tabrevenuestamp[$key] as $k => $mt) {
1216  print '<tr class="oddeven">';
1217  print "<!-- Thirdparty revenuestamp -->";
1218  print "<td>".$date."</td>";
1219  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1220  // Account
1221  print "<td>";
1222  $accountoshow = length_accountg($k);
1223  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1224  print '<span class="error">'.$langs->trans("MainAccountForRevenueStampSaleNotDefined").'</span>';
1225  } else {
1226  print $accountoshow;
1227  }
1228  print '</td>';
1229  // Subledger account
1230  print "<td>";
1231  print '</td>';
1232  print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp")."</td>";
1233  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1234  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1235  print "</tr>";
1236  }
1237  }
1238 
1239  if (!$i) {
1240  print '<tr class="oddeven"><td colspan="6"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1241  }
1242 
1243  print "</table>";
1244  print '</div>';
1245 
1246  // End of page
1247  llxFooter();
1248 }
1249 
1250 $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 accounts.
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:577
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:596
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.