dolibarr 25.0.0-alpha
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 $tabCustomerDiscountHT[$obj->rowid][$accountCustomerDeposit] = -$customerDiscount->total_ht;
356 $tabCustomerDiscountVAT[$obj->rowid][$accountCustomerDepositVAT] = -$customerDiscount->total_tva;
357 $tabCustomerDiscountTTC[$obj->rowid][$compta_soc] = -$customerDiscount->total_ttc;
358 }
359 }
360 $db->free($resql2);
361 } else {
363 }
364 }
365
366 // Invoice lines
367 $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df);
368 $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr);
369 $tabfac[$obj->rowid]["ref"] = $obj->ref;
370 $tabfac[$obj->rowid]["type"] = $obj->type;
371 $tabfac[$obj->rowid]["description"] = $obj->label_compte;
372 $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries)
373 $tabfac[$obj->rowid]["revenuestamp"] = $revenuestamp;
374 //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid;
375
376 // Avoid warnings
377 if (!isset($tabttc[$obj->rowid][$compta_soc])) {
378 $tabttc[$obj->rowid][$compta_soc] = 0;
379 }
380 if (!isset($tabht[$obj->rowid][$compta_prod])) {
381 $tabht[$obj->rowid][$compta_prod] = 0;
382 }
383 if (!isset($tabtva[$obj->rowid][$compta_tva])) {
384 $tabtva[$obj->rowid][$compta_tva] = 0;
385 }
386 if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
387 $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
388 }
389 if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
390 $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
391 }
392
393 // Compensation of data for invoice situation by using $situation_ratio. This works (nearly) for invoice that was not correctly recorded
394 // but it may introduces an error for situation invoices that were correctly saved. There is still rounding problem that differs between
395 // real data we should have stored and result obtained with a compensation.
396 // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact).
397 // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes.
398 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
399 $total_ttc = $obj->total_ttc * $situation_ratio;
400 } else {
401 $total_ttc = $obj->total_ttc;
402 }
403
404 // Move a part of the retained warrenty into the account of warranty
405 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0 && (!getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION') || !empty($obj->situation_final))) {
406 $retained_warranty = (float) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); // Calculate the amount of warrenty for this line (using the percent value)
407 $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty;
408 $total_ttc -= $retained_warranty;
409 }
410
411 $tabttc[$obj->rowid][$compta_soc] += $total_ttc;
412 $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio;
413 $tva_npr = ((($obj->info_bits & 1) == 1) ? 1 : 0);
414 if (!$tva_npr) { // We ignore line if VAT is a NPR
415 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) {
416 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
417 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
418 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
419 } else {
420 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio;
421 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio;
422 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio;
423 }
424 }
425
426 $compta_revenuestamp = 'NotDefined';
427 if (!empty($revenuestamp)) {
428 $sqlrevenuestamp = "SELECT accountancy_code_sell FROM ".MAIN_DB_PREFIX."c_revenuestamp";
429 $sqlrevenuestamp .= " WHERE fk_pays = ".((int) $mysoc->country_id);
430 $sqlrevenuestamp .= " AND taux = ".((float) $revenuestamp);
431 $sqlrevenuestamp .= " AND active = 1";
432 $resqlrevenuestamp = $db->query($sqlrevenuestamp);
433
434 if ($resqlrevenuestamp) {
435 $num_rows_revenuestamp = $db->num_rows($resqlrevenuestamp);
436 if ($num_rows_revenuestamp > 1) {
437 dol_print_error($db, 'Failed 2 or more lines for the revenue stamp of your country. Check the dictionary of revenue stamp.');
438 } else {
439 $objrevenuestamp = $db->fetch_object($resqlrevenuestamp);
440 if ($objrevenuestamp) {
441 $compta_revenuestamp = $objrevenuestamp->accountancy_code_sell;
442 }
443 }
444 }
445 }
446
447 if (empty($tabrevenuestamp[$obj->rowid][$compta_revenuestamp]) && !empty($revenuestamp)) {
448 // The revenue stamp was never seen for this invoice id=$obj->rowid
449 $tabttc[$obj->rowid][$compta_soc] += $obj->revenuestamp;
450 $tabrevenuestamp[$obj->rowid][$compta_revenuestamp] = $obj->revenuestamp;
451 }
452
453 $tabcompany[$obj->rowid] = array(
454 'id' => $obj->socid,
455 'name' => $obj->name,
456 'code_client' => $obj->code_client,
457 'accountancy_code_customer_general' => $accountancy_code_customer_general,
458 'code_compta' => $compta_soc
459 );
460
461 // After the line is processed
462 $parameters = array(
463 'obj' => $obj,
464 'tabfac' => &$tabfac,
465 'tabht' => &$tabht,
466 'tabtva' => &$tabtva,
467 'def_tva' => &$def_tva,
468 'tabwarranty' => &$tabwarranty,
469 'tabrevenuestamp' => &$tabrevenuestamp,
470 'tabttc' => &$tabttc,
471 'tablocaltax1' => &$tablocaltax1,
472 'tablocaltax2' => &$tablocaltax2,
473 'tabcompany' => &$tabcompany,
474 'vatdata_cache' => &$vatdata_cache,
475 );
476 $reshook = $hookmanager->executeHooks('processingJournalData', $parameters); // Note that $action and $object may have been modified by hook
477
478 $i++;
479
480 // Check for too many lines.
481 if ($i > getDolGlobalInt('ACCOUNTANCY_MAX_TOO_MANY_LINES_TO_PROCESS', 10000)) {
482 $error++;
483 setEventMessages("ErrorTooManyLinesToProcessPleaseUseAMoreSelectiveFilter", null, 'errors');
484 break;
485 }
486 }
487
488 // After the loop on each line
489 $parameters = array(
490 'tabfac' => &$tabfac,
491 'tabht' => &$tabht,
492 'tabtva' => &$tabtva,
493 'def_tva' => &$def_tva,
494 'tabwarranty' => &$tabwarranty,
495 'tabrevenuestamp' => &$tabrevenuestamp,
496 'tabttc' => &$tabttc,
497 'tablocaltax1' => &$tablocaltax1,
498 'tablocaltax2' => &$tablocaltax2,
499 'tabcompany' => &$tabcompany,
500 'vatdata_cache' => &$vatdata_cache,
501 );
502 $reshook = $hookmanager->executeHooks('processedJournalData', $parameters); // Note that $action and $object may have been modified by hook
503} else {
505}
506
507
508$errorforinvoice = array();
509
510/*
511// Old way, 1 query for each invoice
512// Loop on all invoices to detect lines without binded code (fk_code_ventilation <= 0)
513foreach ($tabfac as $key => $val) { // Loop on each invoice
514 $sql = "SELECT COUNT(fd.rowid) as nb";
515 $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd";
516 $sql .= " WHERE fd.product_type <= 2 AND fd.fk_code_ventilation <= 0";
517 $sql .= " AND fd.total_ttc <> 0 AND fk_facture = ".((int) $key);
518 $resql = $db->query($sql);
519 if ($resql) {
520 $obj = $db->fetch_object($resql);
521 if ($obj->nb > 0) {
522 $errorforinvoice[$key] = 'somelinesarenotbound';
523 }
524 } else {
525 dol_print_error($db);
526 }
527}
528*/
529// New way, single query, load all unbound lines
530if (!empty($tabfac)) {
531 $sql = "
532 SELECT
533 fk_facture,
534 COUNT(fd.rowid) as nb
535 FROM
536 ".MAIN_DB_PREFIX."facturedet as fd
537 WHERE
538 fd.product_type <= 2
539 AND fd.fk_code_ventilation <= 0
540 AND fd.total_ttc <> 0
541 AND fk_facture IN (".$db->sanitize(implode(",", array_keys($tabfac))).")
542 GROUP BY fk_facture
543 ";
544 $resql = $db->query($sql);
545 if ($resql) {
546 $num = $db->num_rows($resql);
547 $i = 0;
548 while ($i < $num) {
549 $obj = $db->fetch_object($resql);
550 if ($obj->nb > 0) {
551 $errorforinvoice[$obj->fk_facture] = 'somelinesarenotbound';
552 }
553 $i++;
554 }
555 }
556}
557//var_dump($errorforinvoice);exit;
558
559// Bookkeeping Write
560if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'bind', 'write')) {
561 $now = dol_now();
562 $error = 0;
563
564 $companystatic = new Societe($db);
565 $invoicestatic = new Facture($db);
566 $bookkeepingstatic = new BookKeeping($db);
567
568 $accountingaccountcustomer = new AccountingAccount($db);
569 $accountingaccountcustomer->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), true);
570
571 $accountingaccountcustomerwarranty = new AccountingAccount($db);
572 $accountingaccountcustomerwarranty->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'), true);
573
574 foreach ($tabfac as $key => $val) { // Loop on each invoice
575 $errorforline = 0;
576
577 $totalcredit = 0;
578 $totaldebit = 0;
579
580 $db->begin(); // We accept transaction into loop, so if we hang, we can continue transfer from the last error
581
582 $companystatic->id = $tabcompany[$key]['id'];
583 $companystatic->name = $tabcompany[$key]['name'];
584 $companystatic->accountancy_code_customer_general = $tabcompany[$key]['accountancy_code_customer_general'];
585 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
586 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
587 $companystatic->code_client = $tabcompany[$key]['code_client'];
588 $companystatic->client = 3;
589
590 $invoicestatic->id = (int) $key;
591 $invoicestatic->ref = (string) $val["ref"];
592 $invoicestatic->type = (int) ($val["type"] ?? 0);
593 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
594
595 $date = dol_print_date($val["date"], 'day');
596
597 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
598 $replacedinvoice = 0;
599 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
600 $replacedinvoice = 1;
601 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
602 if ($alreadydispatched) {
603 $replacedinvoice = 2;
604 }
605 }
606
607 // 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)
608 if ($replacedinvoice == 1) {
609 $db->rollback();
610 continue;
611 }
612
613 // Error if some lines are not binded/ready to be journalized
614 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
615 $error++;
616 $errorforline++;
617 setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', (string) ($val['ref'] ?? '')), null, 'errors');
618 }
619
620 // Warranty
621 if (!$errorforline && getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY')) {
622 if (isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
623 foreach ($tabwarranty[$key] as $k => $mt) {
624 $bookkeeping = new BookKeeping($db);
625 $bookkeeping->doc_date = $val["date"];
626 $bookkeeping->date_lim_reglement = $val["datereg"];
627 $bookkeeping->doc_ref = $val["ref"];
628 $bookkeeping->date_creation = $now;
629 $bookkeeping->doc_type = 'customer_invoice';
630 $bookkeeping->fk_doc = (int) $key;
631 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are the source of this record to add
632 $bookkeeping->thirdparty_code = $companystatic->code_client;
633
634 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
635 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
636
637 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY');
638 $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label;
639
640 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RetainedWarranty"));
641 $bookkeeping->montant = $mt;
642 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
643 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
644 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
645 $bookkeeping->code_journal = $journal;
646 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
647 $bookkeeping->fk_user_author = $user->id;
648 $bookkeeping->entity = $conf->entity;
649
650 $totaldebit += $bookkeeping->debit;
651 $totalcredit += $bookkeeping->credit;
652
653 $result = $bookkeeping->create($user);
654 if ($result < 0) {
655 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
656 $error++;
657 $errorforline++;
658 $errorforinvoice[$key] = 'alreadyjournalized';
659 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
660 } else {
661 $error++;
662 $errorforline++;
663 $errorforinvoice[$key] = 'other';
664 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
665 }
666 }
667 }
668 }
669 }
670
671 // Thirdparty
672 if (!$errorforline) {
673 foreach ($tabttc[$key] as $k => $mt) {
674 $bookkeeping = new BookKeeping($db);
675 $bookkeeping->doc_date = $val["date"];
676 $bookkeeping->date_lim_reglement = $val["datereg"];
677 $bookkeeping->doc_ref = $val["ref"];
678 $bookkeeping->date_creation = $now;
679 $bookkeeping->doc_type = 'customer_invoice';
680 $bookkeeping->fk_doc = (int) $key;
681 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
682 $bookkeeping->thirdparty_code = $companystatic->code_client;
683
684 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
685 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
686
687 $bookkeeping->numero_compte = (!empty($tabcompany[$key]['accountancy_code_customer_general']) && $tabcompany[$key]['accountancy_code_customer_general'] != '-1') ? $tabcompany[$key]['accountancy_code_customer_general'] : $cptcli;
688 $bookkeeping->label_compte = $accountingaccountcustomer->label;
689
690 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("SubledgerAccount"));
691 $bookkeeping->montant = $mt;
692 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
693 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
694 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
695 $bookkeeping->code_journal = $journal;
696 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
697 $bookkeeping->fk_user_author = $user->id;
698 $bookkeeping->entity = $conf->entity;
699
700 $totaldebit += $bookkeeping->debit;
701 $totalcredit += $bookkeeping->credit;
702
703 $result = $bookkeeping->create($user);
704 if ($result < 0) {
705 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
706 $error++;
707 $errorforline++;
708 $errorforinvoice[$key] = 'alreadyjournalized';
709 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
710 } else {
711 $error++;
712 $errorforline++;
713 $errorforinvoice[$key] = 'other';
714 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
715 }
716 } else {
717 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
718 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
719 $lettering_static = new Lettering($db);
720
721 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
722 }
723 }
724 }
725 }
726
727 // Product / Service
728 if (!$errorforline) {
729 foreach ($tabht[$key] as $k => $mt) {
730 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
731 $accountingaccount = new AccountingAccount($db);
732 $accountingaccount->fetch(0, $k, true);
733 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
734 } else {
735 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
736 }
737
738 $label_account = $accountingaccount->label;
739
740 // get compte id and label
741 if ($accountingaccount->id > 0) {
742 $bookkeeping = new BookKeeping($db);
743 $bookkeeping->doc_date = $val["date"];
744 $bookkeeping->date_lim_reglement = $val["datereg"];
745 $bookkeeping->doc_ref = $val["ref"];
746 $bookkeeping->date_creation = $now;
747 $bookkeeping->doc_type = 'customer_invoice';
748 $bookkeeping->fk_doc = (int) $key;
749 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
750 $bookkeeping->thirdparty_code = $companystatic->code_client;
751
752 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
753 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
754 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
755 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
756 } else {
757 $bookkeeping->subledger_account = '';
758 $bookkeeping->subledger_label = '';
759 }
760 } else {
761 $bookkeeping->subledger_account = '';
762 $bookkeeping->subledger_label = '';
763 }
764
765 $bookkeeping->numero_compte = $k;
766 $bookkeeping->label_compte = $label_account;
767
768 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $label_account);
769 $bookkeeping->montant = $mt;
770 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
771 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
772 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
773 $bookkeeping->code_journal = $journal;
774 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
775 $bookkeeping->fk_user_author = $user->id;
776 $bookkeeping->entity = $conf->entity;
777
778 $totaldebit += $bookkeeping->debit;
779 $totalcredit += $bookkeeping->credit;
780
781 $result = $bookkeeping->create($user);
782 if ($result < 0) {
783 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
784 $error++;
785 $errorforline++;
786 $errorforinvoice[$key] = 'alreadyjournalized';
787 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
788 } else {
789 $error++;
790 $errorforline++;
791 $errorforinvoice[$key] = 'other';
792 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
793 }
794 }
795 }
796 }
797 }
798
799 // VAT
800 if (!$errorforline) {
801 $listoftax = array(0, 1, 2);
802 foreach ($listoftax as $numtax) {
803 $arrayofvat = $tabtva;
804 if ($numtax == 1) {
805 $arrayofvat = $tablocaltax1;
806 }
807 if ($numtax == 2) {
808 $arrayofvat = $tablocaltax2;
809 }
810
811 foreach ($arrayofvat[$key] as $k => $mt) {
812 if ($mt) {
813 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
814 $accountingaccount = new AccountingAccount($db);
815 $accountingaccount->fetch(0, $k, true);
816 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
817 } else {
818 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
819 }
820
821 $label_account = $accountingaccount->label;
822
823 $bookkeeping = new BookKeeping($db);
824 $bookkeeping->doc_date = $val["date"];
825 $bookkeeping->date_lim_reglement = $val["datereg"];
826 $bookkeeping->doc_ref = $val["ref"];
827 $bookkeeping->date_creation = $now;
828 $bookkeeping->doc_type = 'customer_invoice';
829 $bookkeeping->fk_doc = (int) $key;
830 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
831 $bookkeeping->thirdparty_code = $companystatic->code_client;
832
833 $bookkeeping->subledger_account = '';
834 $bookkeeping->subledger_label = '';
835
836 $bookkeeping->numero_compte = $k;
837 $bookkeeping->label_compte = $label_account;
838
839
840 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
841 $labelvataccount = $langs->trans("Taxes").' '.$tmpvatrate.' %';
842 $labelvataccount .= ($numtax ? ' - Localtax '.$numtax : '');
843 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $labelvataccount);
844
845 $bookkeeping->montant = $mt;
846 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
847 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
848 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
849 $bookkeeping->code_journal = $journal;
850 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
851 $bookkeeping->fk_user_author = $user->id;
852 $bookkeeping->entity = $conf->entity;
853
854 $totaldebit += $bookkeeping->debit;
855 $totalcredit += $bookkeeping->credit;
856
857 $result = $bookkeeping->create($user);
858 if ($result < 0) {
859 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
860 $error++;
861 $errorforline++;
862 $errorforinvoice[$key] = 'alreadyjournalized';
863 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
864 } else {
865 $error++;
866 $errorforline++;
867 $errorforinvoice[$key] = 'other';
868 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
869 }
870 }
871 }
872 }
873 }
874 }
875
876 // Revenue stamp
877 if (!$errorforline) {
878 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
879 foreach ($tabrevenuestamp[$key] as $k => $mt) {
880 if ($mt) {
881 if (empty($conf->cache['accountingaccountincurrententity_rs'][$k])) {
882 $accountingaccount = new AccountingAccount($db);
883 $accountingaccount->fetch(0, $k, true);
884 $conf->cache['accountingaccountincurrententity_rs'][$k] = $accountingaccount;
885 } else {
886 $accountingaccount = $conf->cache['accountingaccountincurrententity_rs'][$k];
887 }
888
889 $label_account = $accountingaccount->label;
890
891 $bookkeeping = new BookKeeping($db);
892 $bookkeeping->doc_date = $val["date"];
893 $bookkeeping->date_lim_reglement = $val["datereg"];
894 $bookkeeping->doc_ref = $val["ref"];
895 $bookkeeping->date_creation = $now;
896 $bookkeeping->doc_type = 'customer_invoice';
897 $bookkeeping->fk_doc = (int) $key;
898 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
899 $bookkeeping->thirdparty_code = $companystatic->code_client;
900
901 $bookkeeping->subledger_account = '';
902 $bookkeeping->subledger_label = '';
903
904 $bookkeeping->numero_compte = $k;
905 $bookkeeping->label_compte = $label_account;
906
907 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RevenueStamp"));
908 $bookkeeping->montant = $mt;
909 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
910 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
911 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
912 $bookkeeping->code_journal = $journal;
913 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
914 $bookkeeping->fk_user_author = $user->id;
915 $bookkeeping->entity = $conf->entity;
916
917 $totaldebit += $bookkeeping->debit;
918 $totalcredit += $bookkeeping->credit;
919
920 $result = $bookkeeping->create($user);
921 if ($result < 0) {
922 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
923 $error++;
924 $errorforline++;
925 $errorforinvoice[$key] = 'alreadyjournalized';
926 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
927 } else {
928 $error++;
929 $errorforline++;
930 $errorforinvoice[$key] = 'other';
931 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
932 }
933 }
934 }
935 }
936 }
937 }
938
939 if ($manageCustomerDepositInInvoice) {
940 // customer discount consumed TTC amount (like Third-party section)
941 if (!$errorforline && isset($tabCustomerDiscountTTC[$key])) {
942 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
943 $bookkeeping = new BookKeeping($db);
944 $bookkeeping->doc_date = $val["date"];
945 $bookkeeping->date_lim_reglement = $val["datereg"];
946 $bookkeeping->doc_ref = $val["ref"];
947 $bookkeeping->date_creation = $now;
948 $bookkeeping->doc_type = 'customer_invoice';
949 $bookkeeping->fk_doc = $key;
950 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
951 $bookkeeping->thirdparty_code = $companystatic->code_client;
952
953 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
954 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
955
956 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER');
957
958 $bookkeeping->label_compte = $accountingaccountcustomer->label;
959
960 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("SubledgerAccount") . $labelCustomerDiscountExtension);
961 $bookkeeping->montant = $mt;
962 $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C';
963 $bookkeeping->debit = ($mt >= 0) ? $mt : 0;
964 $bookkeeping->credit = ($mt < 0) ? -$mt : 0;
965 $bookkeeping->code_journal = $journal;
966 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
967 $bookkeeping->fk_user_author = $user->id;
968 $bookkeeping->entity = $conf->entity;
969
970 $totaldebit += $bookkeeping->debit;
971 $totalcredit += $bookkeeping->credit;
972
973 $result = $bookkeeping->create($user);
974 if ($result < 0) {
975 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
976 $error++;
977 $errorforline++;
978 $errorforinvoice[$key] = 'alreadyjournalized';
979 } else {
980 $error++;
981 $errorforline++;
982 $errorforinvoice[$key] = 'other';
983 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
984 }
985 } else {
986 if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) {
987 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
988 $lettering_static = new Lettering($db);
989
990 $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id));
991 }
992 }
993 }
994 }
995
996 // customer discount consumed HT (like Product / Service section)
997 if (!$errorforline && isset($tabCustomerDiscountHT[$key])) {
998 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
999 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1000 $accountingaccount = new AccountingAccount($db);
1001 $accountingaccount->fetch(0, $k, true);
1002 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1003 } else {
1004 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1005 }
1006
1007 $label_account = $accountingaccount->label;
1008
1009 // get compte id and label
1010 if ($accountingaccount->id > 0) {
1011 $bookkeeping = new BookKeeping($db);
1012 $bookkeeping->doc_date = $val["date"];
1013 $bookkeeping->date_lim_reglement = $val["datereg"];
1014 $bookkeeping->doc_ref = $val["ref"];
1015 $bookkeeping->date_creation = $now;
1016 $bookkeeping->doc_type = 'customer_invoice';
1017 $bookkeeping->fk_doc = $key;
1018 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
1019 $bookkeeping->thirdparty_code = $companystatic->code_client;
1020
1021 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1022 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1023 $bookkeeping->subledger_account = $tabcompany[$key]['code_compta'];
1024 $bookkeeping->subledger_label = $tabcompany[$key]['name'];
1025 } else {
1026 $bookkeeping->subledger_account = '';
1027 $bookkeeping->subledger_label = '';
1028 }
1029 } else {
1030 $bookkeeping->subledger_account = '';
1031 $bookkeeping->subledger_label = '';
1032 }
1033
1034 $bookkeeping->numero_compte = $k;
1035 $bookkeeping->label_compte = $label_account;
1036
1037 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $label_account) . $labelCustomerDiscountExtension;
1038 $bookkeeping->montant = $mt;
1039 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
1040 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
1041 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
1042 $bookkeeping->code_journal = $journal;
1043 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
1044 $bookkeeping->fk_user_author = $user->id;
1045 $bookkeeping->entity = $conf->entity;
1046
1047 $totaldebit += $bookkeeping->debit;
1048 $totalcredit += $bookkeeping->credit;
1049
1050 $result = $bookkeeping->create($user);
1051 if ($result < 0) {
1052 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
1053 $error++;
1054 $errorforline++;
1055 $errorforinvoice[$key] = 'alreadyjournalized';
1056 } else {
1057 $error++;
1058 $errorforline++;
1059 $errorforinvoice[$key] = 'other';
1060 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
1061 }
1062 }
1063 }
1064 }
1065 }
1066
1067 // customer discount consumed VAT amount (like VAT section)
1068 if (!$errorforline && isset($tabCustomerDiscountVAT[$key])) {
1069 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1070 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
1071 $accountingaccount = new AccountingAccount($db);
1072 $accountingaccount->fetch(0, $k, true);
1073 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
1074 } else {
1075 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
1076 }
1077
1078 $label_account = $accountingaccount->label;
1079
1080 $bookkeeping = new BookKeeping($db);
1081 $bookkeeping->doc_date = $val["date"];
1082 $bookkeeping->date_lim_reglement = $val["datereg"];
1083 $bookkeeping->doc_ref = $val["ref"];
1084 $bookkeeping->date_creation = $now;
1085 $bookkeeping->doc_type = 'customer_invoice';
1086 $bookkeeping->fk_doc = $key;
1087 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
1088 $bookkeeping->thirdparty_code = $companystatic->code_client;
1089
1090 $bookkeeping->subledger_account = '';
1091 $bookkeeping->subledger_label = '';
1092
1093 $bookkeeping->numero_compte = $k;
1094 $bookkeeping->label_compte = $label_account;
1095
1096 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1097 $labelvataccount = $langs->trans("Taxes") . ' ' . $tmpvatrate . ' %';
1098 $bookkeeping->label_operation = $bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $labelvataccount) . $labelCustomerDiscountExtension;
1099
1100 $bookkeeping->montant = $mt;
1101 $bookkeeping->sens = ($mt < 0) ? 'D' : 'C';
1102 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
1103 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
1104 $bookkeeping->code_journal = $journal;
1105 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
1106 $bookkeeping->fk_user_author = $user->id;
1107 $bookkeeping->entity = $conf->entity;
1108
1109 $totaldebit += $bookkeeping->debit;
1110 $totalcredit += $bookkeeping->credit;
1111
1112 $result = $bookkeeping->create($user);
1113 if ($result < 0) {
1114 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
1115 $error++;
1116 $errorforline++;
1117 $errorforinvoice[$key] = 'alreadyjournalized';
1118 } else {
1119 $error++;
1120 $errorforline++;
1121 $errorforinvoice[$key] = 'other';
1122 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
1123 }
1124 }
1125 }
1126 }
1127 }
1128
1129 // Protection against a bug on lines before
1130 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
1131 $error++;
1132 $errorforline++;
1133 $errorforinvoice[$key] = 'amountsnotbalanced';
1134 setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors');
1135 }
1136
1137 if (!$errorforline) {
1138 $db->commit();
1139 } else {
1140 $db->rollback();
1141
1142 if ($error >= 10) {
1143 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
1144 break; // Break in the foreach
1145 }
1146 }
1147 }
1148
1149 $tabpay = $tabfac;
1150
1151 if (empty($error) && count($tabpay) > 0) {
1152 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
1153 } elseif (count($tabpay) == $error) {
1154 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
1155 } else {
1156 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
1157 }
1158
1159 $action = '';
1160
1161 // Must reload data, so we make a redirect
1162 if (count($tabpay) != $error) {
1163 $param = 'id_journal='.$id_journal;
1164 $param .= '&date_startday='.$date_startday;
1165 $param .= '&date_startmonth='.$date_startmonth;
1166 $param .= '&date_startyear='.$date_startyear;
1167 $param .= '&date_endday='.$date_endday;
1168 $param .= '&date_endmonth='.$date_endmonth;
1169 $param .= '&date_endyear='.$date_endyear;
1170 $param .= '&in_bookkeeping='.$in_bookkeeping;
1171 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
1172 exit;
1173 }
1174}
1175
1176
1177
1178/*
1179 * View
1180 */
1181
1182$form = new Form($db);
1183
1184// Export
1185if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
1186 // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL
1187 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
1188
1189 $filename = 'journal';
1190 $type_export = 'journal';
1191 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
1192
1193 $companystatic = new Client($db);
1194 $invoicestatic = new Facture($db);
1195 $bookkeepingstatic = new BookKeeping($db);
1196
1197 foreach ($tabfac as $key => $val) {
1198 $companystatic->id = $tabcompany[$key]['id'];
1199 $companystatic->name = $tabcompany[$key]['name'];
1200 $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;
1201 $companystatic->code_compta = $tabcompany[$key]['code_compta']; // deprecated
1202 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1203 $companystatic->code_client = $tabcompany[$key]['code_client'];
1204 $companystatic->client = 3;
1205
1206 $invoicestatic->id = (int) $key;
1207 $invoicestatic->ref = (string) $val["ref"];
1208 $invoicestatic->type = (int) ($val["type"] ?? 0);
1209 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
1210
1211 $date = dol_print_date($val["date"], 'day');
1212
1213 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1214 $replacedinvoice = 0;
1215 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1216 $replacedinvoice = 1;
1217 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1218 if ($alreadydispatched) {
1219 $replacedinvoice = 2;
1220 }
1221 }
1222
1223 // 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)
1224 if ($replacedinvoice == 1) {
1225 continue;
1226 }
1227
1228 // Warranty
1229 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) {
1230 foreach ($tabwarranty[$key] as $k => $mt) {
1231 //if ($mt) {
1232 print '"'.$key.'"'.$sep;
1233 print '"'.$date.'"'.$sep;
1234 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1235 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1236 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1237 print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep;
1238 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1239 print '"'.$langs->trans("ThirdParty").'"'.$sep;
1240 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RetainedWarranty"))).'"'.$sep;
1241 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1242 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1243 print '"'.$journal.'"';
1244 print "\n";
1245 //}
1246 }
1247 }
1248
1249 // Third party
1250 foreach ($tabttc[$key] as $k => $mt) {
1251 //if ($mt) {
1252 print '"'.$key.'"'.$sep;
1253 print '"'.$date.'"'.$sep;
1254 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1255 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1256 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1257 print '"'.length_accountg($companystatic->accountancy_code_customer_general).'"'.$sep;
1258 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
1259 print '"'.$langs->trans("ThirdParty").'"'.$sep;
1260 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("ThirdParty"))).'"'.$sep;
1261 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1262 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1263 print '"'.$journal.'"';
1264 print "\n";
1265 //}
1266 }
1267
1268 // Product / Service
1269 foreach ($tabht[$key] as $k => $mt) {
1270 $accountingaccount = new AccountingAccount($db);
1271 $accountingaccount->fetch(0, $k, true);
1272 //if ($mt) {
1273 print '"'.$key.'"'.$sep;
1274 print '"'.$date.'"'.$sep;
1275 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1276 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1277 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1278 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1279 print '""'.$sep;
1280 print '"'.csvClean(dol_trunc($accountingaccount->label, 32)).'"'.$sep;
1281 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $accountingaccount->label)).'"'.$sep;
1282 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1283 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1284 print '"'.$journal.'"';
1285 print "\n";
1286 //}
1287 }
1288
1289 // VAT
1290 $listoftax = array(0, 1, 2);
1291 foreach ($listoftax as $numtax) {
1292 $arrayofvat = $tabtva;
1293 if ($numtax == 1) {
1294 $arrayofvat = $tablocaltax1;
1295 }
1296 if ($numtax == 2) {
1297 $arrayofvat = $tablocaltax2;
1298 }
1299
1300 foreach ($arrayofvat[$key] as $k => $mt) {
1301 if ($mt) {
1302 print '"'.$key.'"'.$sep;
1303 print '"'.$date.'"'.$sep;
1304 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1305 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1306 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1307 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1308 print '""'.$sep;
1309 print '"'.$langs->trans("VAT").' - '.implode(', ', $def_tva[$key][$k]).' %"'.$sep;
1310 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("VAT").implode($def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : ''))).'"'.$sep;
1311 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1312 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1313 print '"'.$journal.'"';
1314 print "\n";
1315 }
1316 }
1317 }
1318
1319 // Revenue stamp
1320 if (isset($tabrevenuestamp[$key])) {
1321 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1322 //if ($mt) {
1323 print '"'.$key.'"'.$sep;
1324 print '"'.$date.'"'.$sep;
1325 print '"'.((string) ($val["ref"] ?? '')).'"'.$sep;
1326 print '"'.csvClean(dol_trunc($companystatic->name, 32)).'"'.$sep;
1327 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1328 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
1329 print '""'.$sep;
1330 print '"'.$langs->trans("RevenueStamp").'"'.$sep;
1331 print '"'.csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("RevenueStamp"))).'"'.$sep;
1332 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
1333 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
1334 print '"'.$journal.'"';
1335 print "\n";
1336 //}
1337 }
1338 }
1339
1340 if ($manageCustomerDepositInInvoice) {
1341 // customer discount consumed TTC amount (like Third-party section)
1342 if (isset($tabCustomerDiscountTTC[$key])) {
1343 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
1344 //if ($mt) {
1345 print '"' . $key . '"' . $sep;
1346 print '"' . $date . '"' . $sep;
1347 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1348 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1349 print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep;
1350 print '"' . length_accountg($companystatic->accountancy_code_customer_general) . '"' . $sep;
1351 print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep;
1352 print '"' . $langs->trans("ThirdParty") . '"' . $sep;
1353 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("ThirdParty")) . $labelCustomerDiscountExtension) . '"' . $sep;
1354 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1355 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1356 print '"' . $journal . '"';
1357 print "\n";
1358 //}
1359 }
1360 }
1361
1362 // customer discount consumed HT (like Product / Service section)
1363 if (isset($tabCustomerDiscountHT[$key])) {
1364 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
1365 $accountingaccount = new AccountingAccount($db);
1366 $accountingaccount->fetch(0, $k, true);
1367 //if ($mt) {
1368 print '"' . $key . '"' . $sep;
1369 print '"' . $date . '"' . $sep;
1370 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1371 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1372 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1373 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1374 print '""' . $sep;
1375 print '"' . csvClean(dol_trunc($accountingaccount->label, 32)) . '"' . $sep;
1376 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $accountingaccount->label) . $labelCustomerDiscountExtension) . '"' . $sep;
1377 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1378 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1379 print '"' . $journal . '"';
1380 print "\n";
1381 //}
1382 }
1383 }
1384
1385 // customer discount consumed VAT amount (like VAT section)
1386 if (isset($tabCustomerDiscountVAT[$key])) {
1387 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1388 if ($mt) {
1389 print '"' . $key . '"' . $sep;
1390 print '"' . $date . '"' . $sep;
1391 print '"' . ((string) ($val["ref"] ?? '')) . '"' . $sep;
1392 print '"' . csvClean(dol_trunc($companystatic->name, 32)) . '"' . $sep;
1393 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1394 print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep;
1395 print '""' . $sep;
1396 print '"' . $langs->trans("VAT") . ' - ' . implode(', ', $def_tva[$key][$k]) . ' %"' . $sep;
1397 print '"' . csvClean($bookkeepingstatic->accountingLabelForOperation($companystatic->name, $invoicestatic->ref, $langs->trans("VAT") . implode($def_tva[$key][$k]) . ' %') . $labelCustomerDiscountExtension) . '"' . $sep;
1398 print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep;
1399 print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep;
1400 print '"' . $journal . '"';
1401 print "\n";
1402 }
1403 }
1404 }
1405 }
1406 }
1407}
1408
1409
1410
1411if (empty($action) || $action == 'view') {
1412 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
1413 $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;';
1414 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-sellsjournal');
1415
1416 $nom = $title;
1417 $nomlink = '';
1418 $periodlink = '';
1419 $exportlink = '';
1420 $builddate = dol_now();
1421 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
1422 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
1423 $description .= $langs->trans("DepositsAreNotIncluded");
1424 } else {
1425 $description .= $langs->trans("DepositsAreIncluded");
1426 }
1427
1428 $listofchoices = array('notyet' => $langs->trans("NotYetInGeneralLedger"), 'already' => $langs->trans("AlreadyInGeneralLedger"));
1429 $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);
1430 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
1431
1432 $varlink = 'id_journal='.$id_journal;
1433
1434 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
1435
1436 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
1437 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
1438 // Fiscal period test
1439 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
1440 $resql = $db->query($sql);
1441 if ($resql) {
1442 $obj = $db->fetch_object($resql);
1443 if ($obj->nb == 0) {
1444 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
1445 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
1446 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
1447 print $desc;
1448 print '</div>';
1449 }
1450 } else {
1452 }
1453 }
1454
1455 // Button to write into Ledger
1456 $acctCustomerNotConfigured = in_array(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), ['','-1']);
1457 if ($acctCustomerNotConfigured) {
1458 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1459 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
1460 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
1461 print $desc;
1462 print '</div>';
1463 }
1464 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1465 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
1466 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1467 }
1468 if ($acctCustomerNotConfigured) {
1469 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1470 } else {
1471 if ($in_bookkeeping == 'notyet') {
1472 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1473 } else {
1474 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1475 }
1476 }
1477 print '</div>';
1478
1479 // TODO Avoid using js. We can use a direct link with $param
1480 print '
1481 <script type="text/javascript">
1482 function launch_export() {
1483 $("div.fiche form input[name=\"action\"]").val("exportcsv");
1484 $("div.fiche form input[type=\"submit\"]").click();
1485 $("div.fiche form input[name=\"action\"]").val("");
1486 }
1487 function writebookkeeping() {
1488 console.log("click on writebookkeeping");
1489 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1490 $("div.fiche form input[type=\"submit\"]").click();
1491 $("div.fiche form input[name=\"action\"]").val("");
1492 }
1493 </script>';
1494
1495 /*
1496 * Show result array
1497 */
1498 print '<br>';
1499
1500 print '<div class="div-table-responsive">';
1501 print "<table class=\"noborder\" width=\"100%\">";
1502 print "<tr class=\"liste_titre\">";
1503 print "<td>".$langs->trans("Date")."</td>";
1504 print "<td>".$langs->trans("Piece").' ('.$langs->trans("InvoiceRef").")</td>";
1505 print "<td>".$langs->trans("AccountAccounting")."</td>";
1506 print "<td>".$langs->trans("SubledgerAccount")."</td>";
1507 print "<td>".$langs->trans("LabelOperation")."</td>";
1508 print '<td class="center">'.$langs->trans("AccountingDebit")."</td>";
1509 print '<td class="center">'.$langs->trans("AccountingCredit")."</td>";
1510 print "</tr>\n";
1511
1512 $i = 0;
1513
1514 $companystatic = new Client($db);
1515 $invoicestatic = new Facture($db);
1516 $bookkeepingstatic = new BookKeeping($db);
1517
1518 foreach ($tabfac as $key => $val) {
1519 $companystatic->id = $tabcompany[$key]['id'];
1520 $companystatic->name = $tabcompany[$key]['name'];
1521 $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;
1522 $companystatic->code_compta = $tabcompany[$key]['code_compta'];
1523 $companystatic->code_compta_client = $tabcompany[$key]['code_compta'];
1524 $companystatic->code_client = $tabcompany[$key]['code_client'];
1525 $companystatic->client = 3;
1526
1527 $invoicestatic->id = (int) $key;
1528 $invoicestatic->ref = (string) $val["ref"];
1529 $invoicestatic->type = (int) ($val["type"] ?? 0);
1530 $invoicestatic->close_code = (string) ($val["close_code"] ?? '');
1531
1532 $date = dol_print_date($val["date"], 'day');
1533
1534 // Is it a replaced invoice? 0=not a replaced invoice, 1=replaced invoice not yet dispatched, 2=replaced invoice dispatched
1535 $replacedinvoice = 0;
1536 if ($invoicestatic->close_code == Facture::CLOSECODE_REPLACED) {
1537 $replacedinvoice = 1;
1538 $alreadydispatched = $invoicestatic->getVentilExportCompta(); // Test if replaced invoice already into bookkeeping.
1539 if ($alreadydispatched) {
1540 $replacedinvoice = 2;
1541 }
1542 }
1543
1544 // If not already into bookkeeping, we won't add it, if yes, add the counterpart ???.
1545 if ($replacedinvoice == 1) {
1546 print '<tr class="oddeven">';
1547 print "<!-- Replaced invoice -->";
1548 print "<td>".$date."</td>";
1549 print "<td><strike>".$invoicestatic->getNomUrl(1)."</strike></td>";
1550 // Account
1551 print "<td>";
1552 print $langs->trans("Replaced");
1553 print '</td>';
1554 // Subledger account
1555 print "<td>";
1556 print '</td>';
1557 print "<td>";
1558 print "</td>";
1559 print '<td class="right"></td>';
1560 print '<td class="right"></td>';
1561 print "</tr>";
1562
1563 $i++;
1564 continue;
1565 }
1566 if (isset($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
1567 print '<tr class="oddeven">';
1568 print "<!-- Some lines are not bound -->";
1569 print "<td>".$date."</td>";
1570 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1571 // Account
1572 print "<td>";
1573 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $invoicestatic->ref).'</span>';
1574 print '</td>';
1575 // Subledger account
1576 print "<td>";
1577 print '</td>';
1578 print "<td>";
1579 print "</td>";
1580 print '<td class="right"></td>';
1581 print '<td class="right"></td>';
1582 print "</tr>";
1583
1584 $i++;
1585 }
1586
1587 // Warranty
1588 if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key]) && is_array($tabwarranty[$key])) {
1589 foreach ($tabwarranty[$key] as $k => $mt) {
1590 print '<tr class="oddeven">';
1591 print "<!-- Thirdparty warranty -->";
1592 print "<td>" . $date . "</td>";
1593 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1594 // Account
1595 print "<td>";
1596 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'));
1597 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1598 print '<span class="error">' . $langs->trans("MainAccountForRetainedWarrantyNotDefined") . '</span>';
1599 } else {
1600 print $accountoshow;
1601 }
1602 print '</td>';
1603 // Subledger account
1604 print "<td>";
1605 $accountoshow = length_accounta($k);
1606 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1607 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1608 } else {
1609 print $accountoshow;
1610 }
1611 print '</td>';
1612 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0), $invoicestatic->ref, $langs->trans("RetainedWarranty"), 1) . "</td>";
1613 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1614 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1615 print "</tr>";
1616 }
1617 }
1618
1619 // Third party
1620 foreach ($tabttc[$key] as $k => $mt) {
1621 print '<tr class="oddeven">';
1622 print "<!-- Thirdparty -->";
1623 print "<td>".$date."</td>";
1624 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1625 // Account
1626 print "<td>";
1627 $accountoshow = length_accountg($companystatic->accountancy_code_customer_general);
1628 if (($accountoshow == "") || $accountoshow == "-1" || $accountoshow == 'NotDefined') {
1629 print '<span class="error">'.$langs->trans("MainAccountForCustomersNotDefined").'</span>';
1630 } else {
1631 print $accountoshow;
1632 }
1633 print '</td>';
1634 // Subledger account
1635 print "<td>";
1636 $accountoshow = length_accounta($k);
1637 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1638 print '<span class="error">'.$langs->trans("ThirdpartyAccountNotDefined").'</span>';
1639 } else {
1640 print $accountoshow;
1641 }
1642 print '</td>';
1643 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("SubledgerAccount"), 1) . "</td>";
1644 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1645 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1646 print "</tr>";
1647
1648 $i++;
1649 }
1650
1651 // Product / Service
1652 foreach ($tabht[$key] as $k => $mt) {
1653 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1654 $accountingaccount = new AccountingAccount($db);
1655 $accountingaccount->fetch(0, $k, true);
1656 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1657 } else {
1658 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1659 }
1660
1661 print '<tr class="oddeven">';
1662 print "<!-- Product -->";
1663 print "<td>".$date."</td>";
1664 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1665 // Account
1666 print "<td>";
1667 $accountoshow = length_accountg($k);
1668 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1669 print '<span class="error">'.$langs->trans("ProductNotDefined").'</span>';
1670 } else {
1671 print $accountoshow;
1672 }
1673 print "</td>";
1674 // Subledger account
1675 print "<td>";
1676 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1677 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1678 print length_accounta($tabcompany[$key]['code_compta']);
1679 }
1680 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1681 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1682 }
1683 print '</td>';
1684 $companystatic->id = $tabcompany[$key]['id'];
1685 $companystatic->name = $tabcompany[$key]['name'];
1686 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $accountingaccount->label, 1) . "</td>";
1687 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1688 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1689 print "</tr>";
1690
1691 $i++;
1692 }
1693
1694 // VAT
1695 $listoftax = array(0, 1, 2);
1696 foreach ($listoftax as $numtax) {
1697 $arrayofvat = $tabtva;
1698 if ($numtax == 1) {
1699 $arrayofvat = $tablocaltax1;
1700 }
1701 if ($numtax == 2) {
1702 $arrayofvat = $tablocaltax2;
1703 }
1704
1705 // $key is id of invoice
1706 foreach ($arrayofvat[$key] as $k => $mt) {
1707 if ($mt) {
1708 print '<tr class="oddeven">';
1709 print "<!-- VAT -->";
1710 print "<td>".$date."</td>";
1711 print "<td>".$invoicestatic->getNomUrl(1)."</td>";
1712 // Account
1713 print "<td>";
1714 $accountoshow = length_accountg($k);
1715 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1716 print '<span class="error">'.$langs->trans("VATAccountNotDefined").' ('.$langs->trans("AccountingJournalType2").')</span>';
1717 } else {
1718 print $accountoshow;
1719 }
1720 print "</td>";
1721 // Subledger account
1722 print "<td>";
1723 print '</td>';
1724 // $def_tva is array[invoiceid][accountancy_code_sell_of_vat_rate_found][vatrate]=vatrate
1725 //var_dump($arrayofvat[$key]); //var_dump($key); //var_dump($k);
1726 $tmpvatrate = (empty($def_tva[$key][$k]) ? (empty($arrayofvat[$key][$k]) ? '' : $arrayofvat[$key][$k]) : implode(', ', $def_tva[$key][$k]));
1727 $labelvatrate = $langs->trans("Taxes").' '.$tmpvatrate.' %';
1728 $labelvatrate .= ($numtax ? ' - Localtax '.$numtax : '');
1729 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $labelvatrate, 1) . "</td>";
1730 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
1731 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
1732 print "</tr>";
1733
1734 $i++;
1735 }
1736 }
1737 }
1738
1739 // Revenue stamp
1740 if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
1741 foreach ($tabrevenuestamp[$key] as $k => $mt) {
1742 print '<tr class="oddeven">';
1743 print "<!-- Thirdparty revenuestamp -->";
1744 print "<td>" . $date . "</td>";
1745 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1746 // Account
1747 print "<td>";
1748 $accountoshow = length_accountg($k);
1749 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1750 print '<span class="error">' . $langs->trans("MainAccountForRevenueStampSaleNotDefined") . '</span>';
1751 } else {
1752 print $accountoshow;
1753 }
1754 print '</td>';
1755 // Subledger account
1756 print "<td>";
1757 print '</td>';
1758 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("RevenueStamp"), 1) . "</td>";
1759 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1760 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1761 print "</tr>";
1762 }
1763 }
1764
1765 if ($manageCustomerDepositInInvoice) {
1766 // customer discount consumed TTC amount (like Third-party section)
1767 if (isset($tabCustomerDiscountTTC[$key])) {
1768 foreach ($tabCustomerDiscountTTC[$key] as $k => $mt) {
1769 print '<tr class="oddeven">';
1770 print "<!-- Discount TTC -->";
1771 print "<td>" . $date . "</td>";
1772 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1773 // Account
1774 print "<td>";
1775 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'));
1776 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1777 print '<span class="error">' . $langs->trans("MainAccountForCustomersNotDefined") . '</span>';
1778 } else {
1779 print $accountoshow;
1780 }
1781 print '</td>';
1782 // Subledger account
1783 print "<td>";
1784 $accountoshow = length_accounta($k);
1785 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1786 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1787 } else {
1788 print $accountoshow;
1789 }
1790 print '</td>';
1791 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $langs->trans("SubledgerAccount") . $labelCustomerDiscountExtension, 1) . "</td>";
1792 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1793 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1794 print "</tr>";
1795
1796 $i++;
1797 }
1798 }
1799
1800 // customer discount consumed HT (like Product / Service section)
1801 if (isset($tabCustomerDiscountHT[$key])) {
1802 foreach ($tabCustomerDiscountHT[$key] as $k => $mt) {
1803 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
1804 $accountingaccount = new AccountingAccount($db);
1805 $accountingaccount->fetch(0, $k, true);
1806 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
1807 } else {
1808 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
1809 }
1810
1811 print '<tr class="oddeven">';
1812 print "<!-- Discount HT -->";
1813 print "<td>" . $date . "</td>";
1814 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1815 // Account
1816 print "<td>";
1817 $accountoshow = length_accountg($k);
1818 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1819 print '<span class="error">' . $langs->trans("ProductNotDefined") . '</span>';
1820 } else {
1821 print $accountoshow;
1822 }
1823 print "</td>";
1824 // Subledger account
1825 print "<td>";
1826 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_USE_AUXILIARY_ON_DEPOSIT')) {
1827 if ($k == getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT')) {
1828 print length_accounta($tabcompany[$key]['code_compta']);
1829 }
1830 } elseif (($accountoshow == "") || $accountoshow == 'NotDefined') {
1831 print '<span class="error">' . $langs->trans("ThirdpartyAccountNotDefined") . '</span>';
1832 }
1833 print '</td>';
1834 $companystatic->id = $tabcompany[$key]['id'];
1835 $companystatic->name = $tabcompany[$key]['name'];
1836 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $accountingaccount->label, 1) . $labelCustomerDiscountExtension . "</td>";
1837 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1838 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1839 print "</tr>";
1840
1841 $i++;
1842 }
1843 }
1844
1845 // customer discount consumed VAT amount (like VAT section)
1846 if (isset($tabCustomerDiscountVAT[$key])) {
1847 foreach ($tabCustomerDiscountVAT[$key] as $k => $mt) {
1848 print '<tr class="oddeven">';
1849 print "<!-- Discount VAT -->";
1850 print "<td>" . $date . "</td>";
1851 print "<td>" . $invoicestatic->getNomUrl(1) . "</td>";
1852 // Account
1853 print "<td>";
1854 $accountoshow = length_accountg($k);
1855 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
1856 print '<span class="error">' . $langs->trans("VATAccountNotDefined") . ' (' . $langs->trans("AccountingJournalType2") . ')</span>';
1857 } else {
1858 print $accountoshow;
1859 }
1860 print "</td>";
1861 // Subledger account
1862 print "<td>";
1863 print '</td>';
1864 $tmpvatrate = (empty($def_tva[$key][$k]) ? '' : implode(', ', $def_tva[$key][$k]));
1865 $labelvatrate = $langs->trans("Taxes") . ' ' . $tmpvatrate . ' %';
1866 print "<td>" . $bookkeepingstatic->accountingLabelForOperation($companystatic->getNomUrl(0, 'customer'), $invoicestatic->ref, $labelvatrate, 1) . $labelCustomerDiscountExtension . "</td>";
1867 print '<td class="right nowraponall amount">' . ($mt < 0 ? price(-$mt) : '') . "</td>";
1868 print '<td class="right nowraponall amount">' . ($mt >= 0 ? price($mt) : '') . "</td>";
1869 print "</tr>";
1870
1871 $i++;
1872 }
1873 }
1874 }
1875 }
1876
1877 if (!$i) {
1878 print '<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1879 }
1880
1881 print "</table>";
1882 print '</div>';
1883
1884 // End of page
1885 llxFooter();
1886}
1887
1888$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.