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