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