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