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
393$sql = "
394SELECT
395 fk_facture,
396 COUNT(fd.rowid) as nb
397FROM
398 ".MAIN_DB_PREFIX."facturedet as fd
399WHERE
400 fd.product_type <= 2
401 AND fd.fk_code_ventilation <= 0
402 AND fd.total_ttc <> 0
403 AND fk_facture IN (".$db->sanitize(join(",", array_keys($tabfac))).")
404GROUP BY fk_facture
405";
406$resql = $db->query($sql);
407if ($resql) {
408 $num = $db->num_rows($resql);
409 $i = 0;
410 while ($i < $num) {
411 $obj = $db->fetch_object($resql);
412 if ($obj->nb > 0) {
413 $errorforinvoice[$obj->fk_facture_fourn] = 'somelinesarenotbound';
414 }
415 $i++;
416 }
417}
418//var_dump($errorforinvoice);exit;
419
420// Bookkeeping Write
421if ($action == 'writebookkeeping' && !$error) {
422 $now = dol_now();
423 $error = 0;
424
425 $companystatic = new Societe($db);
426 $invoicestatic = new Facture($db);
427 $accountingaccountcustomer = new AccountingAccount($db);
428
429 $accountingaccountcustomer->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
430
431 $accountingaccountcustomerwarranty = new AccountingAccount($db);
432
433 $accountingaccountcustomerwarranty->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
434
435 foreach ($tabfac as $key => $val) { // Loop on each invoice
436 $errorforline = 0;
437
438 $totalcredit = 0;
439 $totaldebit = 0;
440
441 $db->begin();
442
443 $companystatic->id = $tabcompany[$key]['id'];
444 $companystatic->name = $tabcompany[$key]['name'];
445 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
446 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
447 $companystatic->code_client = $tabcompany[$key]['code_client'];
448 $companystatic->client = 3;
449
450 $invoicestatic->id = $key;
451 $invoicestatic->ref = (string) $val["ref"];
452 $invoicestatic->type = $val["type"];
453 $invoicestatic->close_code = $val["close_code"];
454
455 $date = dol_print_date($val["date"], 'day');
456
457 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
458 $replacedinvoice = 0;
459 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
460 $replacedinvoice = 1;
461 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
462 if ($alreadydispatched) {
463 $replacedinvoice = 2;
464 }
465 }
466
467 // 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)
468 if ($replacedinvoice == 1) {
469 $db->rollback();
470 continue;
471 }
472
473 // Error if some lines are not binded/ready to be journalized
474 if ($errorforinvoice[$key] == 'somelinesarenotbound') {
475 $error++;
476 $errorforline++;
477 setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
478 }
479
480 // Warranty
481 if (!$errorforline && getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) {
482 if (is_array($tabwarranty[$key])) {
483 foreach ($tabwarranty[$key] as $k => $mt) {
484 $bookkeeping = new BookKeeping($db);
485 $bookkeeping->doc_date = $val["date"];
486 $bookkeeping->date_lim_reglement = $val["datereg"];
487 $bookkeeping->doc_ref = $val["ref"];
488 $bookkeeping->date_creation = $now;
489 $bookkeeping->doc_type = 'customer_invoice';
490 $bookkeeping->fk_doc = $key;
491 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
492 $bookkeeping->thirdparty_code = $companystatic->code_client;
493
494 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
495 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
496
497 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
498 $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
499
500 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Retainedwarranty");
501 $bookkeeping->montant = $mt;
502 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
503 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
504 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
505 $bookkeeping->code_journal = $journal;
506 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
507 $bookkeeping->fk_user_author = $user->id;
508 $bookkeeping->entity = $conf->entity;
509
510 $totaldebit += $bookkeeping->debit;
511 $totalcredit += $bookkeeping->credit;
512
513 $result = $bookkeeping->create($user);
514 if ($result < 0) {
515 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
516 $error++;
517 $errorforline++;
518 $errorforinvoice[$key] = 'alreadyjournalized';
519 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
520 } else {
521 $error++;
522 $errorforline++;
523 $errorforinvoice[$key] = 'other';
524 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
525 }
526 }
527 }
528 }
529 }
530
531 // Thirdparty
532 if (!$errorforline) {
533 foreach ($tabttc[$key] as $k => $mt) {
534 $bookkeeping = new BookKeeping($db);
535 $bookkeeping->doc_date = $val["date"];
536 $bookkeeping->date_lim_reglement = $val["datereg"];
537 $bookkeeping->doc_ref = $val["ref"];
538 $bookkeeping->date_creation = $now;
539 $bookkeeping->doc_type = 'customer_invoice';
540 $bookkeeping->fk_doc = $key;
541 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
542 $bookkeeping->thirdparty_code = $companystatic->code_client;
543
544 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
545 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
546
547 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
548 $bookkeeping->label_compte = $accountingaccountcustomer->label;
549
550 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount");
551 $bookkeeping->montant = $mt;
552 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
553 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
554 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
555 $bookkeeping->code_journal = $journal;
556 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
557 $bookkeeping->fk_user_author = $user->id;
558 $bookkeeping->entity = $conf->entity;
559
560 $totaldebit += $bookkeeping->debit;
561 $totalcredit += $bookkeeping->credit;
562
563 $result = $bookkeeping->create($user);
564 if ($result < 0) {
565 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
566 $error++;
567 $errorforline++;
568 $errorforinvoice[$key] = 'alreadyjournalized';
569 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
570 } else {
571 $error++;
572 $errorforline++;
573 $errorforinvoice[$key] = 'other';
574 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
575 }
576 } else {
577 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
578 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
579 $lettering_static = new Lettering($db);
580
581 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
582 }
583 }
584 }
585 }
586
587 // Product / Service
588 if (!$errorforline) {
589 foreach ($tabht[$key] as $k => $mt) {
590 $resultfetch = $accountingaccount->fetch(null, $k, true); // TODO Use a cache
591 $label_account = $accountingaccount->label;
592
593 // get compte id and label
594 if ($resultfetch > 0) {
595 $bookkeeping = new BookKeeping($db);
596 $bookkeeping->doc_date = $val["date"];
597 $bookkeeping->date_lim_reglement = $val["datereg"];
598 $bookkeeping->doc_ref = $val["ref"];
599 $bookkeeping->date_creation = $now;
600 $bookkeeping->doc_type = 'customer_invoice';
601 $bookkeeping->fk_doc = $key;
602 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
603 $bookkeeping->thirdparty_code = $companystatic->code_client;
604
605 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
606 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
607 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
608 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
609 } else {
610 $bookkeeping->subledger_account = '';
611 $bookkeeping->subledger_label = '';
612 }
613 } else {
614 $bookkeeping->subledger_account = '';
615 $bookkeeping->subledger_label = '';
616 }
617
618 $bookkeeping->numero_compte = $k;
619 $bookkeeping->label_compte = $label_account;
620
621 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$label_account;
622 $bookkeeping->montant = $mt;
623 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
624 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
625 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
626 $bookkeeping->code_journal = $journal;
627 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
628 $bookkeeping->fk_user_author = $user->id;
629 $bookkeeping->entity = $conf->entity;
630
631 $totaldebit += $bookkeeping->debit;
632 $totalcredit += $bookkeeping->credit;
633
634 $result = $bookkeeping->create($user);
635 if ($result < 0) {
636 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
637 $error++;
638 $errorforline++;
639 $errorforinvoice[$key] = 'alreadyjournalized';
640 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
641 } else {
642 $error++;
643 $errorforline++;
644 $errorforinvoice[$key] = 'other';
645 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
646 }
647 }
648 }
649 }
650 }
651
652 // VAT
653 if (!$errorforline) {
654 $listoftax = array(0, 1, 2);
655 foreach ($listoftax as $numtax) {
656 $arrayofvat = $tabtva;
657 if ($numtax == 1) {
658 $arrayofvat = $tablocaltax1;
659 }
660 if ($numtax == 2) {
661 $arrayofvat = $tablocaltax2;
662 }
663
664 foreach ($arrayofvat[$key] as $k => $mt) {
665 if ($mt) {
666 $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
667 $label_account = $accountingaccount->label;
668
669 $bookkeeping = new BookKeeping($db);
670 $bookkeeping->doc_date = $val["date"];
671 $bookkeeping->date_lim_reglement = $val["datereg"];
672 $bookkeeping->doc_ref = $val["ref"];
673 $bookkeeping->date_creation = $now;
674 $bookkeeping->doc_type = 'customer_invoice';
675 $bookkeeping->fk_doc = $key;
676 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
677 $bookkeeping->thirdparty_code = $companystatic->code_client;
678
679 $bookkeeping->subledger_account = '';
680 $bookkeeping->subledger_label = '';
681
682 $bookkeeping->numero_compte = $k;
683 $bookkeeping->label_compte = $label_account;
684
685
686 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref;
687 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : join(', ', $def_tva[$key][$k]));
688 $bookkeeping->label_operation .= ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
689 $bookkeeping->label_operation .= ($numtax ? ' - Localtax '.$numtax : '');
690
691 $bookkeeping->montant = $mt;
692 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
693 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
694 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
695 $bookkeeping->code_journal = $journal;
696 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
697 $bookkeeping->fk_user_author = $user->id;
698 $bookkeeping->entity = $conf->entity;
699
700 $totaldebit += $bookkeeping->debit;
701 $totalcredit += $bookkeeping->credit;
702
703 $result = $bookkeeping->create($user);
704 if ($result < 0) {
705 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
706 $error++;
707 $errorforline++;
708 $errorforinvoice[$key] = 'alreadyjournalized';
709 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
710 } else {
711 $error++;
712 $errorforline++;
713 $errorforinvoice[$key] = 'other';
714 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
715 }
716 }
717 }
718 }
719 }
720 }
721
722 // Revenue stamp
723 if (!$errorforline) {
724 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
725 foreach ($tabrevenuestamp[$key] as $k => $mt) {
726 if ($mt) {
727 $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
728 $label_account = $accountingaccount->label;
729
730 $bookkeeping = new BookKeeping($db);
731 $bookkeeping->doc_date = $val["date"];
732 $bookkeeping->date_lim_reglement = $val["datereg"];
733 $bookkeeping->doc_ref = $val["ref"];
734 $bookkeeping->date_creation = $now;
735 $bookkeeping->doc_type = 'customer_invoice';
736 $bookkeeping->fk_doc = $key;
737 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
738 $bookkeeping->thirdparty_code = $companystatic->code_client;
739
740 $bookkeeping->subledger_account = '';
741 $bookkeeping->subledger_label = '';
742
743 $bookkeeping->numero_compte = $k;
744 $bookkeeping->label_compte = $label_account;
745
746 $bookkeeping->label_operation = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp");
747 $bookkeeping->montant = $mt;
748 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
749 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
750 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
751 $bookkeeping->code_journal = $journal;
752 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
753 $bookkeeping->fk_user_author = $user->id;
754 $bookkeeping->entity = $conf->entity;
755
756 $totaldebit += $bookkeeping->debit;
757 $totalcredit += $bookkeeping->credit;
758
759 $result = $bookkeeping->create($user);
760 if ($result < 0) {
761 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
762 $error++;
763 $errorforline++;
764 $errorforinvoice[$key] = 'alreadyjournalized';
765 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
766 } else {
767 $error++;
768 $errorforline++;
769 $errorforinvoice[$key] = 'other';
770 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
771 }
772 }
773 }
774 }
775 }
776 }
777
778 // Protection against a bug on lines before
779 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
780 $error++;
781 $errorforline++;
782 $errorforinvoice[$key] = 'amountsnotbalanced';
783 setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
784 }
785
786 if (!$errorforline) {
787 $db->commit();
788 } else {
789 $db->rollback();
790
791 if ($error >= 10) {
792 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
793 break; // Break in the foreach
794 }
795 }
796 }
797
798 $tabpay = $tabfac;
799
800 if (empty($error) && count($tabpay) > 0) {
801 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
802 } elseif (count($tabpay) == $error) {
803 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
804 } else {
805 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
806 }
807
808 $action = '';
809
810 // Must reload data, so we make a redirect
811 if (count($tabpay) != $error) {
812 $param = 'id_journal='.$id_journal;
813 $param .= '&date_startday='.$date_startday;
814 $param .= '&date_startmonth='.$date_startmonth;
815 $param .= '&date_startyear='.$date_startyear;
816 $param .= '&date_endday='.$date_endday;
817 $param .= '&date_endmonth='.$date_endmonth;
818 $param .= '&date_endyear='.$date_endyear;
819 $param .= '&in_bookkeeping='.$in_bookkeeping;
820 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
821 exit;
822 }
823}
824
825
826
827/*
828 * View
829 */
830
831$form = new Form($db);
832
833// Export
834if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
835 // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL
836 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
837
838 $filename = 'journal';
839 $type_export = 'journal';
840 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
841
842 $companystatic = new Client($db);
843 $invoicestatic = new Facture($db);
844
845 foreach ($tabfac as $key => $val) {
846 $companystatic->id = $tabcompany[$key]['id'];
847 $companystatic->name = $tabcompany[$key]['name'];
848 $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
849 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
850 $companystatic->code_client = $tabcompany[$key]['code_client'];
851 $companystatic->client = 3;
852
853 $invoicestatic->id = $key;
854 $invoicestatic->ref = (string) $val["ref"];
855 $invoicestatic->type = $val["type"];
856 $invoicestatic->close_code = $val["close_code"];
857
858 $date = dol_print_date($val["date"], 'day');
859
860 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
861 $replacedinvoice = 0;
862 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
863 $replacedinvoice = 1;
864 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
865 if ($alreadydispatched) {
866 $replacedinvoice = 2;
867 }
868 }
869
870 // 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)
871 if ($replacedinvoice == 1) {
872 continue;
873 }
874
875 // Warranty
876 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) {
877 foreach ($tabwarranty[$key] as $k => $mt) {
878 //if ($mt) {
879 print '"'.$key.'"'.$sep;
880 print '"'.$date.'"'.$sep;
881 print '"'.$val["ref"].'"'.$sep;
882 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
883 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
884 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
885 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
886 print '"'.$langs->trans("Thirdparty").'"'.$sep;
887 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").'"'.$sep;
888 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
889 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
890 print '"'.$journal.'"';
891 print "\n";
892 //}
893 }
894 }
895
896 // Third party
897 foreach ($tabttc[$key] as $k => $mt) {
898 //if ($mt) {
899 print '"'.$key.'"'.$sep;
900 print '"'.$date.'"'.$sep;
901 print '"'.$val["ref"].'"'.$sep;
902 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
903 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
904 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')).'"'.$sep;
905 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
906 print '"'.$langs->trans("Thirdparty").'"'.$sep;
907 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("Thirdparty").'"'.$sep;
908 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
909 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
910 print '"'.$journal.'"';
911 print "\n";
912 //}
913 }
914
915 // Product / Service
916 foreach ($tabht[$key] as $k => $mt) {
917 $accountingaccount = new AccountingAccount($db);
918 $accountingaccount->fetch(null, $k, true);
919 //if ($mt) {
920 print '"'.$key.'"'.$sep;
921 print '"'.$date.'"'.$sep;
922 print '"'.$val["ref"].'"'.$sep;
923 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
924 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
925 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
926 print '""'.$sep;
927 print '"'.mb_convert_encoding(dol_trunc($accountingaccount->label, 32), 'ISO-8859-1').'"'.$sep;
928 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.dol_trunc($accountingaccount->label, 32).'"'.$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
937 $listoftax = array(0, 1, 2);
938 foreach ($listoftax as $numtax) {
939 $arrayofvat = $tabtva;
940 if ($numtax == 1) {
941 $arrayofvat = $tablocaltax1;
942 }
943 if ($numtax == 2) {
944 $arrayofvat = $tablocaltax2;
945 }
946
947 foreach ($arrayofvat[$key] as $k => $mt) {
948 if ($mt) {
949 print '"'.$key.'"'.$sep;
950 print '"'.$date.'"'.$sep;
951 print '"'.$val["ref"].'"'.$sep;
952 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
953 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
954 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
955 print '""'.$sep;
956 print '"'.$langs->trans("VAT").' - '.join(', ', $def_tva[$key][$k]).' %"'.$sep;
957 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;
958 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
959 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
960 print '"'.$journal.'"';
961 print "\n";
962 }
963 }
964 }
965
966 // Revenue stamp
967 if (isset($tabrevenuestamp[$key])) {
968 foreach ($tabrevenuestamp[$key] as $k => $mt) {
969 //if ($mt) {
970 print '"'.$key.'"'.$sep;
971 print '"'.$date.'"'.$sep;
972 print '"'.$val["ref"].'"'.$sep;
973 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 32), 'ISO-8859-1').'"'.$sep;
974 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
975 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
976 print '""'.$sep;
977 print '"'.$langs->trans("RevenueStamp").'"'.$sep;
978 print '"'.mb_convert_encoding(dol_trunc($companystatic->name, 16), 'ISO-8859-1').' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").'"'.$sep;
979 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
980 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
981 print '"'.$journal.'"';
982 print "\n";
983 //}
984 }
985 }
986 }
987}
988
989
990
991if (empty($action) || $action == 'view') {
992 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
993
994 llxHeader('', dol_string_nohtmltag($title));
995
996 $nom = $title;
997 $nomlink = '';
998 $periodlink = '';
999 $exportlink = '';
1000 $builddate = dol_now();
1001 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
1002 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
1003 $description .= $langs->trans("DepositsAreNotIncluded");
1004 } else {
1005 $description .= $langs->trans("DepositsAreIncluded");
1006 }
1007
1008 $listofchoices = array('notyet'=>$langs->trans("NotYetInGeneralLedger"), 'already'=>$langs->trans("AlreadyInGeneralLedger"));
1009 $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);
1010 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
1011
1012 $varlink = 'id_journal='.$id_journal;
1013
1014 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
1015
1016 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
1017 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
1018 // Fiscal period test
1019 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
1020 $resql = $db->query($sql);
1021 if ($resql) {
1022 $obj = $db->fetch_object($resql);
1023 if ($obj->nb == 0) {
1024 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
1025 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
1026 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
1027 print $desc;
1028 print '</div>';
1029 }
1030 } else {
1031 dol_print_error($db);
1032 }
1033 }
1034
1035 // Button to write into Ledger
1036 $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
1037 if ($acctCustomerNotConfigured) {
1038 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1039 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
1040 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
1041 print $desc;
1042 print '</div>';
1043 }
1044 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1045 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
1046 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1047 }
1048 if ($acctCustomerNotConfigured) {
1049 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1050 } else {
1051 if ($in_bookkeeping == 'notyet') {
1052 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1053 } else {
1054 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1055 }
1056 }
1057 print '</div>';
1058
1059 // TODO Avoid using js. We can use a direct link with $param
1060 print '
1061 <script type="text/javascript">
1062 function launch_export() {
1063 $("div.fiche form input[name=\"action\"]").val("exportcsv");
1064 $("div.fiche form input[type=\"submit\"]").click();
1065 $("div.fiche form input[name=\"action\"]").val("");
1066 }
1067 function writebookkeeping() {
1068 console.log("click on writebookkeeping");
1069 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1070 $("div.fiche form input[type=\"submit\"]").click();
1071 $("div.fiche form input[name=\"action\"]").val("");
1072 }
1073 </script>';
1074
1075 /*
1076 * Show result array
1077 */
1078 print '<br>';
1079
1080 print '<div class="div-table-responsive">';
1081 print "<table class=\"noborder\" width=\"100%\">";
1082 print "<tr class=\"liste_titre\">";
1083 print "<td>".$langs->trans("Date")."</td>";
1084 print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1085 print "<td>".$langs->trans("AccountAccounting")."</td>";
1086 print "<td>".$langs->trans("SubledgerAccount")."</td>";
1087 print "<td>".$langs->trans("LabelOperation")."</td>";
1088 print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1089 print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1090 print "</tr>\n";
1091
1092 $i = 0;
1093
1094 $companystatic = new Client($db);
1095 $invoicestatic = new Facture($db);
1096
1097 foreach ($tabfac as $key => $val) {
1098 $companystatic->id = $tabcompany[$key]['id'];
1099 $companystatic->name = $tabcompany[$key]['name'];
1100 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
1101 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1102 $companystatic->code_client = $tabcompany[$key]['code_client'];
1103 $companystatic->client = 3;
1104
1105 $invoicestatic->id = $key;
1106 $invoicestatic->ref = (string) $val["ref"];
1107 $invoicestatic->type = $val["type"];
1108 $invoicestatic->close_code = $val["close_code"];
1109
1110 $date = dol_print_date($val["date"], 'day');
1111
1112 // Is it a replaced invoice ? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1113 $replacedinvoice = 0;
1114 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1115 $replacedinvoice = 1;
1116 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1117 if ($alreadydispatched) {
1118 $replacedinvoice = 2;
1119 }
1120 }
1121
1122 // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1123 if ($replacedinvoice == 1) {
1124 print '<tr class="oddeven">';
1125 print "<!-- Replaced invoice -->";
1126 print "<td>".$date."</td>";
1127 print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1128 // Account
1129 print "<td>";
1130 print $langs->trans("Replaced");
1131 print '</td>';
1132 // Subledger account
1133 print "<td>";
1134 print '</td>';
1135 print "<td>";
1136 print "</td>";
1137 print '<td class="right"></td>';
1138 print '<td class="right"></td>';
1139 print "</tr>";
1140
1141 $i++;
1142 continue;
1143 }
1144 if ($errorforinvoice[$key] == 'somelinesarenotbound') {
1145 print '<tr class="oddeven">';
1146 print "<!-- Some lines are not bound -->";
1147 print "<td>".$date."</td>";
1148 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1149 // Account
1150 print "<td>";
1151 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
1152 print '</td>';
1153 // Subledger account
1154 print "<td>";
1155 print '</td>';
1156 print "<td>";
1157 print "</td>";
1158 print '<td class="right"></td>';
1159 print '<td class="right"></td>';
1160 print "</tr>";
1161
1162 $i++;
1163 }
1164
1165 // Warranty
1166 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
1167 foreach ($tabwarranty[$key] as $k => $mt) {
1168 print '<tr class="oddeven">';
1169 print "<!-- Thirdparty warranty -->";
1170 print "<td>" . $date . "</td>";
1171 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1172 // Account
1173 print "<td>";
1174 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
1175 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1176 print '<span class="error">' . $langs->trans("MainAccountForRetainedWarrantyNotDefined") . '</span>';
1177 } else {
1178 print $accountoshow;
1179 }
1180 print '</td>';
1181 // Subledger account
1182 print "<td>";
1183 $accountoshow = length_accounta($k);
1184 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1185 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1186 } else {
1187 print $accountoshow;
1188 }
1189 print '</td>';
1190 print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Retainedwarranty") . "</td>";
1191 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1192 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1193 print "</tr>";
1194 }
1195 }
1196
1197 // Third party
1198 foreach ($tabttc[$key] as $k => $mt) {
1199 print '<tr class="oddeven">';
1200 print "<!-- Thirdparty -->";
1201 print "<td>".$date."</td>";
1202 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1203 // Account
1204 print "<td>";
1205 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
1206 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1207 print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
1208 } else {
1209 print $accountoshow;
1210 }
1211 print '</td>';
1212 // Subledger account
1213 print "<td>";
1214 $accountoshow = length_accounta($k);
1215 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1216 print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1217 } else {
1218 print $accountoshow;
1219 }
1220 print '</td>';
1221 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("SubledgerAccount")."</td>";
1222 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1223 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1224 print "</tr>";
1225
1226 $i++;
1227 }
1228
1229 // Product / Service
1230 foreach ($tabht[$key] as $k => $mt) {
1231 $accountingaccount = new AccountingAccount($db);
1232 $accountingaccount->fetch(null, $k, true);
1233
1234 print '<tr class="oddeven">';
1235 print "<!-- Product -->";
1236 print "<td>".$date."</td>";
1237 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1238 // Account
1239 print "<td>";
1240 $accountoshow = length_accountg($k);
1241 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1242 print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1243 } else {
1244 print $accountoshow;
1245 }
1246 print "</td>";
1247 // Subledger account
1248 print "<td>";
1249 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1250 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1251 print length_accounta($tabcompany[$key]['code_compta']);
1252 }
1253 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1254 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1255 }
1256 print '</td>';
1257 $companystatic->id = $tabcompany[$key]['id'];
1258 $companystatic->name = $tabcompany[$key]['name'];
1259 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$accountingaccount->label."</td>";
1260 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1261 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1262 print "</tr>";
1263
1264 $i++;
1265 }
1266
1267 // VAT
1268 $listoftax = array(0, 1, 2);
1269 foreach ($listoftax as $numtax) {
1270 $arrayofvat = $tabtva;
1271 if ($numtax == 1) {
1272 $arrayofvat = $tablocaltax1;
1273 }
1274 if ($numtax == 2) {
1275 $arrayofvat = $tablocaltax2;
1276 }
1277
1278 // $key is id of invoice
1279 foreach ($arrayofvat[$key] as $k => $mt) {
1280 if ($mt) {
1281 print '<tr class="oddeven">';
1282 print "<!-- VAT -->";
1283 print "<td>".$date."</td>";
1284 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1285 // Account
1286 print "<td>";
1287 $accountoshow = length_accountg($k);
1288 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1289 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType2").')</span>';
1290 } else {
1291 print $accountoshow;
1292 }
1293 print "</td>";
1294 // Subledger account
1295 print "<td>";
1296 print '</td>';
1297 print "<td>".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref;
1298 // $def_tva is array[invoiceid][accountancy_code_sell_of_vat_rate_found][vatrate]=vatrate
1299 //var_dump($arrayofvat[$key]); var_dump($key); var_dump($k);
1300 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : join(', ', $def_tva[$key][$k]));
1301 print ' - '.$langs->trans("Taxes").' '.$tmpvatrate.' %';
1302 print($numtax ? ' - Localtax '.$numtax : '');
1303 print "</td>";
1304 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1305 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1306 print "</tr>";
1307
1308 $i++;
1309 }
1310 }
1311 }
1312
1313 // Revenue stamp
1314 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
1315 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1316 print '<tr class="oddeven">';
1317 print "<!-- Thirdparty revenuestamp -->";
1318 print "<td>" . $date . "</td>";
1319 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1320 // Account
1321 print "<td>";
1322 $accountoshow = length_accountg($k);
1323 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1324 print '<span class="error">' . $langs->trans("MainAccountForRevenueStampSaleNotDefined") . '</span>';
1325 } else {
1326 print $accountoshow;
1327 }
1328 print '</td>';
1329 // Subledger account
1330 print "<td>";
1331 print '</td>';
1332 print "<td>" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp") . "</td>";
1333 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1334 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1335 print "</tr>";
1336 }
1337 }
1338 }
1339
1340 if (!$i) {
1341 print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1342 }
1343
1344 print "</table>";
1345 print '</div>';
1346
1347 // End of page
1348 llxFooter();
1349}
1350
1351$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.