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