dolibarr 24.0.1
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-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
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-2025 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
13 * Copyright (C) 2025 Vincent de Grandporé <vincent@de-grandpre.quebec>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 */
28
35// Load Dolibarr environment
36require '../../main.inc.php';
45require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
49require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
50require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
51require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php';
52require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
53
54// Load translation files required by the page
55$langs->loadLangs(array("commercial", "compta", "bills", "other", "accountancy", "errors"));
56
57$id_journal = GETPOSTINT('id_journal');
58$action = GETPOST('action', 'aZ09');
59
60$date_startmonth = GETPOSTINT('date_startmonth');
61$date_startday = GETPOSTINT('date_startday');
62$date_startyear = GETPOSTINT('date_startyear');
63$date_endmonth = GETPOSTINT('date_endmonth');
64$date_endday = GETPOSTINT('date_endday');
65$date_endyear = GETPOSTINT('date_endyear');
66$in_bookkeeping = GETPOST('in_bookkeeping');
67if ($in_bookkeeping == '') {
68 $in_bookkeeping = 'notyet';
69}
70
71$now = dol_now();
72
73$hookmanager->initHooks(array('sellsjournal'));
74$parameters = array();
75
76// Security check
77if (!isModEnabled('accounting')) {
79}
80if ($user->socid > 0) {
82}
83if (!$user->hasRight('accounting', 'bind', 'write')) {
85}
86
87$error = 0;
88
89$tabfac = array();
90$tabht = array();
91$tabtva = array();
92$tabwarranty = array();
93$tabttc = array();
94$tablocaltax1 = array();
95$tablocaltax2 = array();
96$tabCustomerDiscountHT = array();
97$tabCustomerDiscountVAT = array();
98$tabCustomerDiscountTTC = array();
99
100$manageCustomerDepositInInvoice = getDolGlobalInt('ACCOUNTING_MANAGE_CUSTOMER_DEPOSIT_IN_INVOICE');
101$labelCustomerDiscountExtension = ' (AC)';
102
103$cptcli = 'NotDefined';
104$accountCustomerDeposit = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT', 'NotDefined');
105$accountCustomerDepositVAT = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT_FOR_VAT', 'NotDefined');
106
107/*
108 * Actions
109 */
110
111$reshook = $hookmanager->executeHooks('doActions', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
112
113$accountingaccount = new AccountingAccount($db);
114
115// Get information of a journal
116$accountingjournalstatic = new AccountingJournal($db);
117$accountingjournalstatic->fetch($id_journal);
118$journal = $accountingjournalstatic->code;
119$journal_label = $accountingjournalstatic->label;
120
121$date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
122$date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
123
124$pastmonth = null; // Initialise, could be unset
125$pastmonthyear = null; // Initialise, could be unset
126
127if (empty($date_startmonth)) {
128 // Period by default on transfer
130 $date_start = $dates['date_start'];
131 $pastmonthyear = $dates['pastmonthyear'];
132 $pastmonth = $dates['pastmonth'];
133}
134if (empty($date_endmonth)) {
135 // Period by default on transfer
137 $date_end = $dates['date_end'];
138 $pastmonthyear = $dates['pastmonthyear'];
139 $pastmonth = $dates['pastmonth'];
140}
141if (getDolGlobalString('ACCOUNTANCY_JOURNAL_USE_CURRENT_MONTH')) {
142 $pastmonth += 1;
143}
144
145if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end))) { // We define date_start and date_end, only if we did not submit the form
146 $date_start = dol_get_first_day((int) $pastmonthyear, (int) $pastmonth, false);
147 $date_end = dol_get_last_day((int) $pastmonthyear, (int) $pastmonth, false);
148}
149
150$sql = "SELECT f.rowid, f.ref, f.type, f.module_source, 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, f.situation_final,";
151$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.localtax1_tx, fd.localtax2_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code, fd.info_bits,";
152$sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur, s.fk_pays,";
153if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
154 $sql .= " spe.accountancy_code_customer_general,";
155 $sql .= " spe.accountancy_code_customer as code_compta_client,";
156 $sql .= " spe.accountancy_code_supplier_general,";
157 $sql .= " spe.accountancy_code_supplier as code_compta_fournisseur,";
158} else {
159 $sql .= " s.accountancy_code_customer_general,";
160 $sql .= " s.code_compta as code_compta_client,";
161 $sql .= " s.accountancy_code_supplier_general,";
162 $sql .= " s.code_compta_fournisseur,";
163}
164$sql .= " p.rowid as pid, p.ref as pref, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte,";
165if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
166 $sql .= " ppe.accountancy_code_sell";
167} else {
168 $sql .= " p.accountancy_code_sell";
169}
170$parameters = array();
171$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
172$sql .= $hookmanager->resPrint;
173$sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
174$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product";
175if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
176 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity);
177}
178$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
179$sql .= " JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = fd.fk_facture";
180$sql .= " JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
181if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) {
182 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = " . ((int) $conf->entity);
183}
184$parameters = array();
185$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
186$sql .= $hookmanager->resPrint;
187$sql .= " WHERE fd.fk_code_ventilation > 0";
188$sql .= " AND f.entity IN (".getEntity('invoice', 0).')'; // We don't share object for accountancy, we use source object sharing
189$sql .= " AND f.fk_statut > 0";
190if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) { // Non common setup
191 $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_SITUATION.")";
192} else {
193 $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".Facture::TYPE_DEPOSIT.",".Facture::TYPE_SITUATION.")";
194}
195$sql .= " AND fd.product_type IN (0,1)";
196if ($date_start && $date_end) {
197 $sql .= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
198}
199if (getDolGlobalInt('ACCOUNTING_DISSOCIATE_CASH_SALES')) {
200 $sql .= " AND (f.module_source IS NULL OR f.module_source <> 'takepos')";
201}
202// Define begin binding date
203if (getDolGlobalInt('ACCOUNTING_DATE_START_BINDING')) {
204 $sql .= " AND f.datef >= '".$db->idate(getDolGlobalInt('ACCOUNTING_DATE_START_BINDING'))."'";
205}
206// Already in bookkeeping or not
207if ($in_bookkeeping == 'already') {
208 $sql .= " AND f.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
209 // $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
210}
211if ($in_bookkeeping == 'notyet') {
212 $sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
213 // $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
214}
215if ($manageCustomerDepositInInvoice) {
216 $sql .= " AND (fd.description != '(DEPOSIT)' OR COALESCE(fd.fk_remise_except, 0) = 0)";
217}
218$parameters = array();
219$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
220$sql .= $hookmanager->resPrint;
221$sql .= " ORDER BY f.datef, f.ref";
222//print $sql;
223
224dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG);
225$tabfac = array();
226$tabht = array();
227$tabtva = array();
228$def_tva = array();
229$tabwarranty = array();
230$tabrevenuestamp = array();
231$tabttc = array();
232$tablocaltax1 = array();
233$tablocaltax2 = array();
234$tabcompany = array();
235$vatdata_cache = array();
236$tabCustomerDiscountHT = array();
237$tabCustomerDiscountVAT = array();
238$tabCustomerDiscountTTC = array();
239
240// Variables
241$cptcli = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER', 'NotDefined');
242$cpttva = getDolGlobalString('ACCOUNTING_VAT_SOLD_ACCOUNT', 'NotDefined');
243$cptlocaltax1 = getDolGlobalString('ACCOUNTING_LT1_SOLD_ACCOUNT', 'NotDefined');
244$cptlocaltax2 = getDolGlobalString('ACCOUNTING_LT2_SOLD_ACCOUNT', 'NotDefined');
245
246$result = $db->query($sql);
247if ($result) {
248 $num = $db->num_rows($result);
249
250 $i = 0;
251 while ($i < $num) {
252 $obj = $db->fetch_object($result);
253
254 // Controls
255 $accountancy_code_customer_general = (!empty($obj->accountancy_code_customer_general) && $obj->accountancy_code_customer_general != '-1') ? $obj->accountancy_code_customer_general : $cptcli;
256 $compta_soc = (!empty($obj->code_compta_client)) ? $obj->code_compta_client : $cptcli;
257
258 $compta_prod = $obj->compte;
259 if (empty($compta_prod)) {
260 if ($obj->product_type == 0) {
261 $compta_prod = getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT', 'NotDefined');
262 } else {
263 $compta_prod = getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT', 'NotDefined');
264 }
265 }
266
267 // $compta_revenuestamp = getDolGlobalString('ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT', 'NotDefined');
268
269 $tax_id = $obj->tva_tx . ($obj->vat_src_code ? ' (' . $obj->vat_src_code . ')' : '');
270 // SERVICE_ARE_ECOMMERCE_200238EC makes the chosen accountancy code depend on the buyer country,
271 // so the cache key must include the buyer country to avoid serving a previous buyer's result.
272 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) {
273 $vatdata_cache_key = $tax_id.'_'.(int) $obj->fk_pays;
274 } else {
275 $vatdata_cache_key = $tax_id;
276 }
277 if (array_key_exists($vatdata_cache_key, $vatdata_cache)) {
278 $vatdata = $vatdata_cache[$vatdata_cache_key];
279 } else {
280 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) {
281 $buyer = new Societe($db);
282 $buyer->fetch($obj->socid);
283 } else {
284 $buyer = null; // We don't need the buyer in this case
285 }
286 $seller = $mysoc;
287 $vatdata = getTaxesFromId($tax_id, $buyer, $seller, 0);
288 $vatdata_cache[$vatdata_cache_key] = $vatdata;
289 }
290 if (!empty(length_accountg($accountCustomerDepositVAT)) && $accountCustomerDepositVAT != 'NotDefined' && $obj->type == Facture::TYPE_DEPOSIT) {
291 // customer deposit account for VAT
292 $compta_tva = $accountCustomerDepositVAT;
293 } else {
294 $compta_tva = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva);
295 }
296 $compta_localtax1 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cptlocaltax1);
297 $compta_localtax2 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cptlocaltax2);
298
299 // Define the array to store the detail of each vat rate and code for lines
300 if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) {
301 $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.')' : ''));
302 if ($obj->localtax1_tx > 0.0) {
303 $def_tva[$obj->rowid][$compta_localtax1][vatrate($obj->localtax1_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '').' LT1'] = (vatrate($obj->localtax1_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''));
304 }
305 if ($obj->localtax2_tx > 0.0) {
306 $def_tva[$obj->rowid][$compta_localtax2][vatrate($obj->localtax2_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '').' LT2'] = (vatrate($obj->localtax2_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''));
307 }
308 }
309
310 // Create a compensation rate for situation invoice.
311 $situation_ratio = 1;
312 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
313 if ($obj->situation_cycle_ref) {
314 // Avoid divide by 0
315 if ($obj->situation_percent == 0) {
316 $situation_ratio = 0;
317 } else {
318 $line = new FactureLigne($db);
319 $line->fetch($obj->fdid);
320
321 // Situation invoices handling
322 $prev_progress = $line->get_prev_progress($obj->rowid);
323
324 $situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
325 }
326 }
327 }
328
329 $revenuestamp = (float) price2num($obj->revenuestamp, 'MT');
330
331 if ($manageCustomerDepositInInvoice && $obj->type == Facture::TYPE_STANDARD && !isset($tabfac[$obj->rowid])) {
332 // Get all linked invoice deposit consumed by this invoice
333 $sql2 = "SELECT re.rowid";
334 $sql2 .= " FROM " . $db->prefix() . "societe_remise_except as re";
335 $sql2 .= " WHERE (re.fk_facture = " . ((int) $obj->rowid);
336 $sql2 .= " OR re.fk_facture_line IN (SELECT rowid FROM " . $db->prefix() . "facturedet WHERE fk_facture = " . ((int) $obj->rowid) . ")";
337 $sql2 .= ")";
338
339 $resql2 = $db->query($sql2);
340 if ($resql2) {
341 if ($db->num_rows($resql2) > 0) {
342 if (!isset($tabCustomerDiscountHT[$obj->rowid][$accountCustomerDeposit])) {
343 $tabCustomerDiscountHT[$obj->rowid][$accountCustomerDeposit] = 0;
344 }
345 if (!isset($tabCustomerDiscountVAT[$obj->rowid][$accountCustomerDepositVAT])) {
346 $tabCustomerDiscountVAT[$obj->rowid][$accountCustomerDepositVAT] = 0;
347 }
348 if (!isset($tabCustomerDiscountTTC[$obj->rowid][$compta_soc])) {
349 $tabCustomerDiscountTTC[$obj->rowid][$compta_soc] = 0;
350 }
351
352 while ($obj2 = $db->fetch_object($resql2)) {
353 $customerDiscount = new DiscountAbsolute($db);
354 $customerDiscount->fetch($obj2->rowid);
355 // Accumulate: an invoice can consume several deposits, and the (DEPOSIT) lines are
356 // excluded from the main query, so this reversal is their only trace in the journal.
357 $tabCustomerDiscountHT[$obj->rowid][$accountCustomerDeposit] -= $customerDiscount->total_ht;
358 $tabCustomerDiscountVAT[$obj->rowid][$accountCustomerDepositVAT] -= $customerDiscount->total_tva;
359 $tabCustomerDiscountTTC[$obj->rowid][$compta_soc] -= $customerDiscount->total_ttc;
360 }
361 }
362 $db->free($resql2);
363 } else {
365 }
366 }
367
368 // Invoice lines
369 $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
370 $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
371 $tabfac[$obj->rowid]["ref"] = $obj->ref;
372 $tabfac[$obj->rowid]["type"] = $obj->type;
373 $tabfac[$obj->rowid]["description"] = $obj->label_compte;
374 $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
375 $tabfac[$obj->rowid]["revenuestamp"] = $revenuestamp;
376 //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
377
378 // Avoid warnings
379 if (!isset($tabttc[$obj->rowid][$compta_soc])) {
380 $tabttc[$obj->rowid][$compta_soc] = 0;
381 }
382 if (!isset($tabht[$obj->rowid][$compta_prod])) {
383 $tabht[$obj->rowid][$compta_prod] = 0;
384 }
385 if (!isset($tabtva[$obj->rowid][$compta_tva])) {
386 $tabtva[$obj->rowid][$compta_tva] = 0;
387 }
388 if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
389 $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
390 }
391 if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
392 $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
393 }
394
395 // Compensation of data for invoice situation by using $situation_ratio. This works (nearly) for invoice that was not correctly recorded
396 // but it may introduces an error for situation invoices that were correctly saved. There is still rounding problem that differs between
397 // real data we should have stored and result obtained with a compensation.
398 // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact).
399 // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes.
400 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
401 $total_ttc = $obj->total_ttc * $situation_ratio;
402 } else {
403 $total_ttc = $obj->total_ttc;
404 }
405
406 // Move a part of the retained warrenty into the account of warranty
407 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0 && (!getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION') || !empty($obj->situation_final))) {
408 $retained_warranty = (float) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); // Calculate the amount of warrenty for this line (using the percent value)
409 $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty;
410 $total_ttc -= $retained_warranty;
411 }
412
413 $tabttc[$obj->rowid][$compta_soc] += $total_ttc;
414 $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
415 $tva_npr = ((($obj->info_bits & 1) == 1) ? 1 : 0);
416 if (!$tva_npr) { // We ignore line if VAT is a NPR
417 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) {
418 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
419 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
420 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
421 } else {
422 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
423 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio;
424 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio;
425 }
426 }
427
428 $compta_revenuestamp = 'NotDefined';
429 if (!empty($revenuestamp)) {
430 $sqlrevenuestamp = "SELECT accountancy_code_sell FROM ".MAIN_DB_PREFIX."c_revenuestamp";
431 $sqlrevenuestamp .= " WHERE fk_pays = ".((int) $mysoc->country_id);
432 $sqlrevenuestamp .= " AND taux = ".((float) $revenuestamp);
433 $sqlrevenuestamp .= " AND active = 1";
434 $resqlrevenuestamp = $db->query($sqlrevenuestamp);
435
436 if ($resqlrevenuestamp) {
437 $num_rows_revenuestamp = $db->num_rows($resqlrevenuestamp);
438 if ($num_rows_revenuestamp > 1) {
439 dol_print_error($db, 'Failed 2 or more lines for the revenue stamp of your country. Check the dictionary of revenue stamp.');
440 } else {
441 $objrevenuestamp = $db->fetch_object($resqlrevenuestamp);
442 if ($objrevenuestamp) {
443 $compta_revenuestamp = $objrevenuestamp->accountancy_code_sell;
444 }
445 }
446 }
447 }
448
449 if (empty($tabrevenuestamp[$obj->rowid][$compta_revenuestamp]) && !empty($revenuestamp)) {
450 // The revenue stamp was never seen for this invoice id=$obj->rowid
451 $tabttc[$obj->rowid][$compta_soc] += $obj->revenuestamp;
452 $tabrevenuestamp[$obj->rowid][$compta_revenuestamp] = $obj->revenuestamp;
453 }
454
455 $tabcompany[$obj->rowid] = array(
456 'id' => $obj->socid,
457 'name' => $obj->name,
458 'code_client' => $obj->code_client,
459 'accountancy_code_customer_general' => $accountancy_code_customer_general,
460 'code_compta' => $compta_soc
461 );
462
463 // After the line is processed
464 $parameters = array(
465 'obj' => $obj,
466 'tabfac' => &$tabfac,
467 'tabht' => &$tabht,
468 'tabtva' => &$tabtva,
469 'def_tva' => &$def_tva,
470 'tabwarranty' => &$tabwarranty,
471 'tabrevenuestamp' => &$tabrevenuestamp,
472 'tabttc' => &$tabttc,
473 'tablocaltax1' => &$tablocaltax1,
474 'tablocaltax2' => &$tablocaltax2,
475 'tabcompany' => &$tabcompany,
476 'vatdata_cache' => &$vatdata_cache,
477 );
478 $reshook = $hookmanager->executeHooks('processingJournalData', $parameters); // Note that $action and $object may have been modified by hook
479
480 $i++;
481
482 // Check for too many lines.
483 if ($i > getDolGlobalInt('ACCOUNTANCY_MAX_TOO_MANY_LINES_TO_PROCESS', 10000)) {
484 $error++;
485 setEventMessages("ErrorTooManyLinesToProcessPleaseUseAMoreSelectiveFilter", null, 'errors');
486 break;
487 }
488 }
489
490 // After the loop on each line
491 $parameters = array(
492 'tabfac' => &$tabfac,
493 'tabht' => &$tabht,
494 'tabtva' => &$tabtva,
495 'def_tva' => &$def_tva,
496 'tabwarranty' => &$tabwarranty,
497 'tabrevenuestamp' => &$tabrevenuestamp,
498 'tabttc' => &$tabttc,
499 'tablocaltax1' => &$tablocaltax1,
500 'tablocaltax2' => &$tablocaltax2,
501 'tabcompany' => &$tabcompany,
502 'vatdata_cache' => &$vatdata_cache,
503 );
504 $reshook = $hookmanager->executeHooks('processedJournalData', $parameters); // Note that $action and $object may have been modified by hook
505} else {
507}
508
509
510$errorforinvoice = array();
511
512/*
513// Old way, 1 query for each invoice
514// Loop on all invoices to detect lines without binded code (fk_code_ventilation <= 0)
515foreach ($tabfac as $key => $val) { // Loop on each invoice
516 $sql = "SELECT COUNT(fd.rowid) as nb";
517 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
518 $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
519 $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key);
520 $resql = $db->query($sql);
521 if ($resql) {
522 $obj = $db->fetch_object($resql);
523 if ($obj->nb > 0) {
524 $errorforinvoice[$key] = 'somelinesarenotbound';
525 }
526 } else {
527 dol_print_error($db);
528 }
529}
530*/
531// New way, single query, load all unbound lines
532if (!empty($tabfac)) {
533 $sql = "
534 SELECT
535 fk_facture,
536 COUNT(fd.rowid) as nb
537 FROM
538 ".MAIN_DB_PREFIX."facturedet as fd
539 WHERE
540 fd.product_type <= 2
541 AND fd.fk_code_ventilation <= 0
542 AND fd.total_ttc <> 0
543 AND fk_facture IN (".$db->sanitize(implode(",", array_keys($tabfac))).")
544 GROUP BY fk_facture
545 ";
546 $resql = $db->query($sql);
547 if ($resql) {
548 $num = $db->num_rows($resql);
549 $i = 0;
550 while ($i < $num) {
551 $obj = $db->fetch_object($resql);
552 if ($obj->nb > 0) {
553 $errorforinvoice[$obj->fk_facture] = 'somelinesarenotbound';
554 }
555 $i++;
556 }
557 }
558}
559//var_dump($errorforinvoice);exit;
560
561// Bookkeeping Write
562if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'bind', 'write')) {
563 $now = dol_now();
564 $error = 0;
565
566 $companystatic = new Societe($db);
567 $invoicestatic = new Facture($db);
568 $bookkeepingstatic = new BookKeeping($db);
569
570 $accountingaccountcustomer = new AccountingAccount($db);
571 $accountingaccountcustomer->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
572
573 $accountingaccountcustomerwarranty = new AccountingAccount($db);
574 $accountingaccountcustomerwarranty->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
575
576 foreach ($tabfac as $key => $val) { // Loop on each invoice
577 $errorforline = 0;
578
579 $totalcredit = 0;
580 $totaldebit = 0;
581
582 $db->begin(); // We accept transaction into loop, so if we hang, we can continue transfer from the last error
583
584 $companystatic->id = $tabcompany[$key]['id'];
585 $companystatic->name = $tabcompany[$key]['name'];
586 $companystatic->accountancy_code_customer_general = $tabcompany[$key]['accountancy_code_customer_general'];
587 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
588 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
589 $companystatic->code_client = $tabcompany[$key]['code_client'];
590 $companystatic->client = 3;
591
592 $invoicestatic->id = (int) $key;
593 $invoicestatic->ref = (string) $val["ref"];
594 $invoicestatic->type = (int) ($val["type"] ?? 0);
595 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
596
597 $date = dol_print_date($val["date"], 'day');
598
599 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
600 $replacedinvoice = 0;
601 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
602 $replacedinvoice = 1;
603 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
604 if ($alreadydispatched) {
605 $replacedinvoice = 2;
606 }
607 }
608
609 // If not already into bookkeeping, we won't add it. If yes, do nothing (should not happen because creating a replacement is not possible if invoice is accounted)
610 if ($replacedinvoice == 1) {
611 $db->rollback();
612 continue;
613 }
614
615 // Error if some lines are not binded/ready to be journalized
616 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
617 $error++;
618 $errorforline++;
619 setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', (string) ($val['ref'] ?? '')), null, 'errors');
620 }
621
622 // Warranty
623 if (!$errorforline && getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY')) {
624 if (isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
625 foreach ($tabwarranty[$key] as $k => $mt) {
626 $bookkeeping = new BookKeeping($db);
627 $bookkeeping->doc_date = $val["date"];
628 $bookkeeping->date_lim_reglement = $val["datereg"];
629 $bookkeeping->doc_ref = $val["ref"];
630 $bookkeeping->date_creation = $now;
631 $bookkeeping->doc_type = 'customer_invoice';
632 $bookkeeping->fk_doc = (int) $key;
633 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are the source of this record to add
634 $bookkeeping->thirdparty_code = $companystatic->code_client;
635
636 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
637 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
638
639 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
640 $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
641
642 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RetainedWarranty"));
643 $bookkeeping->montant = $mt;
644 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
645 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
646 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
647 $bookkeeping->code_journal = $journal;
648 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
649 $bookkeeping->fk_user_author = $user->id;
650 $bookkeeping->entity = $conf->entity;
651
652 $totaldebit += $bookkeeping->debit;
653 $totalcredit += $bookkeeping->credit;
654
655 $result = $bookkeeping->create($user);
656 if ($result < 0) {
657 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
658 $error++;
659 $errorforline++;
660 $errorforinvoice[$key] = 'alreadyjournalized';
661 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
662 } else {
663 $error++;
664 $errorforline++;
665 $errorforinvoice[$key] = 'other';
666 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
667 }
668 }
669 }
670 }
671 }
672
673 // Thirdparty
674 if (!$errorforline) {
675 foreach ($tabttc[$key] as $k => $mt) {
676 $bookkeeping = new BookKeeping($db);
677 $bookkeeping->doc_date = $val["date"];
678 $bookkeeping->date_lim_reglement = $val["datereg"];
679 $bookkeeping->doc_ref = $val["ref"];
680 $bookkeeping->date_creation = $now;
681 $bookkeeping->doc_type = 'customer_invoice';
682 $bookkeeping->fk_doc = (int) $key;
683 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
684 $bookkeeping->thirdparty_code = $companystatic->code_client;
685
686 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
687 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
688
689 $bookkeeping->numero_compte = (!empty($tabcompany[$key]['accountancy_code_customer_general']) && $tabcompany[$key]['accountancy_code_customer_general'] != '-1') ? $tabcompany[$key]['accountancy_code_customer_general'] : $cptcli;
690 $bookkeeping->label_compte = $accountingaccountcustomer->label;
691
692 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("SubledgerAccount"));
693 $bookkeeping->montant = $mt;
694 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
695 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
696 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
697 $bookkeeping->code_journal = $journal;
698 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
699 $bookkeeping->fk_user_author = $user->id;
700 $bookkeeping->entity = $conf->entity;
701
702 $totaldebit += $bookkeeping->debit;
703 $totalcredit += $bookkeeping->credit;
704
705 $result = $bookkeeping->create($user);
706 if ($result < 0) {
707 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
708 $error++;
709 $errorforline++;
710 $errorforinvoice[$key] = 'alreadyjournalized';
711 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
712 } else {
713 $error++;
714 $errorforline++;
715 $errorforinvoice[$key] = 'other';
716 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
717 }
718 } else {
719 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
720 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
721 $lettering_static = new Lettering($db);
722
723 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
724 }
725 }
726 }
727 }
728
729 // Product / Service
730 if (!$errorforline) {
731 foreach ($tabht[$key] as $k => $mt) {
732 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
733 $accountingaccount = new AccountingAccount($db);
734 $accountingaccount->fetch(0, $k, true);
735 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
736 } else {
737 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
738 }
739
740 $label_account = $accountingaccount->label;
741
742 // get compte id and label
743 if ($accountingaccount->id > 0) {
744 $bookkeeping = new BookKeeping($db);
745 $bookkeeping->doc_date = $val["date"];
746 $bookkeeping->date_lim_reglement = $val["datereg"];
747 $bookkeeping->doc_ref = $val["ref"];
748 $bookkeeping->date_creation = $now;
749 $bookkeeping->doc_type = 'customer_invoice';
750 $bookkeeping->fk_doc = (int) $key;
751 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
752 $bookkeeping->thirdparty_code = $companystatic->code_client;
753
754 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
755 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
756 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
757 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
758 } else {
759 $bookkeeping->subledger_account = '';
760 $bookkeeping->subledger_label = '';
761 }
762 } else {
763 $bookkeeping->subledger_account = '';
764 $bookkeeping->subledger_label = '';
765 }
766
767 $bookkeeping->numero_compte = $k;
768 $bookkeeping->label_compte = $label_account;
769
770 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $label_account);
771 $bookkeeping->montant = $mt;
772 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
773 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
774 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
775 $bookkeeping->code_journal = $journal;
776 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
777 $bookkeeping->fk_user_author = $user->id;
778 $bookkeeping->entity = $conf->entity;
779
780 $totaldebit += $bookkeeping->debit;
781 $totalcredit += $bookkeeping->credit;
782
783 $result = $bookkeeping->create($user);
784 if ($result < 0) {
785 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
786 $error++;
787 $errorforline++;
788 $errorforinvoice[$key] = 'alreadyjournalized';
789 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
790 } else {
791 $error++;
792 $errorforline++;
793 $errorforinvoice[$key] = 'other';
794 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
795 }
796 }
797 }
798 }
799 }
800
801 // VAT
802 if (!$errorforline) {
803 $listoftax = array(0, 1, 2);
804 foreach ($listoftax as $numtax) {
805 $arrayofvat = $tabtva;
806 if ($numtax == 1) {
807 $arrayofvat = $tablocaltax1;
808 }
809 if ($numtax == 2) {
810 $arrayofvat = $tablocaltax2;
811 }
812
813 foreach ($arrayofvat[$key] as $k => $mt) {
814 if ($mt) {
815 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
816 $accountingaccount = new AccountingAccount($db);
817 $accountingaccount->fetch(0, $k, true);
818 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
819 } else {
820 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
821 }
822
823 $label_account = $accountingaccount->label;
824
825 $bookkeeping = new BookKeeping($db);
826 $bookkeeping->doc_date = $val["date"];
827 $bookkeeping->date_lim_reglement = $val["datereg"];
828 $bookkeeping->doc_ref = $val["ref"];
829 $bookkeeping->date_creation = $now;
830 $bookkeeping->doc_type = 'customer_invoice';
831 $bookkeeping->fk_doc = (int) $key;
832 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
833 $bookkeeping->thirdparty_code = $companystatic->code_client;
834
835 $bookkeeping->subledger_account = '';
836 $bookkeeping->subledger_label = '';
837
838 $bookkeeping->numero_compte = $k;
839 $bookkeeping->label_compte = $label_account;
840
841
842 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
843 $labelvataccount = $langs->trans("Taxes").' '.$tmpvatrate.' %';
844 $labelvataccount .= ($numtax ? ' - Localtax '.$numtax : '');
845 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $labelvataccount);
846
847 $bookkeeping->montant = $mt;
848 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
849 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
850 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
851 $bookkeeping->code_journal = $journal;
852 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
853 $bookkeeping->fk_user_author = $user->id;
854 $bookkeeping->entity = $conf->entity;
855
856 $totaldebit += $bookkeeping->debit;
857 $totalcredit += $bookkeeping->credit;
858
859 $result = $bookkeeping->create($user);
860 if ($result < 0) {
861 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
862 $error++;
863 $errorforline++;
864 $errorforinvoice[$key] = 'alreadyjournalized';
865 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
866 } else {
867 $error++;
868 $errorforline++;
869 $errorforinvoice[$key] = 'other';
870 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
871 }
872 }
873 }
874 }
875 }
876 }
877
878 // Revenue stamp
879 if (!$errorforline) {
880 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
881 foreach ($tabrevenuestamp[$key] as $k => $mt) {
882 if ($mt) {
883 if (empty($conf->cache['accountingaccountincurrententity_rs'][$k])) {
884 $accountingaccount = new AccountingAccount($db);
885 $accountingaccount->fetch(0, $k, true);
886 $conf->cache['accountingaccountincurrententity_rs'][$k] = $accountingaccount;
887 } else {
888 $accountingaccount = $conf->cache['accountingaccountincurrententity_rs'][$k];
889 }
890
891 $label_account = $accountingaccount->label;
892
893 $bookkeeping = new BookKeeping($db);
894 $bookkeeping->doc_date = $val["date"];
895 $bookkeeping->date_lim_reglement = $val["datereg"];
896 $bookkeeping->doc_ref = $val["ref"];
897 $bookkeeping->date_creation = $now;
898 $bookkeeping->doc_type = 'customer_invoice';
899 $bookkeeping->fk_doc = (int) $key;
900 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
901 $bookkeeping->thirdparty_code = $companystatic->code_client;
902
903 $bookkeeping->subledger_account = '';
904 $bookkeeping->subledger_label = '';
905
906 $bookkeeping->numero_compte = $k;
907 $bookkeeping->label_compte = $label_account;
908
909 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RevenueStamp"));
910 $bookkeeping->montant = $mt;
911 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
912 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
913 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
914 $bookkeeping->code_journal = $journal;
915 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
916 $bookkeeping->fk_user_author = $user->id;
917 $bookkeeping->entity = $conf->entity;
918
919 $totaldebit += $bookkeeping->debit;
920 $totalcredit += $bookkeeping->credit;
921
922 $result = $bookkeeping->create($user);
923 if ($result < 0) {
924 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
925 $error++;
926 $errorforline++;
927 $errorforinvoice[$key] = 'alreadyjournalized';
928 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
929 } else {
930 $error++;
931 $errorforline++;
932 $errorforinvoice[$key] = 'other';
933 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
934 }
935 }
936 }
937 }
938 }
939 }
940
941 if ($manageCustomerDepositInInvoice) {
942 // customer discount consumed TTC amount (like Third-party section)
943 if (!$errorforline && isset($tabCustomerDiscountTTC[$key])) {
944 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
945 $bookkeeping = new BookKeeping($db);
946 $bookkeeping->doc_date = $val["date"];
947 $bookkeeping->date_lim_reglement = $val["datereg"];
948 $bookkeeping->doc_ref = $val["ref"];
949 $bookkeeping->date_creation = $now;
950 $bookkeeping->doc_type = 'customer_invoice';
951 $bookkeeping->fk_doc = $key;
952 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
953 $bookkeeping->thirdparty_code = $companystatic->code_client;
954
955 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
956 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
957
958 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
959
960 $bookkeeping->label_compte = $accountingaccountcustomer->label;
961
962 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("SubledgerAccount") . $labelCustomerDiscountExtension);
963 $bookkeeping->montant = $mt;
964 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
965 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
966 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
967 $bookkeeping->code_journal = $journal;
968 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
969 $bookkeeping->fk_user_author = $user->id;
970 $bookkeeping->entity = $conf->entity;
971
972 $totaldebit += $bookkeeping->debit;
973 $totalcredit += $bookkeeping->credit;
974
975 $result = $bookkeeping->create($user);
976 if ($result < 0) {
977 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
978 $error++;
979 $errorforline++;
980 $errorforinvoice[$key] = 'alreadyjournalized';
981 } else {
982 $error++;
983 $errorforline++;
984 $errorforinvoice[$key] = 'other';
985 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
986 }
987 } else {
988 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
989 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
990 $lettering_static = new Lettering($db);
991
992 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
993 }
994 }
995 }
996 }
997
998 // customer discount consumed HT (like Product / Service section)
999 if (!$errorforline && isset($tabCustomerDiscountHT[$key])) {
1000 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
1001 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1002 $accountingaccount = new AccountingAccount($db);
1003 $accountingaccount->fetch(0, $k, true);
1004 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1005 } else {
1006 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1007 }
1008
1009 $label_account = $accountingaccount->label;
1010
1011 // get compte id and label
1012 if ($accountingaccount->id > 0) {
1013 $bookkeeping = new BookKeeping($db);
1014 $bookkeeping->doc_date = $val["date"];
1015 $bookkeeping->date_lim_reglement = $val["datereg"];
1016 $bookkeeping->doc_ref = $val["ref"];
1017 $bookkeeping->date_creation = $now;
1018 $bookkeeping->doc_type = 'customer_invoice';
1019 $bookkeeping->fk_doc = $key;
1020 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
1021 $bookkeeping->thirdparty_code = $companystatic->code_client;
1022
1023 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1024 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1025 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
1026 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
1027 } else {
1028 $bookkeeping->subledger_account = '';
1029 $bookkeeping->subledger_label = '';
1030 }
1031 } else {
1032 $bookkeeping->subledger_account = '';
1033 $bookkeeping->subledger_label = '';
1034 }
1035
1036 $bookkeeping->numero_compte = $k;
1037 $bookkeeping->label_compte = $label_account;
1038
1039 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $label_account) . $labelCustomerDiscountExtension;
1040 $bookkeeping->montant = $mt;
1041 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
1042 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
1043 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
1044 $bookkeeping->code_journal = $journal;
1045 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
1046 $bookkeeping->fk_user_author = $user->id;
1047 $bookkeeping->entity = $conf->entity;
1048
1049 $totaldebit += $bookkeeping->debit;
1050 $totalcredit += $bookkeeping->credit;
1051
1052 $result = $bookkeeping->create($user);
1053 if ($result < 0) {
1054 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
1055 $error++;
1056 $errorforline++;
1057 $errorforinvoice[$key] = 'alreadyjournalized';
1058 } else {
1059 $error++;
1060 $errorforline++;
1061 $errorforinvoice[$key] = 'other';
1062 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
1063 }
1064 }
1065 }
1066 }
1067 }
1068
1069 // customer discount consumed VAT amount (like VAT section)
1070 if (!$errorforline && isset($tabCustomerDiscountVAT[$key])) {
1071 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1072 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
1073 $accountingaccount = new AccountingAccount($db);
1074 $accountingaccount->fetch(0, $k, true);
1075 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
1076 } else {
1077 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
1078 }
1079
1080 $label_account = $accountingaccount->label;
1081
1082 $bookkeeping = new BookKeeping($db);
1083 $bookkeeping->doc_date = $val["date"];
1084 $bookkeeping->date_lim_reglement = $val["datereg"];
1085 $bookkeeping->doc_ref = $val["ref"];
1086 $bookkeeping->date_creation = $now;
1087 $bookkeeping->doc_type = 'customer_invoice';
1088 $bookkeeping->fk_doc = $key;
1089 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
1090 $bookkeeping->thirdparty_code = $companystatic->code_client;
1091
1092 $bookkeeping->subledger_account = '';
1093 $bookkeeping->subledger_label = '';
1094
1095 $bookkeeping->numero_compte = $k;
1096 $bookkeeping->label_compte = $label_account;
1097
1098 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1099 $labelvataccount = $langs->trans("Taxes") . ' ' . $tmpvatrate . ' %';
1100 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $labelvataccount) . $labelCustomerDiscountExtension;
1101
1102 $bookkeeping->montant = $mt;
1103 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
1104 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
1105 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
1106 $bookkeeping->code_journal = $journal;
1107 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
1108 $bookkeeping->fk_user_author = $user->id;
1109 $bookkeeping->entity = $conf->entity;
1110
1111 $totaldebit += $bookkeeping->debit;
1112 $totalcredit += $bookkeeping->credit;
1113
1114 $result = $bookkeeping->create($user);
1115 if ($result < 0) {
1116 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
1117 $error++;
1118 $errorforline++;
1119 $errorforinvoice[$key] = 'alreadyjournalized';
1120 } else {
1121 $error++;
1122 $errorforline++;
1123 $errorforinvoice[$key] = 'other';
1124 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
1125 }
1126 }
1127 }
1128 }
1129 }
1130
1131 // Protection against a bug on lines before
1132 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
1133 $error++;
1134 $errorforline++;
1135 $errorforinvoice[$key] = 'amountsnotbalanced';
1136 setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
1137 }
1138
1139 if (!$errorforline) {
1140 $db->commit();
1141 } else {
1142 $db->rollback();
1143
1144 if ($error >= 10) {
1145 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
1146 break; // Break in the foreach
1147 }
1148 }
1149 }
1150
1151 $tabpay = $tabfac;
1152
1153 if (empty($error) && count($tabpay) > 0) {
1154 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
1155 } elseif (count($tabpay) == $error) {
1156 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
1157 } else {
1158 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
1159 }
1160
1161 $action = '';
1162
1163 // Must reload data, so we make a redirect
1164 if (count($tabpay) != $error) {
1165 $param = 'id_journal='.$id_journal;
1166 $param .= '&date_startday='.$date_startday;
1167 $param .= '&date_startmonth='.$date_startmonth;
1168 $param .= '&date_startyear='.$date_startyear;
1169 $param .= '&date_endday='.$date_endday;
1170 $param .= '&date_endmonth='.$date_endmonth;
1171 $param .= '&date_endyear='.$date_endyear;
1172 $param .= '&in_bookkeeping='.$in_bookkeeping;
1173 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
1174 exit;
1175 }
1176}
1177
1178
1179
1180/*
1181 * View
1182 */
1183
1184$form = new Form($db);
1185
1186// Export
1187if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
1188 // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL
1189 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
1190
1191 $filename = 'journal';
1192 $type_export = 'journal';
1193 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
1194
1195 $companystatic = new Client($db);
1196 $invoicestatic = new Facture($db);
1197 $bookkeepingstatic = new BookKeeping($db);
1198
1199 foreach ($tabfac as $key => $val) {
1200 $companystatic->id = $tabcompany[$key]['id'];
1201 $companystatic->name = $tabcompany[$key]['name'];
1202 $companystatic->accountancy_code_customer_general = (!empty($tabcompany[$key]['accountancy_code_customer_general']) && $tabcompany[$key]['accountancy_code_customer_general'] != '-1') ? $tabcompany[$key]['accountancy_code_customer_general'] : $cptcli;
1203 $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
1204 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1205 $companystatic->code_client = $tabcompany[$key]['code_client'];
1206 $companystatic->client = 3;
1207
1208 $invoicestatic->id = (int) $key;
1209 $invoicestatic->ref = (string) $val["ref"];
1210 $invoicestatic->type = (int) ($val["type"] ?? 0);
1211 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
1212
1213 $date = dol_print_date($val["date"], 'day');
1214
1215 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1216 $replacedinvoice = 0;
1217 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1218 $replacedinvoice = 1;
1219 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1220 if ($alreadydispatched) {
1221 $replacedinvoice = 2;
1222 }
1223 }
1224
1225 // 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)
1226 if ($replacedinvoice == 1) {
1227 continue;
1228 }
1229
1230 // Warranty
1231 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) {
1232 foreach ($tabwarranty[$key] as $k => $mt) {
1233 //if ($mt) {
1234 print '"'.$key.'"'.$sep;
1235 print '"'.$date.'"'.$sep;
1236 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1237 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1238 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1239 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
1240 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1241 print '"'.$langs->trans("ThirdParty").'"'.$sep;
1242 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RetainedWarranty"))).'"'.$sep;
1243 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1244 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1245 print '"'.$journal.'"';
1246 print "\n";
1247 //}
1248 }
1249 }
1250
1251 // Third party
1252 foreach ($tabttc[$key] as $k => $mt) {
1253 //if ($mt) {
1254 print '"'.$key.'"'.$sep;
1255 print '"'.$date.'"'.$sep;
1256 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1257 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1258 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1259 print '"'.length_accountg($companystatic->accountancy_code_customer_general).'"'.$sep;
1260 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1261 print '"'.$langs->trans("ThirdParty").'"'.$sep;
1262 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("ThirdParty"))).'"'.$sep;
1263 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1264 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1265 print '"'.$journal.'"';
1266 print "\n";
1267 //}
1268 }
1269
1270 // Product / Service
1271 foreach ($tabht[$key] as $k => $mt) {
1272 $accountingaccount = new AccountingAccount($db);
1273 $accountingaccount->fetch(0, $k, true);
1274 //if ($mt) {
1275 print '"'.$key.'"'.$sep;
1276 print '"'.$date.'"'.$sep;
1277 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1278 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1279 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1280 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1281 print '""'.$sep;
1282 print '"'.csvClean(dol_trunc($accountingaccount->label, 32)).'"'.$sep;
1283 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $accountingaccount->label)).'"'.$sep;
1284 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1285 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1286 print '"'.$journal.'"';
1287 print "\n";
1288 //}
1289 }
1290
1291 // VAT
1292 $listoftax = array(0, 1, 2);
1293 foreach ($listoftax as $numtax) {
1294 $arrayofvat = $tabtva;
1295 if ($numtax == 1) {
1296 $arrayofvat = $tablocaltax1;
1297 }
1298 if ($numtax == 2) {
1299 $arrayofvat = $tablocaltax2;
1300 }
1301
1302 foreach ($arrayofvat[$key] as $k => $mt) {
1303 if ($mt) {
1304 print '"'.$key.'"'.$sep;
1305 print '"'.$date.'"'.$sep;
1306 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1307 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1308 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1309 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1310 print '""'.$sep;
1311 print '"'.$langs->trans("VAT").' - '.implode(', ', $def_tva[$key][$k]).' %"'.$sep;
1312 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("VAT").implode($def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : ''))).'"'.$sep;
1313 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1314 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1315 print '"'.$journal.'"';
1316 print "\n";
1317 }
1318 }
1319 }
1320
1321 // Revenue stamp
1322 if (isset($tabrevenuestamp[$key])) {
1323 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1324 //if ($mt) {
1325 print '"'.$key.'"'.$sep;
1326 print '"'.$date.'"'.$sep;
1327 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1328 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1329 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1330 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1331 print '""'.$sep;
1332 print '"'.$langs->trans("RevenueStamp").'"'.$sep;
1333 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RevenueStamp"))).'"'.$sep;
1334 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1335 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1336 print '"'.$journal.'"';
1337 print "\n";
1338 //}
1339 }
1340 }
1341
1342 if ($manageCustomerDepositInInvoice) {
1343 // customer discount consumed TTC amount (like Third-party section)
1344 if (isset($tabCustomerDiscountTTC[$key])) {
1345 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
1346 //if ($mt) {
1347 print '"' . $key . '"' . $sep;
1348 print '"' . $date . '"' . $sep;
1349 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1350 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1351 print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep;
1352 print '"' . length_accountg($companystatic->accountancy_code_customer_general) . '"' . $sep;
1353 print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep;
1354 print '"' . $langs->trans("ThirdParty") . '"' . $sep;
1355 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("ThirdParty")) . $labelCustomerDiscountExtension) . '"' . $sep;
1356 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1357 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1358 print '"' . $journal . '"';
1359 print "\n";
1360 //}
1361 }
1362 }
1363
1364 // customer discount consumed HT (like Product / Service section)
1365 if (isset($tabCustomerDiscountHT[$key])) {
1366 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
1367 $accountingaccount = new AccountingAccount($db);
1368 $accountingaccount->fetch(0, $k, true);
1369 //if ($mt) {
1370 print '"' . $key . '"' . $sep;
1371 print '"' . $date . '"' . $sep;
1372 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1373 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1374 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1375 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1376 print '""' . $sep;
1377 print '"' . csvClean(dol_trunc($accountingaccount->label, 32)) . '"' . $sep;
1378 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $accountingaccount->label) . $labelCustomerDiscountExtension) . '"' . $sep;
1379 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1380 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1381 print '"' . $journal . '"';
1382 print "\n";
1383 //}
1384 }
1385 }
1386
1387 // customer discount consumed VAT amount (like VAT section)
1388 if (isset($tabCustomerDiscountVAT[$key])) {
1389 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1390 if ($mt) {
1391 print '"' . $key . '"' . $sep;
1392 print '"' . $date . '"' . $sep;
1393 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1394 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1395 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1396 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1397 print '""' . $sep;
1398 print '"' . $langs->trans("VAT") . ' - ' . implode(', ', $def_tva[$key][$k]) . ' %"' . $sep;
1399 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("VAT") . implode($def_tva[$key][$k]) . ' %') . $labelCustomerDiscountExtension) . '"' . $sep;
1400 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1401 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1402 print '"' . $journal . '"';
1403 print "\n";
1404 }
1405 }
1406 }
1407 }
1408 }
1409}
1410
1411
1412
1413if (empty($action) || $action == 'view') {
1414 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
1415 $help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double#G&eacute;n&eacute;ration_des_&eacute;critures_en_comptabilit&eacute;';
1416 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-sellsjournal');
1417
1418 $nom = $title;
1419 $nomlink = '';
1420 $periodlink = '';
1421 $exportlink = '';
1422 $builddate = dol_now();
1423 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
1424 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
1425 $description .= $langs->trans("DepositsAreNotIncluded");
1426 } else {
1427 $description .= $langs->trans("DepositsAreIncluded");
1428 }
1429
1430 $listofchoices = array('notyet' => $langs->trans("NotYetInGeneralLedger"), 'already' => $langs->trans("AlreadyInGeneralLedger"));
1431 $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);
1432 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
1433
1434 $varlink = 'id_journal='.$id_journal;
1435
1436 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
1437
1438 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
1439 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
1440 // Fiscal period test
1441 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
1442 $resql = $db->query($sql);
1443 if ($resql) {
1444 $obj = $db->fetch_object($resql);
1445 if ($obj->nb == 0) {
1446 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
1447 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
1448 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
1449 print $desc;
1450 print '</div>';
1451 }
1452 } else {
1454 }
1455 }
1456
1457 // Button to write into Ledger
1458 $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
1459 if ($acctCustomerNotConfigured) {
1460 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1461 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
1462 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
1463 print $desc;
1464 print '</div>';
1465 }
1466 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1467 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
1468 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1469 }
1470 if ($acctCustomerNotConfigured) {
1471 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1472 } else {
1473 if ($in_bookkeeping == 'notyet') {
1474 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1475 } else {
1476 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1477 }
1478 }
1479 print '</div>';
1480
1481 // TODO Avoid using js. We can use a direct link with $param
1482 print '
1483 <script type="text/javascript">
1484 function launch_export() {
1485 $("div.fiche form input[name=\"action\"]").val("exportcsv");
1486 $("div.fiche form input[type=\"submit\"]").click();
1487 $("div.fiche form input[name=\"action\"]").val("");
1488 }
1489 function writebookkeeping() {
1490 console.log("click on writebookkeeping");
1491 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1492 $("div.fiche form input[type=\"submit\"]").click();
1493 $("div.fiche form input[name=\"action\"]").val("");
1494 }
1495 </script>';
1496
1497 /*
1498 * Show result array
1499 */
1500 print '<br>';
1501
1502 print '<div class="div-table-responsive">';
1503 print "<table class=\"noborder\" width=\"100%\">";
1504 print "<tr class=\"liste_titre\">";
1505 print "<td>".$langs->trans("Date")."</td>";
1506 print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1507 print "<td>".$langs->trans("AccountAccounting")."</td>";
1508 print "<td>".$langs->trans("SubledgerAccount")."</td>";
1509 print "<td>".$langs->trans("LabelOperation")."</td>";
1510 print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1511 print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1512 print "</tr>\n";
1513
1514 $i = 0;
1515
1516 $companystatic = new Client($db);
1517 $invoicestatic = new Facture($db);
1518 $bookkeepingstatic = new BookKeeping($db);
1519
1520 foreach ($tabfac as $key => $val) {
1521 $companystatic->id = $tabcompany[$key]['id'];
1522 $companystatic->name = $tabcompany[$key]['name'];
1523 $companystatic->accountancy_code_customer_general = (!empty($tabcompany[$key]['accountancy_code_customer_general']) && $tabcompany[$key]['accountancy_code_customer_general'] != '-1') ? $tabcompany[$key]['accountancy_code_customer_general'] : $cptcli;
1524 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
1525 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1526 $companystatic->code_client = $tabcompany[$key]['code_client'];
1527 $companystatic->client = 3;
1528
1529 $invoicestatic->id = (int) $key;
1530 $invoicestatic->ref = (string) $val["ref"];
1531 $invoicestatic->type = (int) ($val["type"] ?? 0);
1532 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
1533
1534 $date = dol_print_date($val["date"], 'day');
1535
1536 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1537 $replacedinvoice = 0;
1538 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1539 $replacedinvoice = 1;
1540 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1541 if ($alreadydispatched) {
1542 $replacedinvoice = 2;
1543 }
1544 }
1545
1546 // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1547 if ($replacedinvoice == 1) {
1548 print '<tr class="oddeven">';
1549 print "<!-- Replaced invoice -->";
1550 print "<td>".$date."</td>";
1551 print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1552 // Account
1553 print "<td>";
1554 print $langs->trans("Replaced");
1555 print '</td>';
1556 // Subledger account
1557 print "<td>";
1558 print '</td>';
1559 print "<td>";
1560 print "</td>";
1561 print '<td class="right"></td>';
1562 print '<td class="right"></td>';
1563 print "</tr>";
1564
1565 $i++;
1566 continue;
1567 }
1568 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
1569 print '<tr class="oddeven">';
1570 print "<!-- Some lines are not bound -->";
1571 print "<td>".$date."</td>";
1572 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1573 // Account
1574 print "<td>";
1575 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $invoicestatic->ref).'</span>';
1576 print '</td>';
1577 // Subledger account
1578 print "<td>";
1579 print '</td>';
1580 print "<td>";
1581 print "</td>";
1582 print '<td class="right"></td>';
1583 print '<td class="right"></td>';
1584 print "</tr>";
1585
1586 $i++;
1587 }
1588
1589 // Warranty
1590 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
1591 foreach ($tabwarranty[$key] as $k => $mt) {
1592 print '<tr class="oddeven">';
1593 print "<!-- Thirdparty warranty -->";
1594 print "<td>" . $date . "</td>";
1595 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1596 // Account
1597 print "<td>";
1598 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
1599 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1600 print '<span class="error">' . $langs->trans("MainAccountForRetainedWarrantyNotDefined") . '</span>';
1601 } else {
1602 print $accountoshow;
1603 }
1604 print '</td>';
1605 // Subledger account
1606 print "<td>";
1607 $accountoshow = length_accounta($k);
1608 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1609 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1610 } else {
1611 print $accountoshow;
1612 }
1613 print '</td>';
1614 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0), $invoicestatic->ref, $langs->trans("RetainedWarranty"), 1) . "</td>";
1615 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1616 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1617 print "</tr>";
1618 }
1619 }
1620
1621 // Third party
1622 foreach ($tabttc[$key] as $k => $mt) {
1623 print '<tr class="oddeven">';
1624 print "<!-- Thirdparty -->";
1625 print "<td>".$date."</td>";
1626 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1627 // Account
1628 print "<td>";
1629 $accountoshow = length_accountg($companystatic->accountancy_code_customer_general);
1630 if (($accountoshow == "") || $accountoshow == "-1" || $accountoshow == 'NotDefined') {
1631 print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
1632 } else {
1633 print $accountoshow;
1634 }
1635 print '</td>';
1636 // Subledger account
1637 print "<td>";
1638 $accountoshow = length_accounta($k);
1639 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1640 print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1641 } else {
1642 print $accountoshow;
1643 }
1644 print '</td>';
1645 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("SubledgerAccount"), 1) . "</td>";
1646 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1647 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1648 print "</tr>";
1649
1650 $i++;
1651 }
1652
1653 // Product / Service
1654 foreach ($tabht[$key] as $k => $mt) {
1655 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1656 $accountingaccount = new AccountingAccount($db);
1657 $accountingaccount->fetch(0, $k, true);
1658 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1659 } else {
1660 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1661 }
1662
1663 print '<tr class="oddeven">';
1664 print "<!-- Product -->";
1665 print "<td>".$date."</td>";
1666 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1667 // Account
1668 print "<td>";
1669 $accountoshow = length_accountg($k);
1670 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1671 print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1672 } else {
1673 print $accountoshow;
1674 }
1675 print "</td>";
1676 // Subledger account
1677 print "<td>";
1678 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1679 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1680 print length_accounta($tabcompany[$key]['code_compta']);
1681 }
1682 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1683 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1684 }
1685 print '</td>';
1686 $companystatic->id = $tabcompany[$key]['id'];
1687 $companystatic->name = $tabcompany[$key]['name'];
1688 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $accountingaccount->label, 1) . "</td>";
1689 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1690 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1691 print "</tr>";
1692
1693 $i++;
1694 }
1695
1696 // VAT
1697 $listoftax = array(0, 1, 2);
1698 foreach ($listoftax as $numtax) {
1699 $arrayofvat = $tabtva;
1700 if ($numtax == 1) {
1701 $arrayofvat = $tablocaltax1;
1702 }
1703 if ($numtax == 2) {
1704 $arrayofvat = $tablocaltax2;
1705 }
1706
1707 // $key is id of invoice
1708 foreach ($arrayofvat[$key] as $k => $mt) {
1709 if ($mt) {
1710 print '<tr class="oddeven">';
1711 print "<!-- VAT -->";
1712 print "<td>".$date."</td>";
1713 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1714 // Account
1715 print "<td>";
1716 $accountoshow = length_accountg($k);
1717 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1718 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType2").')</span>';
1719 } else {
1720 print $accountoshow;
1721 }
1722 print "</td>";
1723 // Subledger account
1724 print "<td>";
1725 print '</td>';
1726 // $def_tva is array[invoiceid][accountancy_code_sell_of_vat_rate_found][vatrate]=vatrate
1727 //var_dump($arrayofvat[$key]); //var_dump($key); //var_dump($k);
1728 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1729 $labelvatrate = $langs->trans("Taxes").' '.$tmpvatrate.' %';
1730 $labelvatrate .= ($numtax ? ' - Localtax '.$numtax : '');
1731 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $labelvatrate, 1) . "</td>";
1732 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1733 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1734 print "</tr>";
1735
1736 $i++;
1737 }
1738 }
1739 }
1740
1741 // Revenue stamp
1742 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
1743 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1744 print '<tr class="oddeven">';
1745 print "<!-- Thirdparty revenuestamp -->";
1746 print "<td>" . $date . "</td>";
1747 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1748 // Account
1749 print "<td>";
1750 $accountoshow = length_accountg($k);
1751 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1752 print '<span class="error">' . $langs->trans("MainAccountForRevenueStampSaleNotDefined") . '</span>';
1753 } else {
1754 print $accountoshow;
1755 }
1756 print '</td>';
1757 // Subledger account
1758 print "<td>";
1759 print '</td>';
1760 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("RevenueStamp"), 1) . "</td>";
1761 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1762 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1763 print "</tr>";
1764 }
1765 }
1766
1767 if ($manageCustomerDepositInInvoice) {
1768 // customer discount consumed TTC amount (like Third-party section)
1769 if (isset($tabCustomerDiscountTTC[$key])) {
1770 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
1771 print '<tr class="oddeven">';
1772 print "<!-- Discount TTC -->";
1773 print "<td>" . $date . "</td>";
1774 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1775 // Account
1776 print "<td>";
1777 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
1778 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1779 print '<span class="error">' . $langs->trans("MainAccountForCustomersNotDefined") . '</span>';
1780 } else {
1781 print $accountoshow;
1782 }
1783 print '</td>';
1784 // Subledger account
1785 print "<td>";
1786 $accountoshow = length_accounta($k);
1787 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1788 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1789 } else {
1790 print $accountoshow;
1791 }
1792 print '</td>';
1793 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("SubledgerAccount") . $labelCustomerDiscountExtension, 1) . "</td>";
1794 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1795 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1796 print "</tr>";
1797
1798 $i++;
1799 }
1800 }
1801
1802 // customer discount consumed HT (like Product / Service section)
1803 if (isset($tabCustomerDiscountHT[$key])) {
1804 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
1805 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1806 $accountingaccount = new AccountingAccount($db);
1807 $accountingaccount->fetch(0, $k, true);
1808 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1809 } else {
1810 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1811 }
1812
1813 print '<tr class="oddeven">';
1814 print "<!-- Discount HT -->";
1815 print "<td>" . $date . "</td>";
1816 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1817 // Account
1818 print "<td>";
1819 $accountoshow = length_accountg($k);
1820 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1821 print '<span class="error">' . $langs->trans("ProductNotDefined") . '</span>';
1822 } else {
1823 print $accountoshow;
1824 }
1825 print "</td>";
1826 // Subledger account
1827 print "<td>";
1828 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1829 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1830 print length_accounta($tabcompany[$key]['code_compta']);
1831 }
1832 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1833 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1834 }
1835 print '</td>';
1836 $companystatic->id = $tabcompany[$key]['id'];
1837 $companystatic->name = $tabcompany[$key]['name'];
1838 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $accountingaccount->label, 1) . $labelCustomerDiscountExtension . "</td>";
1839 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1840 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1841 print "</tr>";
1842
1843 $i++;
1844 }
1845 }
1846
1847 // customer discount consumed VAT amount (like VAT section)
1848 if (isset($tabCustomerDiscountVAT[$key])) {
1849 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1850 print '<tr class="oddeven">';
1851 print "<!-- Discount VAT -->";
1852 print "<td>" . $date . "</td>";
1853 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1854 // Account
1855 print "<td>";
1856 $accountoshow = length_accountg($k);
1857 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1858 print '<span class="error">' . $langs->trans("VATAccountNotDefined") . ' (' . $langs->trans("AccountingJournalType2") . ')</span>';
1859 } else {
1860 print $accountoshow;
1861 }
1862 print "</td>";
1863 // Subledger account
1864 print "<td>";
1865 print '</td>';
1866 $tmpvatrate = (empty($def_tva[$key][$k]) ? '' : implode(', ', $def_tva[$key][$k]));
1867 $labelvatrate = $langs->trans("Taxes") . ' ' . $tmpvatrate . ' %';
1868 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $labelvatrate, 1) . $labelCustomerDiscountExtension . "</td>";
1869 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1870 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1871 print "</tr>";
1872
1873 $i++;
1874 }
1875 }
1876 }
1877 }
1878
1879 if (!$i) {
1880 print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1881 }
1882
1883 print "</table>";
1884 print '</div>';
1885
1886 // End of page
1887 llxFooter();
1888}
1889
1890$db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
journalHead($nom, $variant, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='', $moreoptions=array())
Show header of a page used to transfer/dispatch data in accounting.
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
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 absolute discounts.
Class to manage invoices.
const TYPE_REPLACEMENT
Replacement invoice.
const TYPE_STANDARD
Standard 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...)
global $mysoc
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:605
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:624
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
$date_start
Variables from include:
csvClean($newvalue, $charset='', $separator='')
Clean a cell to respect rules of CSV file cells.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getTaxesFromId($vatrate, $buyer=null, $seller=null, $firstparamisid=1)
Get tax (VAT) main information from Id.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.