dolibarr  20.0.0-beta
purchasesjournal.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-2023 Alexandre Spangaro <aspangaro@easya.solutions>
7  * Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
8  * Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
9  * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
10  * Copyright (C) 2018 Eric Seigne <eric.seigne@cap-rel.fr>
11  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
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 
32 require '../../main.inc.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
37 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
42 
43 // Load translation files required by the page
44 $langs->loadLangs(array("commercial", "compta", "bills", "other", "accountancy", "errors"));
45 
46 $id_journal = GETPOSTINT('id_journal');
47 $action = GETPOST('action', 'aZ09');
48 
49 $date_startmonth = GETPOST('date_startmonth');
50 $date_startday = GETPOST('date_startday');
51 $date_startyear = GETPOST('date_startyear');
52 $date_endmonth = GETPOST('date_endmonth');
53 $date_endday = GETPOST('date_endday');
54 $date_endyear = GETPOST('date_endyear');
55 $in_bookkeeping = GETPOST('in_bookkeeping');
56 if ($in_bookkeeping == '') {
57  $in_bookkeeping = 'notyet';
58 }
59 
60 $now = dol_now();
61 
62 $hookmanager->initHooks(array('purchasesjournal'));
63 $parameters = array();
64 
65 // Security check
66 if (!isModEnabled('accounting')) {
68 }
69 if ($user->socid > 0) {
71 }
72 if (!$user->hasRight('accounting', 'bind', 'write')) {
74 }
75 
76 $error = 0;
77 
78 
79 /*
80  * Actions
81  */
82 
83 $reshook = $hookmanager->executeHooks('doActions', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
84 
85 $accountingaccount = new AccountingAccount($db);
86 
87 // Get information of journal
88 $accountingjournalstatic = new AccountingJournal($db);
89 $accountingjournalstatic->fetch($id_journal);
90 $journal = $accountingjournalstatic->code;
91 $journal_label = $accountingjournalstatic->label;
92 
93 $date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
94 $date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
95 
96 if (empty($date_startmonth)) {
97  // Period by default on transfer
98  $dates = getDefaultDatesForTransfer();
99  $date_start = $dates['date_start'];
100  $pastmonthyear = $dates['pastmonthyear'];
101  $pastmonth = $dates['pastmonth'];
102 }
103 if (empty($date_endmonth)) {
104  // Period by default on transfer
105  $dates = getDefaultDatesForTransfer();
106  $date_end = $dates['date_end'];
107  $pastmonthyear = $dates['pastmonthyear'];
108  $pastmonth = $dates['pastmonth'];
109 }
110 
111 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
112  $date_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
113  $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
114 }
115 
116 $sql = "SELECT f.rowid, f.ref as ref, f.type, f.datef as df, f.libelle as label, f.ref_supplier, f.date_lim_reglement as dlr, f.close_code, f.vat_reverse_charge,";
117 $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.tva as total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.vat_src_code, fd.info_bits,";
118 $sql .= " p.default_vat_code AS product_buy_default_vat_code, p.tva_tx as product_buy_vat, p.localtax1_tx as product_buy_localvat1, p.localtax2_tx as product_buy_localvat2,";
119 $sql .= " co.code as country_code, co.label as country_label,";
120 $sql .= " s.rowid as socid, s.nom as name, s.fournisseur, s.code_client, s.code_fournisseur, s.fk_pays,";
121 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
122  $sql .= " spe.accountancy_code_customer as code_compta,";
123  $sql .= " spe.accountancy_code_supplier as code_compta_fournisseur,";
124 } else {
125  $sql .= " s.code_compta as code_compta,";
126  $sql .= " s.code_compta_fournisseur,";
127 }
128 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
129  $sql .= " ppe.accountancy_code_buy,";
130 } else {
131  $sql .= " p.accountancy_code_buy,";
132 }
133 $sql .= " aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte";
134 $parameters = array();
135 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
136 $sql .= $hookmanager->resPrint;
137 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as fd";
138 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product";
139 if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
140  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
141 }
142 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
143 $sql .= " JOIN ".MAIN_DB_PREFIX."facture_fourn as f ON f.rowid = fd.fk_facture_fourn";
144 $sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
145 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays ";
146 if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
147  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity);
148 }
149 $parameters = array();
150 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
151 $sql .= $hookmanager->resPrint;
152 $sql .= " WHERE f.fk_statut > 0";
153 $sql .= " AND fd.fk_code_ventilation > 0";
154 $sql .= " AND f.entity IN (".getEntity('facture_fourn', 0).")"; // We don't share object for accountancy
155 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
156  $sql .= " AND f.type IN (".FactureFournisseur::TYPE_STANDARD.",".FactureFournisseur::TYPE_REPLACEMENT.",".FactureFournisseur::TYPE_CREDIT_NOTE.",".FactureFournisseur::TYPE_SITUATION.")";
157 } else {
159 }
160 if ($date_start && $date_end) {
161  $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
162 }
163 // Define begin binding date
164 if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
165  $sql .= " AND f.datef >= '".$db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING'))."'";
166 }
167 // Already in bookkeeping or not
168 if ($in_bookkeeping == 'already') {
169  $sql .= " AND f.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='supplier_invoice')";
170 }
171 if ($in_bookkeeping == 'notyet') {
172  $sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='supplier_invoice')";
173 }
174 $parameters = array();
175 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
176 $sql .= $hookmanager->resPrint;
177 $sql .= " ORDER BY f.datef";
178 
179 dol_syslog('accountancy/journal/purchasesjournal.php', LOG_DEBUG);
180 $result = $db->query($sql);
181 if ($result) {
182  $tabfac = array();
183  $tabht = array();
184  $tabtva = array();
185  $def_tva = array();
186  $tabttc = array();
187  $tablocaltax1 = array();
188  $tablocaltax2 = array();
189  $tabcompany = array();
190  $tabother = array();
191  $tabrctva = array();
192  $tabrclocaltax1 = array();
193  $tabrclocaltax2 = array();
194  $vatdata_cache = array();
195 
196  $num = $db->num_rows($result);
197 
198  // Variables
199  $cptfour = getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER', 'NotDefined');
200  $cpttva = getDolGlobalString('ACCOUNTING_VAT_BUY_ACCOUNT', 'NotDefined');
201  $rcctva = getDolGlobalString('ACCOUNTING_VAT_BUY_REVERSE_CHARGES_CREDIT', 'NotDefined');
202  $rcdtva = getDolGlobalString('ACCOUNTING_VAT_BUY_REVERSE_CHARGES_DEBIT', 'NotDefined');
203  $country_code_in_EEC = getCountriesInEEC(); // This make a database call but there is a cache done into $conf->cache['country_code_in_EEC']
204 
205  $i = 0;
206  while ($i < $num) {
207  $obj = $db->fetch_object($result);
208 
209  // Controls
210  $compta_soc = ($obj->code_compta_fournisseur != "") ? $obj->code_compta_fournisseur : $cptfour;
211 
212  $compta_prod = $obj->compte;
213  if (empty($compta_prod)) {
214  if ($obj->product_type == 0) {
215  $compta_prod = getDolGlobalString('ACCOUNTING_PRODUCT_BUY_ACCOUNT', 'NotDefined');
216  } else {
217  $compta_prod = getDolGlobalString('ACCOUNTING_SERVICE_BUY_ACCOUNT', 'NotDefined');
218  }
219  }
220 
221  $tax_id = $obj->tva_tx . ($obj->vat_src_code ? ' (' . $obj->vat_src_code . ')' : '');
222  if (array_key_exists($tax_id, $vatdata_cache)) {
223  $vatdata = $vatdata_cache[$tax_id];
224  } else {
225  $vatdata = getTaxesFromId($tax_id, $mysoc, $mysoc, 0);
226  $vatdata_cache[$tax_id] = $vatdata;
227  }
228  $compta_tva = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva);
229  $compta_localtax1 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva);
230  $compta_localtax2 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva);
231  $compta_counterpart_tva_npr = getDolGlobalString('ACCOUNTING_COUNTERPART_VAT_NPR', 'NotDefined');
232 
233  // Define array to display all VAT rates that use this accounting account $compta_tva
234  if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) {
235  $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.')' : ''));
236  }
237 
238  //$line = new SupplierInvoiceLine($db);
239  //$line->fetch($obj->fdid);
240 
241  $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
242  $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
243  $tabfac[$obj->rowid]["ref"] = $obj->ref_supplier.' ('.$obj->ref.')';
244  $tabfac[$obj->rowid]["refsologest"] = $obj->ref;
245  $tabfac[$obj->rowid]["refsuppliersologest"] = $obj->ref_supplier;
246  $tabfac[$obj->rowid]["type"] = $obj->type;
247  $tabfac[$obj->rowid]["description"] = $obj->description;
248  $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
249  //$tabfac[$obj->rowid]["fk_facturefourndet"] = $obj->fdid;
250 
251  // Avoid warnings
252  if (!isset($tabttc[$obj->rowid][$compta_soc])) {
253  $tabttc[$obj->rowid][$compta_soc] = 0;
254  }
255  if (!isset($tabht[$obj->rowid][$compta_prod])) {
256  $tabht[$obj->rowid][$compta_prod] = 0;
257  }
258  if (!isset($tabtva[$obj->rowid][$compta_tva])) {
259  $tabtva[$obj->rowid][$compta_tva] = 0;
260  }
261  if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
262  $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
263  }
264  if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
265  $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
266  }
267 
268  // VAT Reverse charge
269  if (($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) && $obj->vat_reverse_charge == 1 && in_array($obj->country_code, $country_code_in_EEC)) {
270  $rcvatdata = getTaxesFromId($obj->product_buy_vat . ($obj->product_buy_default_vat_code ? ' (' . $obj->product_buy_default_vat_code . ')' : ''), $mysoc, $mysoc, 0);
271  $rcc_compta_tva = (!empty($vatdata['accountancy_code_vat_reverse_charge_credit']) ? $vatdata['accountancy_code_vat_reverse_charge_credit'] : $rcctva);
272  $rcd_compta_tva = (!empty($vatdata['accountancy_code_vat_reverse_charge_debit']) ? $vatdata['accountancy_code_vat_reverse_charge_debit'] : $rcdtva);
273  $rcc_compta_localtax1 = (!empty($vatdata['accountancy_code_vat_reverse_charge_credit']) ? $vatdata['accountancy_code_vat_reverse_charge_credit'] : $rcctva);
274  $rcd_compta_localtax1 = (!empty($vatdata['accountancy_code_vat_reverse_charge_debit']) ? $vatdata['accountancy_code_vat_reverse_charge_debit'] : $rcdtva);
275  $rcc_compta_localtax2 = (!empty($vatdata['accountancy_code_vat_reverse_charge_credit']) ? $vatdata['accountancy_code_vat_reverse_charge_credit'] : $rcctva);
276  $rcd_compta_localtax2 = (!empty($vatdata['accountancy_code_vat_reverse_charge_debit']) ? $vatdata['accountancy_code_vat_reverse_charge_debit'] : $rcdtva);
277  if (price2num($obj->product_buy_vat) || !empty($obj->product_buy_default_vat_code)) {
278  $vat_key = vatrate($obj->product_buy_vat) . ($obj->product_buy_default_vat_code ? ' (' . $obj->product_buy_default_vat_code . ')' : '');
279  $val_value = $vat_key;
280  $def_tva[$obj->rowid][$rcc_compta_tva][$vat_key] = $val_value;
281  $def_tva[$obj->rowid][$rcd_compta_tva][$vat_key] = $val_value;
282  }
283 
284  if (!isset($tabrctva[$obj->rowid][$rcc_compta_tva])) {
285  $tabrctva[$obj->rowid][$rcc_compta_tva] = 0;
286  }
287  if (!isset($tabrctva[$obj->rowid][$rcd_compta_tva])) {
288  $tabrctva[$obj->rowid][$rcd_compta_tva] = 0;
289  }
290  if (!isset($tabrclocaltax1[$obj->rowid][$rcc_compta_localtax1])) {
291  $tabrclocaltax1[$obj->rowid][$rcc_compta_localtax1] = 0;
292  }
293  if (!isset($tabrclocaltax1[$obj->rowid][$rcd_compta_localtax1])) {
294  $tabrclocaltax1[$obj->rowid][$rcd_compta_localtax1] = 0;
295  }
296  if (!isset($tabrclocaltax2[$obj->rowid][$rcc_compta_localtax2])) {
297  $tabrclocaltax2[$obj->rowid][$rcc_compta_localtax2] = 0;
298  }
299  if (!isset($tabrclocaltax2[$obj->rowid][$rcd_compta_localtax2])) {
300  $tabrclocaltax2[$obj->rowid][$rcd_compta_localtax2] = 0;
301  }
302 
303  $rcvat = (float) price2num($obj->total_ttc * $obj->product_buy_vat / 100, 'MT');
304  $rclocalvat1 = (float) price2num($obj->total_ttc * $obj->product_buy_localvat1 / 100, 'MT');
305  $rclocalvat2 = (float) price2num($obj->total_ttc * $obj->product_buy_localvat2 / 100, 'MT');
306 
307  $tabrctva[$obj->rowid][$rcd_compta_tva] += $rcvat;
308  $tabrctva[$obj->rowid][$rcc_compta_tva] -= $rcvat;
309  $tabrclocaltax1[$obj->rowid][$rcd_compta_localtax1] += $rclocalvat1;
310  $tabrclocaltax1[$obj->rowid][$rcc_compta_localtax1] -= $rclocalvat1;
311  $tabrclocaltax2[$obj->rowid][$rcd_compta_localtax2] += $rclocalvat2;
312  $tabrclocaltax2[$obj->rowid][$rcc_compta_localtax2] -= $rclocalvat2;
313  }
314 
315  $tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc;
316  $tabht[$obj->rowid][$compta_prod] += $obj->total_ht;
317  $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
318  $tva_npr = ((($obj->info_bits & 1) == 1) ? 1 : 0);
319  if ($tva_npr) { // If NPR, we add an entry for counterpartWe into tabother
320  $tabother[$obj->rowid][$compta_counterpart_tva_npr] += $obj->total_tva;
321  }
322  $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
323  $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
324  $tabcompany[$obj->rowid] = array(
325  'id' => $obj->socid,
326  'name' => $obj->name,
327  'code_fournisseur' => $obj->code_fournisseur,
328  'code_compta_fournisseur' => $compta_soc
329  );
330 
331  $i++;
332  }
333 } else {
334  dol_print_error($db);
335 }
336 
337 // Check for too many invoices first.
338 if (count($tabfac) > 10000) { // Global config in htdocs/admin/const.php???
339  $error++;
340  setEventMessages("TooManyInvoicesToProcessPleaseUseAMoreSelectiveFilter", null, 'errors');
341 }
342 
343 $errorforinvoice = array();
344 
345 /*
346 // Old way, 1 query for each invoice
347 // Loop in invoices to detect lines with not binding lines
348 foreach ($tabfac as $key => $val) { // Loop on each invoice
349  $sql = "SELECT COUNT(fd.rowid) as nb";
350  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn_det as fd";
351  $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
352  $sql .= " AND fd.total_ttc <> 0 AND fk_facture_fourn = ".((int) $key);
353  $resql = $db->query($sql);
354  if ($resql) {
355  $obj = $db->fetch_object($resql);
356  if ($obj->nb > 0) {
357  $errorforinvoice[$key] = 'somelinesarenotbound';
358  }
359  } else {
360  dol_print_error($db);
361  }
362 }
363 */
364 // New way, single query, load all unbound lines
365 $sql = "
366 SELECT
367  fk_facture_fourn,
368  COUNT(fd.rowid) as nb
369 FROM
370  " . MAIN_DB_PREFIX . "facture_fourn_det as fd
371 WHERE
372  fd.product_type <= 2
373  AND fd.fk_code_ventilation <= 0
374  AND fd.total_ttc <> 0
375  AND fk_facture_fourn IN (".$db->sanitize(implode(",", array_keys($tabfac))).")
376 GROUP BY fk_facture_fourn
377 ";
378 $resql = $db->query($sql);
379 
380 $num = $db->num_rows($resql);
381 $i = 0;
382 while ($i < $num) {
383  $obj = $db->fetch_object($resql);
384  if ($obj->nb > 0) {
385  $errorforinvoice[$obj->fk_facture_fourn] = 'somelinesarenotbound';
386  }
387  $i++;
388 }
389 //var_dump($errorforinvoice);exit;
390 
391 
392 
393 // Bookkeeping Write
394 if ($action == 'writebookkeeping' && !$error) {
395  $now = dol_now();
396  $error = 0;
397 
398  $companystatic = new Societe($db);
399  $invoicestatic = new FactureFournisseur($db);
400  $accountingaccountsupplier = new AccountingAccount($db);
401 
402  $accountingaccountsupplier->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER'), true);
403 
404  foreach ($tabfac as $key => $val) { // Loop on each invoice
405  $errorforline = 0;
406 
407  $totalcredit = 0;
408  $totaldebit = 0;
409 
410  $db->begin();
411 
412  $companystatic->id = $tabcompany[$key]['id'];
413  $companystatic->name = $tabcompany[$key]['name'];
414  $companystatic->code_compta_fournisseur = $tabcompany[$key]['code_compta_fournisseur'];
415  $companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
416  $companystatic->fournisseur = 1;
417 
418  $invoicestatic->id = $key;
419  $invoicestatic->ref = (string) $val["refsologest"];
420  $invoicestatic->ref_supplier = $val["refsuppliersologest"];
421  $invoicestatic->type = $val["type"];
422  $invoicestatic->description = html_entity_decode(dol_trunc($val["description"], 32));
423  $invoicestatic->close_code = $val["close_code"];
424 
425  $date = dol_print_date($val["date"], 'day');
426 
427  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
428  $replacedinvoice = 0;
429  if ($invoicestatic->close_code == FactureFournisseur::CLOSECODE_REPLACED) {
430  $replacedinvoice = 1;
431  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
432  if ($alreadydispatched) {
433  $replacedinvoice = 2;
434  }
435  }
436 
437  // 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)
438  if ($replacedinvoice == 1) {
439  $db->rollback();
440  continue;
441  }
442 
443  // Error if some lines are not binded/ready to be journalized
444  if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
445  $error++;
446  $errorforline++;
447  setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
448  }
449 
450  // Thirdparty
451  if (!$errorforline) {
452  foreach ($tabttc[$key] as $k => $mt) {
453  $bookkeeping = new BookKeeping($db);
454  $bookkeeping->doc_date = $val["date"];
455  $bookkeeping->date_lim_reglement = $val["datereg"];
456  $bookkeeping->doc_ref = $val["refsologest"];
457  $bookkeeping->date_creation = $now;
458  $bookkeeping->doc_type = 'supplier_invoice';
459  $bookkeeping->fk_doc = $key;
460  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
461  $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
462 
463  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta_fournisseur'];
464  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
465 
466  $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER');
467  $bookkeeping->label_compte = $accountingaccountsupplier->label;
468 
469  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("SubledgerAccount");
470  $bookkeeping->montant = $mt;
471  $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
472  $bookkeeping->debit = ($mt <= 0) ? -$mt : 0;
473  $bookkeeping->credit = ($mt > 0) ? $mt : 0;
474  $bookkeeping->code_journal = $journal;
475  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
476  $bookkeeping->fk_user_author = $user->id;
477  $bookkeeping->entity = $conf->entity;
478 
479  $totaldebit += $bookkeeping->debit;
480  $totalcredit += $bookkeeping->credit;
481 
482  $result = $bookkeeping->create($user);
483  if ($result < 0) {
484  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
485  $error++;
486  $errorforline++;
487  $errorforinvoice[$key] = 'alreadyjournalized';
488  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
489  } else {
490  $error++;
491  $errorforline++;
492  $errorforinvoice[$key] = 'other';
493  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
494  }
495  } else {
496  if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
497  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
498  $lettering_static = new Lettering($db);
499 
500  $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
501  }
502  }
503  }
504  }
505 
506  // Product / Service
507  if (!$errorforline) {
508  foreach ($tabht[$key] as $k => $mt) {
509  $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache
510  $label_account = $accountingaccount->label;
511 
512  // get compte id and label
513  if ($resultfetch > 0) {
514  $bookkeeping = new BookKeeping($db);
515  $bookkeeping->doc_date = $val["date"];
516  $bookkeeping->date_lim_reglement = $val["datereg"];
517  $bookkeeping->doc_ref = $val["refsologest"];
518  $bookkeeping->date_creation = $now;
519  $bookkeeping->doc_type = 'supplier_invoice';
520  $bookkeeping->fk_doc = $key;
521  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
522  $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
523 
524  if (getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_USE_AUXILIARY_ON_DEPOSIT')) {
525  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT')) {
526  $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
527  $bookkeeping->subledger_label = $tabcompany[$key]['name'];
528  } else {
529  $bookkeeping->subledger_account = '';
530  $bookkeeping->subledger_label = '';
531  }
532  } else {
533  $bookkeeping->subledger_account = '';
534  $bookkeeping->subledger_label = '';
535  }
536 
537  $bookkeeping->numero_compte = $k;
538  $bookkeeping->label_compte = $label_account;
539 
540  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$label_account;
541  $bookkeeping->montant = $mt;
542  $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
543  $bookkeeping->debit = ($mt > 0) ? $mt : 0;
544  $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
545  $bookkeeping->code_journal = $journal;
546  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
547  $bookkeeping->fk_user_author = $user->id;
548  $bookkeeping->entity = $conf->entity;
549 
550  $totaldebit += $bookkeeping->debit;
551  $totalcredit += $bookkeeping->credit;
552 
553  $result = $bookkeeping->create($user);
554  if ($result < 0) {
555  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
556  $error++;
557  $errorforline++;
558  $errorforinvoice[$key] = 'alreadyjournalized';
559  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
560  } else {
561  $error++;
562  $errorforline++;
563  $errorforinvoice[$key] = 'other';
564  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
565  }
566  }
567  }
568  }
569  }
570 
571  // VAT
572  // var_dump($tabtva);
573  if (!$errorforline) {
574  $listoftax = array(0, 1, 2);
575  foreach ($listoftax as $numtax) {
576  $arrayofvat = $tabtva;
577  if ($numtax == 1) {
578  $arrayofvat = $tablocaltax1;
579  }
580  if ($numtax == 2) {
581  $arrayofvat = $tablocaltax2;
582  }
583 
584  // VAT Reverse charge
585  if ($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
586  $has_vat = false;
587  foreach ($arrayofvat[$key] as $k => $mt) {
588  if ($mt) {
589  $has_vat = true;
590  }
591  }
592 
593  if (!$has_vat) {
594  $arrayofvat = $tabrctva;
595  if ($numtax == 1) {
596  $arrayofvat = $tabrclocaltax1;
597  }
598  if ($numtax == 2) {
599  $arrayofvat = $tabrclocaltax2;
600  }
601  if (!isset($arrayofvat[$key]) || !is_array($arrayofvat[$key])) {
602  $arrayofvat[$key] = array();
603  }
604  }
605  }
606 
607  foreach ($arrayofvat[$key] as $k => $mt) {
608  if ($mt) {
609  $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
610  $label_account = $accountingaccount->label;
611 
612  $bookkeeping = new BookKeeping($db);
613  $bookkeeping->doc_date = $val["date"];
614  $bookkeeping->date_lim_reglement = $val["datereg"];
615  $bookkeeping->doc_ref = $val["refsologest"];
616  $bookkeeping->date_creation = $now;
617  $bookkeeping->doc_type = 'supplier_invoice';
618  $bookkeeping->fk_doc = $key;
619  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
620  $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
621 
622  $bookkeeping->subledger_account = '';
623  $bookkeeping->subledger_label = '';
624 
625  $bookkeeping->numero_compte = $k;
626  $bookkeeping->label_compte = $label_account;
627 
628  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
629  $bookkeeping->montant = $mt;
630  $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
631  $bookkeeping->debit = ($mt > 0) ? $mt : 0;
632  $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
633  $bookkeeping->code_journal = $journal;
634  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
635  $bookkeeping->fk_user_author = $user->id;
636  $bookkeeping->entity = $conf->entity;
637 
638  $totaldebit += $bookkeeping->debit;
639  $totalcredit += $bookkeeping->credit;
640 
641  $result = $bookkeeping->create($user);
642  if ($result < 0) {
643  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
644  $error++;
645  $errorforline++;
646  $errorforinvoice[$key] = 'alreadyjournalized';
647  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
648  } else {
649  $error++;
650  $errorforline++;
651  $errorforinvoice[$key] = 'other';
652  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
653  }
654  }
655  }
656  }
657  }
658  }
659 
660  // Counterpart of VAT for VAT NPR
661  // var_dump($tabother);
662  if (!$errorforline && isset($tabother[$key]) && is_array($tabother[$key])) {
663  foreach ($tabother[$key] as $k => $mt) {
664  if ($mt) {
665  $bookkeeping = new BookKeeping($db);
666  $bookkeeping->doc_date = $val["date"];
667  $bookkeeping->date_lim_reglement = $val["datereg"];
668  $bookkeeping->doc_ref = $val["refsologest"];
669  $bookkeeping->date_creation = $now;
670  $bookkeeping->doc_type = 'supplier_invoice';
671  $bookkeeping->fk_doc = $key;
672  $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
673  $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
674 
675  $bookkeeping->subledger_account = '';
676  $bookkeeping->subledger_label = '';
677 
678  $bookkeeping->numero_compte = $k;
679 
680  $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT").' NPR';
681  $bookkeeping->montant = $mt;
682  $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
683  $bookkeeping->debit = ($mt > 0) ? $mt : 0;
684  $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
685  $bookkeeping->code_journal = $journal;
686  $bookkeeping->journal_label = $langs->transnoentities($journal_label);
687  $bookkeeping->fk_user_author = $user->id;
688  $bookkeeping->entity = $conf->entity;
689 
690  $totaldebit += $bookkeeping->debit;
691  $totalcredit += $bookkeeping->credit;
692 
693  $result = $bookkeeping->create($user);
694  if ($result < 0) {
695  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
696  $error++;
697  $errorforline++;
698  $errorforinvoice[$key] = 'alreadyjournalized';
699  //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
700  } else {
701  $error++;
702  $errorforline++;
703  $errorforinvoice[$key] = 'other';
704  setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
705  }
706  }
707  }
708  }
709  }
710 
711  // Protection against a bug on lines before
712  if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
713  $error++;
714  $errorforline++;
715  $errorforinvoice[$key] = 'amountsnotbalanced';
716  setEventMessages('We tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
717  }
718 
719  if (!$errorforline) {
720  $db->commit();
721  } else {
722  $db->rollback();
723 
724  if ($error >= 10) {
725  setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
726  break; // Break in the foreach
727  }
728  }
729  }
730 
731  $tabpay = $tabfac;
732 
733  if (empty($error) && count($tabpay) > 0) {
734  setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
735  } elseif (count($tabpay) == $error) {
736  setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
737  } else {
738  setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
739  }
740 
741  $action = '';
742 
743  // Must reload data, so we make a redirect
744  if (count($tabpay) != $error) {
745  $param = 'id_journal='.$id_journal;
746  $param .= '&date_startday='.$date_startday;
747  $param .= '&date_startmonth='.$date_startmonth;
748  $param .= '&date_startyear='.$date_startyear;
749  $param .= '&date_endday='.$date_endday;
750  $param .= '&date_endmonth='.$date_endmonth;
751  $param .= '&date_endyear='.$date_endyear;
752  $param .= '&in_bookkeeping='.$in_bookkeeping;
753  header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
754  exit;
755  }
756 }
757 
758 /*
759  * View
760  */
761 
762 $form = new Form($db);
763 
764 // Export
765 if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
766  $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
767 
768  $filename = 'journal';
769  $type_export = 'journal';
770  include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
771 
772  $companystatic = new Fournisseur($db);
773  $invoicestatic = new FactureFournisseur($db);
774 
775  foreach ($tabfac as $key => $val) {
776  $companystatic->id = $tabcompany[$key]['id'];
777  $companystatic->name = $tabcompany[$key]['name'];
778  $companystatic->code_compta_fournisseur = $tabcompany[$key]['code_compta_fournisseur'];
779  $companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
780  $companystatic->fournisseur = 1;
781 
782  $invoicestatic->id = $key;
783  $invoicestatic->ref = $val["refsologest"];
784  $invoicestatic->ref_supplier = $val["refsuppliersologest"];
785  $invoicestatic->type = $val["type"];
786  $invoicestatic->description = dol_trunc(html_entity_decode($val["description"]), 32);
787  $invoicestatic->close_code = $val["close_code"];
788 
789  $date = dol_print_date($val["date"], 'day');
790 
791  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
792  $replacedinvoice = 0;
793  if ($invoicestatic->close_code == FactureFournisseur::CLOSECODE_REPLACED) {
794  $replacedinvoice = 1;
795  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
796  if ($alreadydispatched) {
797  $replacedinvoice = 2;
798  }
799  }
800 
801  // 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)
802  if ($replacedinvoice == 1) {
803  continue;
804  }
805 
806  // Third party
807  foreach ($tabttc[$key] as $k => $mt) {
808  //if ($mt) {
809  print '"'.$key.'"'.$sep;
810  print '"'.$date.'"'.$sep;
811  print '"'.$val["refsologest"].'"'.$sep;
812  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
813  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
814  print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER')).'"'.$sep;
815  print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
816  print '"'.$langs->trans("Thirdparty").'"'.$sep;
817  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$val["refsuppliersologest"].' - '.$langs->trans("Thirdparty").'"'.$sep;
818  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
819  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
820  print '"'.$journal.'"';
821  print "\n";
822  //}
823  }
824 
825  // Product / Service
826  foreach ($tabht[$key] as $k => $mt) {
827  $accountingaccount = new AccountingAccount($db);
828  $accountingaccount->fetch(null, $k, true);
829  //if ($mt) {
830  print '"'.$key.'"'.$sep;
831  print '"'.$date.'"'.$sep;
832  print '"'.$val["refsologest"].'"'.$sep;
833  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
834  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
835  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
836  print '""'.$sep;
837  print '"'.mb_convert_encoding(dol_trunc($accountingaccount->label, 32), 'ISO-8859-1').'"'.$sep;
838  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$val["refsuppliersologest"].' - '.dol_trunc($accountingaccount->label, 32).'"'.$sep;
839  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
840  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
841  print '"'.$journal.'"';
842  print "\n";
843  //}
844  }
845 
846  // VAT
847  $listoftax = array(0, 1, 2);
848  foreach ($listoftax as $numtax) {
849  $arrayofvat = $tabtva;
850  if ($numtax == 1) {
851  $arrayofvat = $tablocaltax1;
852  }
853  if ($numtax == 2) {
854  $arrayofvat = $tablocaltax2;
855  }
856 
857  // VAT Reverse charge
858  if ($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
859  $has_vat = false;
860  foreach ($arrayofvat[$key] as $k => $mt) {
861  if ($mt) {
862  $has_vat = true;
863  }
864  }
865 
866  if (!$has_vat) {
867  $arrayofvat = $tabrctva;
868  if ($numtax == 1) {
869  $arrayofvat = $tabrclocaltax1;
870  }
871  if ($numtax == 2) {
872  $arrayofvat = $tabrclocaltax2;
873  }
874  if (!isset($arrayofvat[$key]) || !is_array($arrayofvat[$key])) {
875  $arrayofvat[$key] = array();
876  }
877  }
878  }
879 
880  foreach ($arrayofvat[$key] as $k => $mt) {
881  if ($mt) {
882  print '"'.$key.'"'.$sep;
883  print '"'.$date.'"'.$sep;
884  print '"'.$val["refsologest"].'"'.$sep;
885  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
886  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
887  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
888  print '""'.$sep;
889  print '"'.$langs->trans("VAT").' - '.implode(', ', $def_tva[$key][$k]).' %"'.$sep;
890  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$val["refsuppliersologest"].' - '.$langs->trans("VAT").implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '').'"'.$sep;
891  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
892  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
893  print '"'.$journal.'"';
894  print "\n";
895  }
896  }
897 
898  // VAT counterpart for NPR
899  if (isset($tabother[$key]) && is_array($tabother[$key])) {
900  foreach ($tabother[$key] as $k => $mt) {
901  if ($mt) {
902  print '"'.$key.'"'.$sep;
903  print '"'.$date.'"'.$sep;
904  print '"'.$val["refsologest"].'"'.$sep;
905  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
906  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
907  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
908  print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
909  print '"'.$langs->trans("Thirdparty").'"'.$sep;
910  print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$val["refsuppliersologest"].' - '.$langs->trans("VAT").' NPR"'.$sep;
911  print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
912  print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
913  print '"'.$journal.'"';
914  print "\n";
915  }
916  }
917  }
918  }
919  }
920 }
921 
922 if (empty($action) || $action == 'view') {
923  $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
924 
925  llxHeader('', dol_string_nohtmltag($title));
926 
927  $nom = $title;
928  $nomlink = '';
929  $periodlink = '';
930  $exportlink = '';
931  $builddate = dol_now();
932  $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
933  if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
934  $description .= $langs->trans("DepositsAreNotIncluded");
935  } else {
936  $description .= $langs->trans("DepositsAreIncluded");
937  }
938 
939  $listofchoices = array('notyet' => $langs->trans("NotYetInGeneralLedger"), 'already' => $langs->trans("AlreadyInGeneralLedger"));
940  $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);
941  $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
942 
943  $varlink = 'id_journal='.$id_journal;
944 
945  journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
946 
947  if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
948  // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
949  // Fiscal period test
950  $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
951  $resql = $db->query($sql);
952  if ($resql) {
953  $obj = $db->fetch_object($resql);
954  if ($obj->nb == 0) {
955  print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
956  $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
957  $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
958  print $desc;
959  print '</div>';
960  }
961  } else {
962  dol_print_error($db);
963  }
964  }
965 
966  // Button to write into Ledger
967  $acctSupplierNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER'), ['','-1']);
968  if ($acctSupplierNotConfigured) {
969  print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
970  $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
971  $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
972  print $desc;
973  print '</div>';
974  }
975  print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
976  if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
977  print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
978  }
979  if ($acctSupplierNotConfigured) {
980  print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
981  } else {
982  if ($in_bookkeeping == 'notyet') {
983  print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
984  } else {
985  print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
986  }
987  }
988  print '</div>';
989 
990  // TODO Avoid using js. We can use a direct link with $param
991  print '
992  <script type="text/javascript">
993  function launch_export() {
994  $("div.fiche form input[name=\"action\"]").val("exportcsv");
995  $("div.fiche form input[type=\"submit\"]").click();
996  $("div.fiche form input[name=\"action\"]").val("");
997  }
998  function writebookkeeping() {
999  console.log("click on writebookkeeping");
1000  $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1001  $("div.fiche form input[type=\"submit\"]").click();
1002  $("div.fiche form input[name=\"action\"]").val("");
1003  }
1004  </script>';
1005 
1006  /*
1007  * Show result array
1008  */
1009  print '<br>';
1010 
1011  print '<div class="div-table-responsive">';
1012  print "<table class=\"noborder\" width=\"100%\">";
1013  print "<tr class=\"liste_titre\">";
1014  print "<td>".$langs->trans("Date")."</td>";
1015  print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1016  print "<td>".$langs->trans("AccountAccounting")."</td>";
1017  print "<td>".$langs->trans("SubledgerAccount")."</td>";
1018  print "<td>".$langs->trans("LabelOperation")."</td>";
1019  print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1020  print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1021  print "</tr>\n";
1022 
1023  $i = 0;
1024 
1025  $invoicestatic = new FactureFournisseur($db);
1026  $companystatic = new Fournisseur($db);
1027 
1028  foreach ($tabfac as $key => $val) {
1029  $companystatic->id = $tabcompany[$key]['id'];
1030  $companystatic->name = $tabcompany[$key]['name'];
1031  $companystatic->code_compta_fournisseur = $tabcompany[$key]['code_compta_fournisseur'];
1032  $companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
1033  $companystatic->fournisseur = 1;
1034 
1035  $invoicestatic->id = $key;
1036  $invoicestatic->ref = $val["refsologest"];
1037  $invoicestatic->ref_supplier = $val["refsuppliersologest"];
1038  $invoicestatic->type = $val["type"];
1039  $invoicestatic->description = dol_trunc(html_entity_decode($val["description"]), 32);
1040  $invoicestatic->close_code = $val["close_code"];
1041 
1042  $date = dol_print_date($val["date"], 'day');
1043 
1044  // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1045  $replacedinvoice = 0;
1046  if ($invoicestatic->close_code == FactureFournisseur::CLOSECODE_REPLACED) {
1047  $replacedinvoice = 1;
1048  $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1049  if ($alreadydispatched) {
1050  $replacedinvoice = 2;
1051  }
1052  }
1053 
1054  // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1055  if ($replacedinvoice == 1) {
1056  print '<tr class="oddeven">';
1057  print "<!-- Replaced invoice -->";
1058  print "<td>".$date."</td>";
1059  print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1060  // Account
1061  print "<td>";
1062  print $langs->trans("Replaced");
1063  print '</td>';
1064  // Subledger account
1065  print "<td>";
1066  print '</td>';
1067  print "<td>";
1068  print "</td>";
1069  print '<td class="right"></td>';
1070  print '<td class="right"></td>';
1071  print "</tr>";
1072 
1073  $i++;
1074  continue;
1075  }
1076  if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
1077  print '<tr class="oddeven">';
1078  print "<!-- Some lines are not bound -->";
1079  print "<td>".$date."</td>";
1080  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1081  // Account
1082  print "<td>";
1083  print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
1084  print '</td>';
1085  // Subledger account
1086  print "<td>";
1087  print '</td>';
1088  print "<td>";
1089  print "</td>";
1090  print '<td class="right"></td>';
1091  print '<td class="right"></td>';
1092  print "</tr>";
1093 
1094  $i++;
1095  }
1096 
1097  // Third party
1098  foreach ($tabttc[$key] as $k => $mt) {
1099  print '<tr class="oddeven">';
1100  print "<!-- Thirdparty -->";
1101  print "<td>".$date."</td>";
1102  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1103  // Account
1104  print "<td>";
1105  $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER'));
1106  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1107  print '<span class="error">'.$langs->trans("MainAccountForSuppliersNotDefined").'</span>';
1108  } else {
1109  print $accountoshow;
1110  }
1111  print '</td>';
1112  // Subledger account
1113  print "<td>";
1114  $accountoshow = length_accounta($k);
1115  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1116  print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1117  } else {
1118  print $accountoshow;
1119  }
1120  print '</td>';
1121  print "<td>".$companystatic->getNomUrl(0, 'supplier', 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("SubledgerAccount")."</td>";
1122  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1123  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1124  print "</tr>";
1125 
1126  $i++;
1127  }
1128 
1129  // Product / Service
1130  foreach ($tabht[$key] as $k => $mt) {
1131  $accountingaccount = new AccountingAccount($db);
1132  $accountingaccount->fetch(null, $k, true);
1133 
1134  print '<tr class="oddeven">';
1135  print "<!-- Product -->";
1136  print "<td>".$date."</td>";
1137  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1138  // Account
1139  print "<td>";
1140  $accountoshow = length_accountg($k);
1141  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1142  print '<span class="error">'.$langs->trans("ProductAccountNotDefined").'</span>';
1143  } else {
1144  print $accountoshow;
1145  }
1146  print "</td>";
1147  // Subledger account
1148  print "<td>";
1149  if (getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_USE_AUXILIARY_ON_DEPOSIT')) {
1150  if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT')) {
1151  print length_accounta($tabcompany[$key]['code_compta']);
1152  }
1153  } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1154  print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1155  }
1156  print '</td>';
1157  $companystatic->id = $tabcompany[$key]['id'];
1158  $companystatic->name = $tabcompany[$key]['name'];
1159  print "<td>".$companystatic->getNomUrl(0, 'supplier', 16).' - '.$invoicestatic->ref_supplier.' - '.$accountingaccount->label."</td>";
1160  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1161  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1162  print "</tr>";
1163 
1164  $i++;
1165  }
1166 
1167  // VAT
1168  $listoftax = array(0, 1, 2);
1169  foreach ($listoftax as $numtax) {
1170  $arrayofvat = $tabtva;
1171  if ($numtax == 1) {
1172  $arrayofvat = $tablocaltax1;
1173  }
1174  if ($numtax == 2) {
1175  $arrayofvat = $tablocaltax2;
1176  }
1177 
1178  // VAT Reverse charge
1179  if ($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
1180  $has_vat = false;
1181  foreach ($arrayofvat[$key] as $k => $mt) {
1182  if ($mt) {
1183  $has_vat = true;
1184  }
1185  }
1186 
1187  if (!$has_vat) {
1188  $arrayofvat = $tabrctva;
1189  if ($numtax == 1) {
1190  $arrayofvat = $tabrclocaltax1;
1191  }
1192  if ($numtax == 2) {
1193  $arrayofvat = $tabrclocaltax2;
1194  }
1195  if (!isset($arrayofvat[$key]) || !is_array($arrayofvat[$key])) {
1196  $arrayofvat[$key] = array();
1197  }
1198  }
1199  }
1200 
1201  foreach ($arrayofvat[$key] as $k => $mt) {
1202  if ($mt) {
1203  print '<tr class="oddeven">';
1204  print "<!-- VAT -->";
1205  print "<td>".$date."</td>";
1206  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1207  // Account
1208  print "<td>";
1209  $accountoshow = length_accountg($k);
1210  if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1211  print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType3").')</span>';
1212  } else {
1213  print $accountoshow;
1214  }
1215  print "</td>";
1216  // Subledger account
1217  print "<td>";
1218  print '</td>';
1219  print "<td>";
1220  print $companystatic->getNomUrl(0, 'supplier', 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
1221  print "</td>";
1222  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1223  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1224  print "</tr>";
1225 
1226  $i++;
1227  }
1228  }
1229  }
1230 
1231  // VAT counterpart for NPR
1232  if (isset($tabother[$key]) && is_array($tabother[$key])) {
1233  foreach ($tabother[$key] as $k => $mt) {
1234  if ($mt) {
1235  print '<tr class="oddeven">';
1236  print '<!-- VAT counterpart NPR -->';
1237  print "<td>".$date."</td>";
1238  print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1239  // Account
1240  print '<td>';
1241  $accountoshow = length_accountg($k);
1242  if ($accountoshow == '' || $accountoshow == 'NotDefined') {
1243  print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("NPR counterpart").'). Set ACCOUNTING_COUNTERPART_VAT_NPR to the subvention account</span>';
1244  } else {
1245  print $accountoshow;
1246  }
1247  print '</td>';
1248  // Subledger account
1249  print "<td>";
1250  print '</td>';
1251  print "<td>".$companystatic->getNomUrl(0, 'supplier', 16).' - '.$invoicestatic->ref_supplier.' - '.$langs->trans("VAT")." NPR (counterpart)</td>";
1252  print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1253  print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1254  print "</tr>";
1255 
1256  $i++;
1257  }
1258  }
1259  }
1260  }
1261 
1262  if (!$i) {
1263  print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1264  }
1265 
1266  print "</table>";
1267  print '</div>';
1268 
1269  // End of page
1270  llxFooter();
1271 }
1272 $db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
journalHead($nom, $variant, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='', $moreoptions=array())
Show header of a page used to transfer/dispatch data in accounting.
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:55
llxFooter()
Empty footer.
Definition: wrapper.php:69
Class to manage accounting accounts.
Class to manage accounting journals.
Class to manage Ledger (General Ledger and Subledger)
const TYPE_SITUATION
Situation invoice.
Class to manage suppliers invoices.
const TYPE_DEPOSIT
Deposit invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
const TYPE_REPLACEMENT
Replacement invoice.
Class to manage generation of HTML components Only common components must be here.
Class to manage suppliers.
Class Lettering.
Class to manage third parties objects (customers, suppliers, prospects...)
getCountriesInEEC()
Return list of countries that are inside the EEC (European Economic Community) Note: Try to keep this...
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('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') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition: date.lib.php:595
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:614
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getTaxesFromId($vatrate, $buyer=null, $seller=null, $firstparamisid=1)
Get tax (VAT) main information from Id.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
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'))
div float
Buy price without taxes.
Definition: style.css.php:960
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.