dolibarr 21.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-2024 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// New way, single query, load all unbound lines
403$sql = "
404SELECT
405 fk_facture_fourn,
406 COUNT(fd.rowid) as nb
407FROM
408 " . MAIN_DB_PREFIX . "facture_fourn_det as fd
409WHERE
410 fd.product_type <= 2
411 AND fd.fk_code_ventilation <= 0
412 AND fd.total_ttc <> 0
413 AND fk_facture_fourn IN (".$db->sanitize(implode(",", array_keys($tabfac))).")
414GROUP BY fk_facture_fourn
415";
416$resql = $db->query($sql);
417
418$num = $db->num_rows($resql);
419$i = 0;
420while ($i < $num) {
421 $obj = $db->fetch_object($resql);
422 if ($obj->nb > 0) {
423 $errorforinvoice[$obj->fk_facture_fourn] = 'somelinesarenotbound';
424 }
425 $i++;
426}
427//var_dump($errorforinvoice);exit;
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 $accountingaccount->fetch(0, $k, true); // TODO Use a cache for label
657 $label_account = $accountingaccount->label;
658
659 $bookkeeping = new BookKeeping($db);
660 $bookkeeping->doc_date = $val["date"];
661 $bookkeeping->date_lim_reglement = $val["datereg"];
662 $bookkeeping->doc_ref = $val["refsologest"];
663 $bookkeeping->date_creation = $now;
664 $bookkeeping->doc_type = 'supplier_invoice';
665 $bookkeeping->fk_doc = $key;
666 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
667 $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
668
669 $bookkeeping->subledger_account = '';
670 $bookkeeping->subledger_label = '';
671
672 $bookkeeping->numero_compte = $k;
673 $bookkeeping->label_compte = $label_account;
674
675 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
676 $labelvataccount = $langs->trans("Taxes").' '.$tmpvatrate.' %';
677 $labelvataccount .= ($numtax ? ' - Localtax '.$numtax : '');
678 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref_supplier, $labelvataccount);
679
680 $bookkeeping->montant = $mt;
681 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
682 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
683 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
684 $bookkeeping->code_journal = $journal;
685 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
686 $bookkeeping->fk_user_author = $user->id;
687 $bookkeeping->entity = $conf->entity;
688
689 $totaldebit += $bookkeeping->debit;
690 $totalcredit += $bookkeeping->credit;
691
692 $result = $bookkeeping->create($user);
693 if ($result < 0) {
694 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
695 $error++;
696 $errorforline++;
697 $errorforinvoice[$key] = 'alreadyjournalized';
698 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
699 } else {
700 $error++;
701 $errorforline++;
702 $errorforinvoice[$key] = 'other';
703 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
704 }
705 }
706 }
707 }
708 }
709 }
710
711 // Counterpart of VAT for VAT NPR
712 // var_dump($tabother);
713 if (!$errorforline && isset($tabother[$key]) && is_array($tabother[$key])) {
714 foreach ($tabother[$key] as $k => $mt) {
715 if ($mt) {
716 $bookkeeping = new BookKeeping($db);
717 $bookkeeping->doc_date = $val["date"];
718 $bookkeeping->date_lim_reglement = $val["datereg"];
719 $bookkeeping->doc_ref = $val["refsologest"];
720 $bookkeeping->date_creation = $now;
721 $bookkeeping->doc_type = 'supplier_invoice';
722 $bookkeeping->fk_doc = $key;
723 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
724 $bookkeeping->thirdparty_code = $companystatic->code_fournisseur;
725
726 $bookkeeping->subledger_account = '';
727 $bookkeeping->subledger_label = '';
728
729 $bookkeeping->numero_compte = $k;
730
731 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref_supplier, $langs->trans("VAT").' NPR');
732 $bookkeeping->montant = $mt;
733 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
734 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
735 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
736 $bookkeeping->code_journal = $journal;
737 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
738 $bookkeeping->fk_user_author = $user->id;
739 $bookkeeping->entity = $conf->entity;
740
741 $totaldebit += $bookkeeping->debit;
742 $totalcredit += $bookkeeping->credit;
743
744 $result = $bookkeeping->create($user);
745 if ($result < 0) {
746 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
747 $error++;
748 $errorforline++;
749 $errorforinvoice[$key] = 'alreadyjournalized';
750 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
751 } else {
752 $error++;
753 $errorforline++;
754 $errorforinvoice[$key] = 'other';
755 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
756 }
757 }
758 }
759 }
760 }
761
762 // Protection against a bug on lines before
763 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
764 $error++;
765 $errorforline++;
766 $errorforinvoice[$key] = 'amountsnotbalanced';
767 setEventMessages('We tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
768 }
769
770 if (!$errorforline) {
771 $db->commit();
772 } else {
773 $db->rollback();
774
775 if ($error >= 10) {
776 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
777 break; // Break in the foreach
778 }
779 }
780 }
781
782 $tabpay = $tabfac;
783
784 if (empty($error) && count($tabpay) > 0) {
785 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
786 } elseif (count($tabpay) == $error) {
787 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
788 } else {
789 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
790 }
791
792 $action = '';
793
794 // Must reload data, so we make a redirect
795 if (count($tabpay) != $error) {
796 $param = 'id_journal='.$id_journal;
797 $param .= '&date_startday='.$date_startday;
798 $param .= '&date_startmonth='.$date_startmonth;
799 $param .= '&date_startyear='.$date_startyear;
800 $param .= '&date_endday='.$date_endday;
801 $param .= '&date_endmonth='.$date_endmonth;
802 $param .= '&date_endyear='.$date_endyear;
803 $param .= '&in_bookkeeping='.$in_bookkeeping;
804 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
805 exit;
806 }
807}
808
809/*
810 * View
811 */
812
813$form = new Form($db);
814
815// Export
816if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
817 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
818
819 $filename = 'journal';
820 $type_export = 'journal';
821 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
822
823 $companystatic = new Fournisseur($db);
824 $invoicestatic = new FactureFournisseur($db);
825 $bookkeepingstatic = new BookKeeping($db);
826
827 foreach ($tabfac as $key => $val) {
828 $companystatic->id = $tabcompany[$key]['id'];
829 $companystatic->name = $tabcompany[$key]['name'];
830 $companystatic->accountancy_code_supplier_general = !empty($tabcompany[$key]['accountancy_code_supplier_general']) ? $tabcompany[$key]['accountancy_code_supplier_general'] : $cptfour;
831 $companystatic->code_compta_fournisseur = $tabcompany[$key]['code_compta_fournisseur'];
832 $companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
833 $companystatic->fournisseur = 1;
834
835 $invoicestatic->id = $key;
836 $invoicestatic->ref = $val["refsologest"];
837 $invoicestatic->ref_supplier = $val["refsuppliersologest"];
838 $invoicestatic->type = $val["type"];
839 $invoicestatic->description = dol_trunc(html_entity_decode($val["description"]), 32);
840 $invoicestatic->close_code = $val["close_code"];
841
842 $date = dol_print_date($val["date"], 'day');
843
844 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
845 $replacedinvoice = 0;
846 if ($invoicestatic->close_code == FactureFournisseur::CLOSECODE_REPLACED) {
847 $replacedinvoice = 1;
848 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
849 if ($alreadydispatched) {
850 $replacedinvoice = 2;
851 }
852 }
853
854 // 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)
855 if ($replacedinvoice == 1) {
856 continue;
857 }
858
859 // Third party
860 foreach ($tabttc[$key] as $k => $mt) {
861 //if ($mt) {
862 print '"'.$key.'"'.$sep;
863 print '"'.$date.'"'.$sep;
864 print '"'.$val["refsologest"].'"'.$sep;
865 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
866 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
867 print '"'.length_accountg($companystatic->accountancy_code_supplier_general).'"'.$sep;
868 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
869 print '"'.$langs->trans("Thirdparty").'"'.$sep;
870 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $val["refsuppliersologest"], $langs->trans("Thirdparty"))).'"'.$sep;
871 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
872 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
873 print '"'.$journal.'"';
874 print "\n";
875 //}
876 }
877
878 // Product / Service
879 foreach ($tabht[$key] as $k => $mt) {
880 $accountingaccount = new AccountingAccount($db);
881 $accountingaccount->fetch(0, $k, true);
882 //if ($mt) {
883 print '"'.$key.'"'.$sep;
884 print '"'.$date.'"'.$sep;
885 print '"'.$val["refsologest"].'"'.$sep;
886 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
887 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
888 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
889 print '""'.$sep;
890 print '"'.csvClean(dol_trunc($accountingaccount->label, 32)).'"'.$sep;
891 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $val["refsuppliersologest"], $accountingaccount->label)).'"'.$sep;
892 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
893 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
894 print '"'.$journal.'"';
895 print "\n";
896 //}
897 }
898
899 // VAT
900 $listoftax = array(0, 1, 2);
901 foreach ($listoftax as $numtax) {
902 $arrayofvat = $tabtva;
903 if ($numtax == 1) {
904 $arrayofvat = $tablocaltax1;
905 }
906 if ($numtax == 2) {
907 $arrayofvat = $tablocaltax2;
908 }
909
910 // VAT Reverse charge
911 if ($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
912 $has_vat = false;
913 foreach ($arrayofvat[$key] as $k => $mt) {
914 if ($mt) {
915 $has_vat = true;
916 }
917 }
918
919 if (!$has_vat) {
920 $arrayofvat = $tabrctva;
921 if ($numtax == 1) {
922 $arrayofvat = $tabrclocaltax1;
923 }
924 if ($numtax == 2) {
925 $arrayofvat = $tabrclocaltax2;
926 }
927 if (!isset($arrayofvat[$key]) || !is_array($arrayofvat[$key])) {
928 $arrayofvat[$key] = array();
929 }
930 }
931 }
932
933 foreach ($arrayofvat[$key] as $k => $mt) {
934 if ($mt) {
935 print '"'.$key.'"'.$sep;
936 print '"'.$date.'"'.$sep;
937 print '"'.$val["refsologest"].'"'.$sep;
938 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
939 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
940 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
941 print '""'.$sep;
942 print '"'.$langs->trans("VAT").' - '.implode(', ', $def_tva[$key][$k]).' %"'.$sep;
943 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $val["refsuppliersologest"], $langs->trans("VAT").implode($def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : ''))).'"'.$sep;
944 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
945 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
946 print '"'.$journal.'"';
947 print "\n";
948 }
949 }
950
951 // VAT counterpart for NPR
952 if (isset($tabother[$key]) && is_array($tabother[$key])) {
953 foreach ($tabother[$key] as $k => $mt) {
954 if ($mt) {
955 print '"'.$key.'"'.$sep;
956 print '"'.$date.'"'.$sep;
957 print '"'.$val["refsologest"].'"'.$sep;
958 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
959 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
960 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
961 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
962 print '"'.$langs->trans("Thirdparty").'"'.$sep;
963 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $val["refsuppliersologest"], $langs->trans("VAT").' NPR')).'"'.$sep;
964 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
965 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
966 print '"'.$journal.'"';
967 print "\n";
968 }
969 }
970 }
971 }
972 }
973}
974
975if (empty($action) || $action == 'view') {
976 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
977 $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;';
978 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-purchasesjournal');
979
980 $nom = $title;
981 $nomlink = '';
982 $periodlink = '';
983 $exportlink = '';
984 $builddate = dol_now();
985 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
986 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
987 $description .= $langs->trans("DepositsAreNotIncluded");
988 } else {
989 $description .= $langs->trans("DepositsAreIncluded");
990 }
991
992 $listofchoices = array('notyet' => $langs->trans("NotYetInGeneralLedger"), 'already' => $langs->trans("AlreadyInGeneralLedger"));
993 $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);
994 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
995
996 $varlink = 'id_journal='.$id_journal;
997
998 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
999
1000 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
1001 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
1002 // Fiscal period test
1003 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
1004 $resql = $db->query($sql);
1005 if ($resql) {
1006 $obj = $db->fetch_object($resql);
1007 if ($obj->nb == 0) {
1008 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
1009 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
1010 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
1011 print $desc;
1012 print '</div>';
1013 }
1014 } else {
1015 dol_print_error($db);
1016 }
1017 }
1018
1019 // Button to write into Ledger
1020 $acctSupplierNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER'), ['','-1']);
1021 if ($acctSupplierNotConfigured) {
1022 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1023 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
1024 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
1025 print $desc;
1026 print '</div>';
1027 }
1028 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1029 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
1030 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1031 }
1032 if ($acctSupplierNotConfigured) {
1033 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1034 } else {
1035 if ($in_bookkeeping == 'notyet') {
1036 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1037 } else {
1038 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1039 }
1040 }
1041 print '</div>';
1042
1043 // TODO Avoid using js. We can use a direct link with $param
1044 print '
1045 <script type="text/javascript">
1046 function launch_export() {
1047 $("div.fiche form input[name=\"action\"]").val("exportcsv");
1048 $("div.fiche form input[type=\"submit\"]").click();
1049 $("div.fiche form input[name=\"action\"]").val("");
1050 }
1051 function writebookkeeping() {
1052 console.log("click on writebookkeeping");
1053 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1054 $("div.fiche form input[type=\"submit\"]").click();
1055 $("div.fiche form input[name=\"action\"]").val("");
1056 }
1057 </script>';
1058
1059 /*
1060 * Show result array
1061 */
1062 print '<br>';
1063
1064 print '<div class="div-table-responsive">';
1065 print "<table class=\"noborder\" width=\"100%\">";
1066 print "<tr class=\"liste_titre\">";
1067 print "<td>".$langs->trans("Date")."</td>";
1068 print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1069 print "<td>".$langs->trans("AccountAccounting")."</td>";
1070 print "<td>".$langs->trans("SubledgerAccount")."</td>";
1071 print "<td>".$langs->trans("LabelOperation")."</td>";
1072 print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1073 print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1074 print "</tr>\n";
1075
1076 $i = 0;
1077
1078 $invoicestatic = new FactureFournisseur($db);
1079 $companystatic = new Fournisseur($db);
1080 $bookkeepingstatic = new BookKeeping($db);
1081
1082 foreach ($tabfac as $key => $val) {
1083 $companystatic->id = $tabcompany[$key]['id'];
1084 $companystatic->name = $tabcompany[$key]['name'];
1085 $companystatic->accountancy_code_supplier_general = !empty($tabcompany[$key]['accountancy_code_supplier_general']) ? $tabcompany[$key]['accountancy_code_supplier_general'] : $cptfour;
1086 $companystatic->code_compta_fournisseur = $tabcompany[$key]['code_compta_fournisseur'];
1087 $companystatic->code_fournisseur = $tabcompany[$key]['code_fournisseur'];
1088 $companystatic->fournisseur = 1;
1089
1090 $invoicestatic->id = $key;
1091 $invoicestatic->ref = $val["refsologest"];
1092 $invoicestatic->ref_supplier = $val["refsuppliersologest"];
1093 $invoicestatic->type = $val["type"];
1094 $invoicestatic->description = dol_trunc(html_entity_decode($val["description"]), 32);
1095 $invoicestatic->close_code = $val["close_code"];
1096
1097 $date = dol_print_date($val["date"], 'day');
1098
1099 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1100 $replacedinvoice = 0;
1101 if ($invoicestatic->close_code == FactureFournisseur::CLOSECODE_REPLACED) {
1102 $replacedinvoice = 1;
1103 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1104 if ($alreadydispatched) {
1105 $replacedinvoice = 2;
1106 }
1107 }
1108
1109 // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1110 if ($replacedinvoice == 1) {
1111 print '<tr class="oddeven">';
1112 print "<!-- Replaced invoice -->";
1113 print "<td>".$date."</td>";
1114 print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1115 // Account
1116 print "<td>";
1117 print $langs->trans("Replaced");
1118 print '</td>';
1119 // Subledger account
1120 print "<td>";
1121 print '</td>';
1122 print "<td>";
1123 print "</td>";
1124 print '<td class="right"></td>';
1125 print '<td class="right"></td>';
1126 print "</tr>";
1127
1128 $i++;
1129 continue;
1130 }
1131 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
1132 print '<tr class="oddeven">';
1133 print "<!-- Some lines are not bound -->";
1134 print "<td>".$date."</td>";
1135 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1136 // Account
1137 print "<td>";
1138 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
1139 print '</td>';
1140 // Subledger account
1141 print "<td>";
1142 print '</td>';
1143 print "<td>";
1144 print "</td>";
1145 print '<td class="right"></td>';
1146 print '<td class="right"></td>';
1147 print "</tr>";
1148
1149 $i++;
1150 }
1151
1152 // Third party
1153 foreach ($tabttc[$key] as $k => $mt) {
1154 print '<tr class="oddeven">';
1155 print "<!-- Thirdparty -->";
1156 print "<td>".$date."</td>";
1157 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1158 // Account
1159 print "<td>";
1160 $accountoshow = length_accountg(!empty($tabcompany[$key]['accountancy_code_supplier_general']) ? $tabcompany[$key]['accountancy_code_supplier_general'] : $cptfour);
1161 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1162 print '<span class="error">'.$langs->trans("MainAccountForSuppliersNotDefined").'</span>';
1163 } else {
1164 print $accountoshow;
1165 }
1166 print '</td>';
1167 // Subledger account
1168 print "<td>";
1169 $accountoshow = length_accounta($k);
1170 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1171 print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1172 } else {
1173 print $accountoshow;
1174 }
1175 print '</td>';
1176 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'supplier'), $invoicestatic->ref_supplier, $langs->trans("SubledgerAccount")) . "</td>";
1177 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1178 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1179 print "</tr>";
1180
1181 $i++;
1182 }
1183
1184 // Product / Service
1185 foreach ($tabht[$key] as $k => $mt) {
1186 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1187 $accountingaccount = new AccountingAccount($db);
1188 $accountingaccount->fetch(0, $k, true);
1189 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1190 } else {
1191 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1192 }
1193
1194 print '<tr class="oddeven">';
1195 print "<!-- Product -->";
1196 print "<td>".$date."</td>";
1197 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1198 // Account
1199 print "<td>";
1200 $accountoshow = length_accountg($k);
1201 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1202 print '<span class="error">'.$langs->trans("ProductAccountNotDefined").'</span>';
1203 } else {
1204 print $accountoshow;
1205 }
1206 print "</td>";
1207 // Subledger account
1208 print "<td>";
1209 if (getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_USE_AUXILIARY_ON_DEPOSIT')) {
1210 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT')) {
1211 print length_accounta($tabcompany[$key]['code_compta_fournisseur']);
1212 }
1213 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1214 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1215 }
1216 print '</td>';
1217 $companystatic->id = $tabcompany[$key]['id'];
1218 $companystatic->name = $tabcompany[$key]['name'];
1219 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'supplier'), $invoicestatic->ref_supplier, $accountingaccount->label) . "</td>";
1220 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1221 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1222 print "</tr>";
1223
1224 $i++;
1225 }
1226
1227 // VAT
1228 $listoftax = array(0, 1, 2);
1229 foreach ($listoftax as $numtax) {
1230 $arrayofvat = $tabtva;
1231 if ($numtax == 1) {
1232 $arrayofvat = $tablocaltax1;
1233 }
1234 if ($numtax == 2) {
1235 $arrayofvat = $tablocaltax2;
1236 }
1237
1238 // VAT Reverse charge
1239 if ($mysoc->country_code == 'FR' || getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) {
1240 $has_vat = false;
1241 foreach ($arrayofvat[$key] as $k => $mt) {
1242 if ($mt) {
1243 $has_vat = true;
1244 }
1245 }
1246
1247 if (!$has_vat) {
1248 $arrayofvat = $tabrctva;
1249 if ($numtax == 1) {
1250 $arrayofvat = $tabrclocaltax1;
1251 }
1252 if ($numtax == 2) {
1253 $arrayofvat = $tabrclocaltax2;
1254 }
1255 if (!isset($arrayofvat[$key]) || !is_array($arrayofvat[$key])) {
1256 $arrayofvat[$key] = array();
1257 }
1258 }
1259 }
1260
1261 foreach ($arrayofvat[$key] as $k => $mt) {
1262 if ($mt) {
1263 print '<tr class="oddeven">';
1264 print "<!-- VAT -->";
1265 print "<td>".$date."</td>";
1266 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1267 // Account
1268 print "<td>";
1269 $accountoshow = length_accountg($k);
1270 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1271 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType3").')</span>';
1272 } else {
1273 print $accountoshow;
1274 }
1275 print "</td>";
1276 // Subledger account
1277 print "<td>";
1278 print '</td>';
1279 print "<td>";
1280 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1281 $labelvatrate = $langs->trans("Taxes").' '.$tmpvatrate.' %';
1282 $labelvatrate .= ($numtax ? ' - Localtax '.$numtax : '');
1283 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'supplier'), $invoicestatic->ref_supplier, $labelvatrate) . "</td>";
1284 print "</td>";
1285 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1286 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1287 print "</tr>";
1288
1289 $i++;
1290 }
1291 }
1292 }
1293
1294 // VAT counterpart for NPR
1295 if (isset($tabother[$key]) && is_array($tabother[$key])) {
1296 foreach ($tabother[$key] as $k => $mt) {
1297 if ($mt) {
1298 print '<tr class="oddeven">';
1299 print '<!-- VAT counterpart NPR -->';
1300 print "<td>".$date."</td>";
1301 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1302 // Account
1303 print '<td>';
1304 $accountoshow = length_accountg($k);
1305 if ($accountoshow == '' || $accountoshow == 'NotDefined') {
1306 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("NPR counterpart").'). Set ACCOUNTING_COUNTERPART_VAT_NPR to the subvention account</span>';
1307 } else {
1308 print $accountoshow;
1309 }
1310 print '</td>';
1311 // Subledger account
1312 print "<td>";
1313 print '</td>';
1314 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'supplier'), $invoicestatic->ref_supplier, $langs->trans("VAT")." NPR (counterpart)") . "</td>";
1315 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1316 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1317 print "</tr>";
1318
1319 $i++;
1320 }
1321 }
1322 }
1323 }
1324
1325 if (!$i) {
1326 print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1327 }
1328
1329 print "</table>";
1330 print '</div>';
1331
1332 // End of page
1333 llxFooter();
1334}
1335$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($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
llxFooter()
Footer empty.
Definition document.php:107
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.