dolibarr 22.0.5
treasuryjournal.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-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
8 * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
9 * Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
10 * Copyright (C) 2017-2025 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
12 * Copyright (C) 2025 Hannes Hieronimi <hannes@innwerk.org>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
33require '../../main.inc.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
37require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
38require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
39require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
40require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
41
51// Load translation files required by the page
52$langs->loadLangs(array("companies", "other", "compta", "banks", "bills", "donations", "loan", "accountancy", "trips", "salaries", "hrm", "members"));
53
54// Multi journal
55$id_journal = GETPOSTINT('id_journal');
56
57$date_startmonth = GETPOSTINT('date_startmonth');
58$date_startday = GETPOSTINT('date_startday');
59$date_startyear = GETPOSTINT('date_startyear');
60$date_endmonth = GETPOSTINT('date_endmonth');
61$date_endday = GETPOSTINT('date_endday');
62$date_endyear = GETPOSTINT('date_endyear');
63$in_bookkeeping = GETPOST('in_bookkeeping', 'aZ09');
64
65$only_rappro = GETPOSTINT('only_rappro');
66if ($only_rappro == 0) {
67 //GET page for the first time, use default settings
68 $only_rappro = getDolGlobalInt('ACCOUNTING_BANK_CONCILIATED');
69}
70
71$now = dol_now();
72
73$action = GETPOST('action', 'aZ09');
74
75if ($in_bookkeeping == '') {
76 $in_bookkeeping = 'notyet';
77}
78
79// Security check
80if (!isModEnabled('accounting')) {
82}
83if ($user->socid > 0) {
85}
86if (!$user->hasRight('accounting', 'bind', 'write')) {
88}
89
90
91/*
92 * Actions
93 */
94
95$error = 0;
96
97$date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
98$date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
99
100$pastmonth = null; // Initialise for static analysis (could be really unseg)
101$pastmonthyear = null;
102
103if (empty($date_startmonth)) {
104 // Period by default on transfer
106 $date_start = $dates['date_start'];
107 $pastmonthyear = $dates['pastmonthyear'];
108 $pastmonth = $dates['pastmonth'];
109}
110if (empty($date_endmonth)) {
111 // Period by default on transfer
113 $date_end = $dates['date_end'];
114 $pastmonthyear = $dates['pastmonthyear'];
115 $pastmonth = $dates['pastmonth'];
116}
117
118if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end))) { // We define date_start and date_end, only if we did not submit the form
119 $date_start = dol_get_first_day((int) $pastmonthyear, (int) $pastmonth, false);
120 $date_end = dol_get_last_day((int) $pastmonthyear, (int) $pastmonth, false);
121}
122
123// Get all bank lines
124//-------------------------------------
125$sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.amount_main_currency, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, b.fk_account,";
126$sql .= " ba.courant, ba.ref as baref, ba.account_number, ba.fk_accountancy_journal,";
127$sql .= " bu.type as bu_type";
128$sql .= " FROM ".$db->prefix()."bank as b";
129$sql .= " JOIN ".$db->prefix()."bank_account as ba on b.fk_account = ba.rowid";
130$sql .= " LEFT JOIN ".$db->prefix()."bank_url as bu ON bu.fk_bank = b.rowid";
131$sql .= " WHERE ba.fk_accountancy_journal = ".((int) $id_journal);
132$sql .= " AND b.amount <> 0 AND ba.entity IN (".getEntity('bank_account').")"; // We don't share object for accountancy, we use source object sharing
133if ($date_start && $date_end) {
134 $sql .= " AND b.dateo >= '".$db->idate($date_start)."' AND b.dateo <= '".$db->idate($date_end)."'";
135}
136// Define begin binding date
137if (getDolGlobalInt('ACCOUNTING_DATE_START_BINDING')) {
138 $sql .= " AND b.dateo >= '".$db->idate(getDolGlobalInt('ACCOUNTING_DATE_START_BINDING'))."'";
139}
140// Already in bookkeeping or not
141if ($in_bookkeeping == 'already') {
142 $sql .= " AND (b.rowid IN (SELECT fk_doc FROM ".$db->prefix()."accounting_bookkeeping as ab WHERE ab.doc_type='bank') )";
143}
144if ($in_bookkeeping == 'notyet') {
145 $sql .= " AND (b.rowid NOT IN (SELECT fk_doc FROM ".$db->prefix()."accounting_bookkeeping as ab WHERE ab.doc_type='bank') )";
146}
147if ($only_rappro == 2) {
148 $sql .= " AND (b.rappro = '1')";
149}
150$sql .= " ORDER BY b.dateo";
151//print $sql;
152
153$result_lines = array();
154
155// Data cached
156$payment_ids = array();
157$tabpay = array();
158$tabaccount = array();
159$tabobject = array();
160$tabaccountingaccount = array();
161$tabvatdata = array();
162
163dol_syslog("accountancy/journal/treasuryjournal.php", LOG_DEBUG);
164$resql = $db->query($sql);
165if ($resql) {
166 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
167 $static_account = new Account($db);
168
169 while ($obj = $db->fetch_object($resql)) {
170 // Get payment infos (rowid is bank ID)
171 if (!isset($tabpay[$obj->rowid])) {
172 $tabpay[$obj->rowid] = array(
173 'id' => $obj->rowid,
174 'date' => $db->jdate($obj->do),
175 'type_payment' => $obj->fk_type,// CHQ, VIR, LIQ, CB, ...
176 'ref' => $obj->label, // by default, not unique. May be changed later
177 'fk_bank_account' => $obj->fk_account,
178 'objects' => array(),
179 );
180 $reg = array();
181 if (preg_match('/^\‍((.*)\‍)$/i', $obj->label, $reg)) {
182 $tabpay[$obj->rowid]["lib"] = $langs->trans($reg[1]);
183 } else {
184 $tabpay[$obj->rowid]["lib"] = dol_trunc($obj->label, 60);
185 }
186 }
187 $payment_ids[$obj->bu_type][$obj->rowid] = $obj->rowid;
188
189 // Get bank account infos (rowid is bank ID)
190 if (!isset($tabaccount[$obj->fk_account])) {
191 $static_account->id = $obj->fk_account;
192 $static_account->ref = $obj->baref;
193 $tabaccount[$obj->fk_account] = [
194 'id' => $obj->fk_account,
195 'account_ref' => $obj->baref,
196 'account_number' => $obj->account_number,
197 'url' => $static_account->getNomUrl(1),
198 ];
199 }
200 }
201 $db->free($resql);
202
203 foreach ($payment_ids as $type => $ids) {
204 switch ($type) {
205 case 'payment':
206 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
207
208 // Customer invoices
209 //------------------------------------------
210 $sql = "SELECT f.rowid, f.ref AS ref, f.total_ht AS invoice_total_ht, f.total_ttc AS invoice_total_ttc,";
211 $sql .= " pf.amount AS amount_payment,";
212 $sql .= " fd.rowid AS row_id, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.vat_src_code,";
213 $sql .= " aa.account_number as accountancy_code, aa.label as accountancy_code_label,";
214 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
215 $sql .= " FROM ".$db->prefix()."facturedet as fd";
216 $sql .= " INNER JOIN ".$db->prefix()."facture as f ON f.rowid = fd.fk_facture";
217 $sql .= " INNER JOIN ".$db->prefix()."paiement_facture as pf ON pf.fk_facture = f.rowid";
218 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pf.fk_paiement AND bu.type = '".$db->escape($type)."'";
219 $sql .= " LEFT JOIN ".$db->prefix()."product as p ON p.rowid = fd.fk_product";
220 $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON aa.rowid = fd.fk_code_ventilation";
221 // Already in bookkeeping or not
222 if ($in_bookkeeping == 'already') {
223 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=f.rowid";
224 } else {
225 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=f.rowid";
226 }
227 $sql .= " WHERE f.entity IN (".getEntity('facture', 0).')'; // We don't share object for accountancy, we use source object sharing
228 // Not already in bookkeeping
229 if ($in_bookkeeping == 'notyet') {
230 $sql .= " AND ab.rowid IS NULL";
231 }
232 $sql .= " AND fd.fk_code_ventilation > 0";
233 $sql .= " AND f.fk_statut > 0";
234 $sql .= " AND fd.product_type IN (0,1)";
235 $sql .= " AND f.type IN (".Facture::TYPE_STANDARD.",".Facture::TYPE_REPLACEMENT.",".Facture::TYPE_CREDIT_NOTE.",".(!getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS') ? Facture::TYPE_DEPOSIT."," : "").Facture::TYPE_SITUATION.")";
236 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
237 $sql .= " GROUP BY fd.rowid, bu.fk_bank, pf.amount, bu.url_id"; // TODO Must never have a GROUP BY on a field if field is not inside an aggregate function.
238 $sql .= " ORDER BY aa.account_number";
239
240 $resql = $db->query($sql);
241 if ($resql) {
242 $langs->load("bills");
243 $static_invoice = new Facture($db);
244 $already_sum = array();
245 $account_vat_sold = getDolGlobalString('ACCOUNTING_VAT_SOLD_ACCOUNT', 'NotDefined'); // NotDefined is a reserved word
246
247 while ($obj = $db->fetch_object($resql)) {
248 $object_key = $obj->bu_type.'_'.$obj->rowid;
249
250 // To check...
251 // If 1 invoice has 2 payments at 2 different date, seems ok, we have 2 record $tabpay because $obj->fk_bank is different (obj->fk_bank is ID of payment in bank record table).
252 // If 2 invoices are paid in the same payment, we have 2 $tabobject but also 2 $tabpay (because $object_key has 2 different values) when we should have 1.
253
254 // Add object in payment
255 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
256 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
257 'amount' => $obj->amount_payment,
258 'bu_url_id' => $obj->bu_url_id,
259 );
260 }
261
262 if (isset($already_sum[$obj->row_id])) {
263 continue;
264 }
265 $already_sum[$obj->row_id] = $obj->row_id;
266
267 // Set object infos
268 if (!isset($tabobject[$object_key])) {
269 $static_invoice->id = $obj->rowid;
270 $static_invoice->ref = $obj->ref;
271 $tabobject[$object_key] = array(
272 'id' => $obj->rowid,
273 'ref' => $obj->ref, // It would be better to have a doc_ref that is 'BankId '.$obj->fk_bank.' - Facture FAzzz' and not just 'FAzzz' to be protected against duplicate, where xxx = $obj->fk_bank
274 'total_ht' => $obj->invoice_total_ht,
275 'total_ttc' => $obj->invoice_total_ttc,
276 'url' => $static_invoice->getNomUrl(1),
277 'operations' => array(),
278 'vats' => array(),
279 );
280 }
281
282 // Set accounting account infos
283 if (!isset($tabaccountingaccount[$obj->accountancy_code])) {
284 $tabaccountingaccount[$obj->accountancy_code] = array(
285 'label' => !empty($obj->accountancy_code_label) ? $obj->accountancy_code_label : $langs->trans('NotDefined'),
286 );
287 }
288
289 // Add amount for the accountancy code
290 if (!isset($tabobject[$object_key]['operations'][$obj->accountancy_code])) {
291 $tabobject[$object_key]['operations'][$obj->accountancy_code] = array(
292 'total_ht' => 0,
293 );
294 }
295 $tabobject[$object_key]['operations'][$obj->accountancy_code]['total_ht'] += $obj->total_ht;
296
297 if ($obj->total_tva + $obj->total_localtax1 + $obj->total_localtax2 != 0) {
298 // Get vat code compta
299 if (!isset($tabvatdata[$obj->tva_tx][$obj->vat_src_code])) {
300 $tabvatdata[$obj->tva_tx][$obj->vat_src_code] = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0);
301 }
302 $compta_tva = (!empty($tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_sell']) ? $tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_sell'] : $account_vat_sold);
303
304 // Add amount VAT for the code compta
305 if (!isset($tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx])) {
306 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx] = array(
307 'tva_tx' => $obj->tva_tx,
308 'total_tva' => 0,
309 'total_localtax1' => 0,
310 'total_localtax2' => 0,
311 );
312 }
313 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_tva'] += $obj->total_tva;
314 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax1'] += $obj->total_localtax1;
315 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax2'] += $obj->total_localtax2;
316 }
317 }
318 } else {
319 dol_print_error($db);
320 }
321 break;
322 case 'payment_supplier':
323 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
324
325 // Supplier invoices
326 //------------------------------------------
327 $sql = "SELECT ff.rowid, ff.ref, ff.total_ht AS supplier_invoice_total_ht, ff.total_ttc AS supplier_invoice_total_ttc,";
328 $sql .= " pff.amount AS amount_payment,";
329 $sql .= " ffd.rowid AS row_id, ffd.total_ht, ffd.tva AS total_tva, ffd.total_localtax1, ffd.total_localtax2, ffd.tva_tx, ffd.total_ttc, ffd.vat_src_code,";
330 $sql .= " aa.account_number as accountancy_code, aa.label as accountancy_code_label,";
331 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
332 $sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd";
333 $sql .= " INNER JOIN ".$db->prefix()."facture_fourn as ff ON ff.rowid = ffd.fk_facture_fourn";
334 $sql .= " INNER JOIN ".$db->prefix()."paiementfourn_facturefourn as pff ON pff.fk_facturefourn = ff.rowid";
335 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pff.fk_paiementfourn AND bu.type = '".$db->escape($type)."'";
336 $sql .= " LEFT JOIN ".$db->prefix()."product as p ON p.rowid = ffd.fk_product";
337 $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON aa.rowid = ffd.fk_code_ventilation";
338 // Already in bookkeeping or not
339 if ($in_bookkeeping == 'already') {
340 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=ff.rowid";
341 } else {
342 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=ff.rowid";
343 }
344 $sql .= " WHERE ff.entity IN (".getEntity('facture_fourn', 0).')'; // We don't share object for accountancy, we use source object sharing
345 // Not already in bookkeeping
346 if ($in_bookkeeping == 'notyet') {
347 $sql .= " AND ab.rowid IS NULL";
348 }
349 $sql .= " AND ffd.fk_code_ventilation > 0";
350 $sql .= " AND ff.fk_statut > 0";
351 $sql .= " AND ffd.product_type IN (0,1)";
352 $sql .= " AND ff.type IN (".FactureFournisseur::TYPE_STANDARD.",".FactureFournisseur::TYPE_REPLACEMENT.",".FactureFournisseur::TYPE_CREDIT_NOTE.",".(!getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS') ? FactureFournisseur::TYPE_DEPOSIT."," : "").FactureFournisseur::TYPE_SITUATION.")";
353 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
354 $sql .= " GROUP BY ffd.rowid, bu.fk_bank";
355 $sql .= " ORDER BY aa.account_number";
356
357 $resql = $db->query($sql);
358 if ($resql) {
359 $langs->load("suppliers");
360 $static_supplier_invoice = new FactureFournisseur($db);
361 $already_sum = array();
362 $account_vat_buy = getDolGlobalString('ACCOUNTING_VAT_BUY_ACCOUNT', 'NotDefined'); // NotDefined is a reserved word
363
364 while ($obj = $db->fetch_object($resql)) {
365 $object_key = $obj->bu_type.'_'.$obj->rowid;
366
367 // Add object in payment
368 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
369 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
370 'amount' => -$obj->amount_payment,
371 'bu_url_id' => $obj->bu_url_id,
372 );
373 }
374
375 if (isset($already_sum[$obj->row_id])) {
376 continue;
377 }
378 $already_sum[$obj->row_id] = $obj->row_id;
379
380 // Set object infos
381 if (!isset($tabobject[$object_key])) {
382 $static_supplier_invoice->id = $obj->rowid;
383 $static_supplier_invoice->ref = $obj->ref;
384 $tabobject[$object_key] = array(
385 'id' => $obj->rowid,
386 'ref' => $obj->ref, // It would be better to have a doc_ref that is 'BankId '.$obj->fk_bank.' - Facture FAzzz' and not just 'FAzzz' to be protected against duplicate, where xxx = $obj->fk_bank
387 'total_ht' => -$obj->supplier_invoice_total_ht,
388 'total_ttc' => -$obj->supplier_invoice_total_ttc,
389 'url' => $static_supplier_invoice->getNomUrl(1),
390 'operations' => array(),
391 'vats' => array(),
392 );
393 }
394
395 // Set accounting account infos
396 if (!isset($tabaccountingaccount[$obj->accountancy_code])) {
397 $tabaccountingaccount[$obj->accountancy_code] = array(
398 'label' => !empty($obj->accountancy_code_label) ? $obj->accountancy_code_label : $langs->trans('NotDefined'),
399 );
400 }
401
402 // Add amount for the accountancy code
403 if (!isset($tabobject[$object_key]['operations'][$obj->accountancy_code])) {
404 $tabobject[$object_key]['operations'][$obj->accountancy_code] = array(
405 'total_ht' => 0,
406 );
407 }
408 $tabobject[$object_key]['operations'][$obj->accountancy_code]['total_ht'] -= $obj->total_ht;
409
410 if ($obj->total_tva + $obj->total_localtax1 + $obj->total_localtax2 != 0) {
411 // Get vat code compta
412 if (!isset($tabvatdata[$obj->tva_tx][$obj->vat_src_code])) {
413 $tabvatdata[$obj->tva_tx][$obj->vat_src_code] = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0);
414 }
415 $compta_tva = (!empty($tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_buy']) ? $tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_buy'] : $account_vat_buy);
416
417 // Add amount VAT for the code compta
418 if (!isset($tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx])) {
419 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx] = array(
420 'tva_tx' => $obj->tva_tx,
421 'total_tva' => 0,
422 'total_localtax1' => 0,
423 'total_localtax2' => 0,
424 );
425 }
426 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_tva'] -= $obj->total_tva;
427 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax1'] -= $obj->total_localtax1;
428 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax2'] -= $obj->total_localtax2;
429 }
430 }
431 } else {
432 dol_print_error($db);
433 }
434 break;
435 case 'payment_expensereport':
436 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
437
438 // Expense reports
439 //------------------------------------------
440 $sql = "SELECT er.rowid, er.ref, er.total_ht AS expense_report_total_ht, er.total_ttc AS expense_report_total_ttc,";
441 $sql .= " per.amount AS amount_payment,";
442 $sql .= " erf.rowid AS row_id, erf.total_ht, erf.total_tva, erf.total_localtax1, erf.total_localtax2, erf.tva_tx, erf.total_ttc, erf.vat_src_code,";
443 $sql .= " ctf.accountancy_code,";
444 $sql .= " aa.label as accountancy_code_label,";
445 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
446 $sql .= " FROM ".$db->prefix()."expensereport_det as erf";
447 $sql .= " INNER JOIN ".$db->prefix()."expensereport as er ON er.rowid = erf.fk_expensereport";
448 $sql .= " INNER JOIN ".$db->prefix()."payment_expensereport as per ON per.fk_expensereport = er.rowid";
449 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = per.rowid AND bu.type = '".$db->escape($type)."'";
450 $sql .= " LEFT JOIN ".$db->prefix()."c_type_fees as ctf ON ctf.id = erf.fk_c_type_fees";
451 $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON aa.account_number = ctf.accountancy_code";
452 // Already in bookkeeping or not
453 if ($in_bookkeeping == 'already') {
454 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=er.rowid";
455 } else {
456 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=er.rowid";
457 }
458 $sql .= " WHERE er.entity IN (".getEntity('expensereport', 0).')'; // We don't share object for accountancy, we use source object sharing
459 // Not already in bookkeeping
460 if ($in_bookkeeping == 'notyet') {
461 $sql .= " AND ab.rowid IS NULL";
462 }
463 $sql .= " AND er.fk_statut >= ".ExpenseReport::STATUS_APPROVED;
464 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
465 $sql .= " GROUP BY erf.rowid, bu.fk_bank, per.amount, aa.label, bu.url_id";
466 $sql .= " ORDER BY aa.account_number";
467
468 $resql = $db->query($sql);
469 if ($resql) {
470 $langs->load("trips");
471 $static_expense_report = new ExpenseReport($db);
472 $already_sum = array();
473 $account_vat_buy = getDolGlobalString('ACCOUNTING_VAT_BUY_ACCOUNT', 'NotDefined'); // NotDefined is a reserved word
474
475 while ($obj = $db->fetch_object($resql)) {
476 $object_key = $obj->bu_type.'_'.$obj->rowid;
477
478 // Add object in payment
479 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
480 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
481 'amount' => -$obj->amount_payment,
482 'bu_url_id' => $obj->bu_url_id,
483 );
484 }
485
486 if (isset($already_sum[$obj->row_id])) {
487 continue;
488 }
489 $already_sum[$obj->row_id] = $obj->row_id;
490
491 // Set object infos
492 if (!isset($tabobject[$object_key])) {
493 $static_expense_report->id = $obj->rowid;
494 $static_expense_report->ref = $obj->ref;
495 $tabobject[$object_key] = array(
496 'id' => $obj->rowid,
497 'ref' => $obj->ref,
498 'total_ht' => -$obj->expense_report_total_ht,
499 'total_ttc' => -$obj->expense_report_total_ttc,
500 'url' => $static_expense_report->getNomUrl(1),
501 'operations' => array(),
502 'vats' => array(),
503 );
504 }
505
506 // Set accounting account infos
507 $accountancy_code = !empty($obj->accountancy_code) ? $obj->accountancy_code : 'NotDefined';
508 if (!isset($tabaccountingaccount[$accountancy_code])) {
509 $tabaccountingaccount[$accountancy_code] = array(
510 'label' => !empty($obj->accountancy_code_label) ? $obj->accountancy_code_label : $langs->trans('NotDefined'),
511 );
512 }
513
514 // Add amount for the accountancy code
515 if (!isset($tabobject[$object_key]['operations'][$accountancy_code])) {
516 $tabobject[$object_key]['operations'][$accountancy_code] = array(
517 'total_ht' => 0,
518 );
519 }
520 $tabobject[$object_key]['operations'][$accountancy_code]['total_ht'] -= $obj->total_ht;
521
522 if ($obj->total_tva + $obj->total_localtax1 + $obj->total_localtax2 != 0) {
523 // Get vat code compta
524 if (!isset($tabvatdata[$obj->tva_tx][$obj->vat_src_code])) {
525 $tabvatdata[$obj->tva_tx][$obj->vat_src_code] = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0);
526 }
527 $compta_tva = (!empty($tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_buy']) ? $tabvatdata[$obj->tva_tx][$obj->vat_src_code]['accountancy_code_buy'] : $account_vat_buy);
528
529 // Add amount VAT for the code compta
530 if (!isset($tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx])) {
531 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx] = array(
532 'tva_tx' => $obj->tva_tx,
533 'total_tva' => 0,
534 'total_localtax1' => 0,
535 'total_localtax2' => 0,
536 );
537 }
538 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_tva'] -= $obj->total_tva;
539 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax1'] -= $obj->total_localtax1;
540 $tabobject[$object_key]['vats'][$compta_tva][$obj->tva_tx]['total_localtax2'] -= $obj->total_localtax2;
541 }
542 }
543 } else {
544 dol_print_error($db);
545 }
546 break;
547 case 'payment_salary':
548 // Payment salaries
549 //------------------------------------------
550 $sql = "SELECT ps.rowid,";
551 $sql .= " ps.amount AS amount_payment, ps.label AS label,";
552 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
553 $sql .= " FROM ".$db->prefix()."payment_salary as ps";
554 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = ps.rowid AND bu.type = '".$db->escape($type)."'";
555 // Already in bookkeeping or not
556 if ($in_bookkeeping == 'already') {
557 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=ps.rowid";
558 } else {
559 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=ps.rowid";
560 }
561 $sql .= " WHERE ps.entity IN (".getEntity('user', 0).')'; // We don't share object for accountancy, we use source object sharing
562 // Not already in bookkeeping
563 if ($in_bookkeeping == 'notyet') {
564 $sql .= " AND ab.rowid IS NULL";
565 }
566 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
567
568 $resql = $db->query($sql);
569 if ($resql) {
570 require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php';
571 $langs->load("salaries");
572 $static_payment_salary = new PaymentSalary($db);
573 $account_employee = getDolGlobalString('SALARIES_ACCOUNTING_ACCOUNT_PAYMENT', 'NotDefined'); // NotDefined is a reserved word
574 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_SALARY_REF_PREFIX', 'PS');
575
576 while ($obj = $db->fetch_object($resql)) {
577 $object_key = $obj->bu_type.'_'.$obj->rowid;
578
579 // Add object in payment
580 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
581 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
582 'amount' => -$obj->amount_payment,
583 'bu_url_id' => $obj->bu_url_id,
584 );
585 }
586
587 // Set object infos
588 if (!isset($tabobject[$object_key])) {
589 $static_payment_salary->id = $obj->rowid;
590 $static_payment_salary->ref = $prefix_ref.$obj->rowid;
591 $tabobject[$object_key] = array(
592 'id' => $obj->rowid,
593 'ref' => $prefix_ref.$obj->rowid,
594 'total_ht' => -$obj->amount_payment,
595 'total_ttc' => -$obj->amount_payment,
596 'url' => $static_payment_salary->getNomUrl(1),
597 'operations' => array(),
598 'vats' => array(),
599 );
600 }
601
602 // Add amount for the accountancy code
603 $tabobject[$object_key]['operations'][$account_employee] = array(
604 'total_ht' => -$obj->amount_payment,
605 'label' => $obj->label,
606 );
607 }
608 } else {
609 dol_print_error($db);
610 }
611 break;
612 case 'payment_sc':
613 // Socials contributions
614 //------------------------------------------
615 $sql = "SELECT cs.rowid, cs.ref, cs.libelle AS label, cs.amount AS sociales_contributions_amount,";
616 $sql .= " pc.amount AS amount_payment,";
617 $sql .= " ccs.accountancy_code,";
618 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
619 $sql .= " FROM ".$db->prefix()."paiementcharge as pc";
620 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pc.rowid AND bu.type = '".$db->escape($type)."'";
621 $sql .= " INNER JOIN ".$db->prefix()."chargesociales AS cs ON cs.rowid = pc.fk_charge";
622 $sql .= " LEFT JOIN ".$db->prefix()."c_chargesociales as ccs ON ccs.id = cs.fk_type";
623 // Already in bookkeeping or not
624 if ($in_bookkeeping == 'already') {
625 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=cs.rowid";
626 } else {
627 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=cs.rowid";
628 }
629 $sql .= " WHERE cs.entity = ".$conf->entity; // We don't share object for accountancy, we use source object sharing
630 // Not already in bookkeeping
631 if ($in_bookkeeping == 'notyet') {
632 $sql .= " AND ab.rowid IS NULL";
633 }
634 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
635
636 $resql = $db->query($sql);
637 if ($resql) {
638 require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
639
640 $langs->load("bills");
641 $static_sociales_contributions = new ChargeSociales($db);
642 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_SOCIALES_CONTRIBUTIONS_REF_PREFIX', 'SC');
643
644 while ($obj = $db->fetch_object($resql)) {
645 $object_key = $obj->bu_type.'_'.$obj->rowid;
646
647 // Add object in payment
648 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
649 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
650 'amount' => -$obj->amount_payment,
651 'bu_url_id' => $obj->bu_url_id,
652 );
653 }
654
655 // Set object infos
656 if (!isset($tabobject[$object_key])) {
657 $static_sociales_contributions->id = $obj->rowid;
658 $static_sociales_contributions->ref = $prefix_ref.$obj->rowid;
659 $tabobject[$object_key] = array(
660 'id' => $obj->rowid,
661 'ref' => $prefix_ref.$obj->rowid,
662 'total_ht' => -$obj->sociales_contributions_amount,
663 'total_ttc' => -$obj->sociales_contributions_amount,
664 'url' => $static_sociales_contributions->getNomUrl(1),
665 'operations' => array(),
666 'vats' => array(),
667 );
668 }
669
670 $accountancy_code = !empty($obj->accountancy_code) ? $obj->accountancy_code : 'NotDefined';
671
672 // Add amount for the accountancy code
673 $tabobject[$object_key]['operations'][$accountancy_code] = array(
674 'total_ht' => -$obj->sociales_contributions_amount,
675 'label' => $obj->label,
676 );
677 }
678 } else {
679 dol_print_error($db);
680 }
681 break;
682 case 'payment_vat':
683 // Payment VAT
684 //------------------------------------------
685 $sql = "SELECT t.rowid,";
686 $sql .= " t.amount AS amount_payment, t.label AS label,";
687 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
688 $sql .= " FROM ".$db->prefix()."tva as t";
689 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = t.rowid AND bu.type = '".$db->escape($type)."'";
690 // Already in bookkeeping or not
691 if ($in_bookkeeping == 'already') {
692 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=t.rowid";
693 } else {
694 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=t.rowid";
695 }
696 $sql .= " WHERE bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
697 // $sql .= " AND t.entity = " . $conf->entity; // TODO when entity is managed in tva
698 // Not already in bookkeeping
699 if ($in_bookkeeping == 'notyet') {
700 $sql .= " AND ab.rowid IS NULL";
701 }
702
703 $resql = $db->query($sql);
704 if ($resql) {
705 require_once DOL_DOCUMENT_ROOT.'/compta/tva/class/tva.class.php';
706
707 $langs->load("salaries");
708 $static_tva = new Tva($db);
709 $account_pay_vat = getDolGlobalString('ACCOUNTING_VAT_PAY_ACCOUNT', 'NotDefined'); // NotDefined is a reserved word
710 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_VAT_REF_PREFIX', 'VAT');
711
712 while ($obj = $db->fetch_object($resql)) {
713 $object_key = $obj->bu_type.'_'.$obj->rowid;
714
715 // Add object in payment
716 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
717 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
718 'amount' => -$obj->amount_payment,
719 'bu_url_id' => $obj->bu_url_id,
720 );
721 }
722
723 // Set object infos
724 if (!isset($tabobject[$object_key])) {
725 $static_tva->id = $obj->rowid;
726 $static_tva->ref = $prefix_ref.$obj->rowid;
727 $tabobject[$object_key] = array(
728 'id' => $obj->rowid,
729 'ref' => $prefix_ref.$obj->rowid,
730 'total_ht' => -$obj->amount_payment,
731 'total_ttc' => -$obj->amount_payment,
732 'url' => $static_tva->getNomUrl(1),
733 'operations' => array(),
734 'vats' => array(),
735 );
736 }
737
738 // Add amount for the accountancy code
739 $tabobject[$object_key]['operations'][$account_pay_vat] = array(
740 'total_ht' => -$obj->amount_payment,
741 'label' => $obj->label,
742 );
743 }
744 } else {
745 dol_print_error($db);
746 }
747 break;
748 case 'payment_donation':
749 // Payment donation
750 //------------------------------------------
751 $sql = "SELECT d.rowid, d.amount AS don_amount,";
752 $sql .= " pd.amount AS amount_payment,";
753 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
754 $sql .= " FROM ".$db->prefix()."payment_donation as pd";
755 $sql .= " INNER JOIN ".$db->prefix()."don as d ON pd.fk_donation = d.rowid";
756 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pd.rowid AND bu.type = '".$db->escape($type)."'";
757 // Already in bookkeeping or not
758 if ($in_bookkeeping == 'already') {
759 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=d.rowid";
760 } else {
761 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=d.rowid";
762 }
763 $sql .= " WHERE d.entity IN (".getEntity('donation', 0).')'; // We don't share object for accountancy, we use source object sharing
764 // Not already in bookkeeping
765 if ($in_bookkeeping == 'notyet') {
766 $sql .= " AND ab.rowid IS NULL";
767 }
768 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
769
770 $resql = $db->query($sql);
771 if ($resql) {
772 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
773
774 $langs->load("donations");
775 $static_don = new Don($db);
776 $account_pay_donation = getDolGlobalString('DONATION_ACCOUNTINGACCOUNT', 'NotDefined'); // NotDefined is a reserved word
777 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_DONATION_REF_PREFIX', 'D');
778
779 while ($obj = $db->fetch_object($resql)) {
780 $object_key = $obj->bu_type.'_'.$obj->rowid;
781
782 // Add object in payment
783 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
784 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
785 'amount' => $obj->amount_payment,
786 'bu_url_id' => $obj->bu_url_id,
787 );
788 }
789
790 // Set object infos
791 if (!isset($tabobject[$object_key])) {
792 $static_don->id = $obj->rowid;
793 $static_don->ref = $prefix_ref.$obj->rowid;
794 $tabobject[$object_key] = array(
795 'id' => $obj->rowid,
796 'ref' => $prefix_ref.$obj->rowid,
797 'total_ht' => $obj->don_amount,
798 'total_ttc' => $obj->don_amount,
799 'url' => $static_don->getNomUrl(1),
800 'operations' => array(),
801 'vats' => array(),
802 );
803 }
804
805 // Add amount for the accountancy code
806 $tabobject[$object_key]['operations'][$account_pay_donation] = array(
807 'total_ht' => $obj->don_amount,
808 'label' => $langs->trans('Donation').' '.$prefix_ref.$obj->rowid,
809 );
810 }
811 } else {
812 dol_print_error($db);
813 }
814 break;
815 case 'payment_loan':
816 // Payment loan
817 //------------------------------------------
818 $sql = "SELECT l.rowid, l.capital AS loan_capital, l.accountancy_account_capital, l.accountancy_account_interest, l.accountancy_account_insurance, l.label,";
819 $sql .= " pl.amount_capital, pl.amount_interest, pl.amount_insurance,";
820 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
821 $sql .= " FROM ".$db->prefix()."payment_loan as pl";
822 $sql .= " INNER JOIN ".$db->prefix()."loan as l ON pl.fk_loan = l.rowid";
823 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pl.rowid AND bu.type = '".$db->escape($type)."'";
824 // Already in bookkeeping or not
825 if ($in_bookkeeping == 'already') {
826 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=l.rowid";
827 } else {
828 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=l.rowid";
829 }
830 $sql .= " WHERE l.entity = ".$conf->entity; // We don't share object for accountancy, we use source object sharing
831 // Not already in bookkeeping
832 if ($in_bookkeeping == 'notyet') {
833 $sql .= " AND ab.rowid IS NULL";
834 }
835 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
836
837 $resql = $db->query($sql);
838 if ($resql) {
839 require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
840
841 $langs->load("loan");
842 $static_loan = new Loan($db);
843 $account_pay_loan_capital = getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_CAPITAL', 'NotDefined'); // NotDefined is a reserved word
844 $account_pay_loan_interest = getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_INTEREST', 'NotDefined'); // NotDefined is a reserved word
845 $account_pay_loan_insurance = getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_INSURANCE', 'NotDefined'); // NotDefined is a reserved word
846 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_LOAN_REF_PREFIX', 'L');
847
848 while ($obj = $db->fetch_object($resql)) {
849 $object_key = $obj->bu_type.'_'.$obj->rowid;
850
851 // Add object in payment
852 $payment_amount = $obj->amount_capital + $obj->amount_interest + $obj->amount_insurance;
853 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
854 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
855 'amount' => -$payment_amount,
856 'bu_url_id' => $obj->bu_url_id,
857 );
858 }
859
860 // Set object infos
861 if (!isset($tabobject[$object_key])) {
862 $static_loan->id = $obj->rowid;
863 $static_loan->ref = $prefix_ref.$obj->rowid;
864 $tabobject[$object_key] = array(
865 'id' => $obj->rowid,
866 'ref' => $prefix_ref.$obj->rowid,
867 'total_ht' => -$obj->loan_capital,
868 'total_ttc' => -$obj->loan_capital,
869 'url' => $static_loan->getNomUrl(1),
870 'operations' => array(),
871 'vats' => array(),
872 );
873 }
874
875 // Add amount for the accountancy code
876 $accountancy_account_capital = !empty($obj->accountancy_account_capital) ? $obj->accountancy_account_capital : $account_pay_loan_capital;
877 $tabobject[$object_key]['operations'][$accountancy_account_capital] = array(
878 // virtual total = loan_capital * amount_capital / payment_amount
879 'total_ht' => -($obj->loan_capital * $obj->amount_capital / $payment_amount),
880 'label' => $obj->label.' '.$langs->trans('LoanCapital'),
881 );
882
883 // Add amount for the accountancy code
884 $accountancy_account_interest = !empty($obj->accountancy_account_interest) ? $obj->accountancy_account_interest : $account_pay_loan_interest;
885 $tabobject[$object_key]['operations'][$accountancy_account_interest] = array(
886 // virtual total = loan_capital * amount_interest / payment_amount
887 'total_ht' => -($obj->loan_capital * $obj->amount_interest / $payment_amount),
888 'label' => $obj->label.' '.$langs->trans('Interest'),
889 );
890
891 // 526,23 = 569,74 * x / 15 000,00
892
893 // Add amount for the accountancy code
894 $accountancy_account_insurance = !empty($obj->accountancy_account_insurance) ? $obj->accountancy_account_insurance : $account_pay_loan_insurance;
895 $tabobject[$object_key]['operations'][$accountancy_account_insurance] = array(
896 // virtual total = loan_capital * amount_insurance / payment_amount
897 'total_ht' => -($obj->loan_capital * $obj->amount_insurance / $payment_amount),
898 'label' => $obj->label.' '.$langs->trans('Insurance'),
899 );
900 }
901 } else {
902 dol_print_error($db);
903 }
904 break;
905 case 'payment_various':
906 // Payment various
907 //------------------------------------------
908 $sql = "SELECT pv.rowid,";
909 $sql .= " pv.sens AS sens_payment, pv.amount AS amount_payment, pv.label, pv.accountancy_code,";
910 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
911 $sql .= " FROM ".$db->prefix()."payment_various as pv";
912 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.url_id = pv.rowid AND bu.type = '".$db->escape($type)."'";
913 // Already in bookkeeping or not
914 if ($in_bookkeeping == 'already') {
915 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=pv.rowid";
916 } else {
917 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=pv.rowid";
918 }
919 $sql .= " WHERE pv.entity IN (".getEntity('payment_various', 0).')'; // We don't share object for accountancy, we use source object sharing
920 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
921 // Not already in bookkeeping
922 if ($in_bookkeeping == 'notyet') {
923 $sql .= " AND ab.rowid IS NULL";
924 }
925
926 $resql = $db->query($sql);
927 if ($resql) {
928 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
929
930 $static_payment_various = new PaymentVarious($db);
931 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_VARIOUS_REF_PREFIX', 'PM');
932
933 while ($obj = $db->fetch_object($resql)) {
934 $object_key = $obj->bu_type.'_'.$obj->rowid;
935
936 $payment_amount = (empty($obj->sens_payment) ? -1 : 1) * $obj->amount_payment;
937 // Add object in payment
938 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
939 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
940 'amount' => $payment_amount,
941 'bu_url_id' => $obj->bu_url_id,
942 );
943 }
944
945 // Set object infos
946 if (!isset($tabobject[$object_key])) {
947 $static_payment_various->id = $obj->rowid;
948 $static_payment_various->ref = $prefix_ref.$obj->rowid;
949 $tabobject[$object_key] = array(
950 'id' => $obj->rowid,
951 'ref' => $prefix_ref.$obj->rowid,
952 'total_ht' => $payment_amount,
953 'total_ttc' => $payment_amount,
954 'url' => $static_payment_various->getNomUrl(1),
955 'operations' => array(),
956 'vats' => array(),
957 );
958 }
959
960 // Add amount for the accountancy code
961 $accountancy_code = !empty($obj->accountancy_code) ? $obj->accountancy_code : 'NotDefined';
962 $tabobject[$object_key]['operations'][$obj->accountancy_code] = array(
963 'total_ht' => $payment_amount,
964 'label' => $obj->label,
965 );
966 }
967 } else {
968 dol_print_error($db);
969 }
970 break;
971 case 'member':
972 // Subscription member
973 //------------------------------------------
974 $sql = "SELECT su.rowid,";
975 $sql .= " su.subscription AS amount_payment, su.note AS label,";
976 $sql .= " adh.lastname, adh.firstname,";
977 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
978 $sql .= " FROM ".$db->prefix()."subscription as su";
979 $sql .= " INNER JOIN ".$db->prefix()."adherent as adh ON adh.rowid = su.fk_adherent";
980 $sql .= " INNER JOIN ".$db->prefix()."bank_url as bu ON bu.fk_bank = su.fk_bank AND bu.type = '".$db->escape($type)."'";
981 // Already in bookkeeping or not
982 if ($in_bookkeeping == 'already') {
983 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=su.rowid";
984 } else {
985 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=su.rowid";
986 }
987 $sql .= " WHERE bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
988 // Not already in bookkeeping
989 if ($in_bookkeeping == 'notyet') {
990 $sql .= " AND ab.rowid IS NULL";
991 }
992
993 $resql = $db->query($sql);
994 if ($resql) {
995 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
996
997 $langs->load("members");
998 $static_subscription = new Subscription($db);
999 $account_subscription = getDolGlobalString('ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT', 'NotDefined'); // NotDefined is a reserved word
1000 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_SUBSCRIPTION_REF_PREFIX', 'SU');
1001
1002 while ($obj = $db->fetch_object($resql)) {
1003 $object_key = $obj->bu_type.'_'.$obj->rowid;
1004
1005 // Add object in payment
1006 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
1007 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
1008 'amount' => $obj->amount_payment,
1009 'bu_url_id' => $obj->bu_url_id,
1010 );
1011 }
1012
1013 // Set object infos
1014 if (!isset($tabobject[$object_key])) {
1015 $static_subscription->id = $obj->rowid;
1016 $static_subscription->ref = $prefix_ref.$obj->rowid;
1017 $tabobject[$object_key] = array(
1018 'id' => $obj->rowid,
1019 'ref' => $prefix_ref.$obj->rowid,
1020 'total_ht' => -$obj->amount_payment,
1021 'total_ttc' => -$obj->amount_payment,
1022 'url' => $static_subscription->getNomUrl(1),
1023 'operations' => array(),
1024 'vats' => array(),
1025 );
1026 }
1027
1028 // Add amount for the accountancy code
1029 $tabobject[$object_key]['operations'][$account_subscription] = array(
1030 'total_ht' => -$obj->amount_payment,
1031 'label' => $obj->label.' - '.$obj->lastname.' '.$obj->firstname,
1032 );
1033 }
1034 } else {
1035 dol_print_error($db);
1036 }
1037 break;
1038 case 'banktransfert':
1039 // Bank transfer
1040 //------------------------------------------
1041 $sql = "SELECT b.rowid, b.amount, b.label,";
1042 $sql .= " bu.fk_bank, bu.url_id AS bu_url_id, bu.type AS bu_type";
1043 $sql .= " FROM ".$db->prefix()."bank_url as bu";
1044 $sql .= " INNER JOIN ".$db->prefix()."bank as b ON bu.url_id = b.rowid";
1045 $sql .= " LEFT JOIN ".$db->prefix()."bank_account as ba ON ba.rowid = b.fk_account";
1046 // Already in bookkeeping or not
1047 if ($in_bookkeeping == 'already') {
1048 $sql .= " INNER JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=b.rowid";
1049 } else {
1050 $sql .= " LEFT JOIN ".$db->prefix()."accounting_bookkeeping as ab ON ab.fk_doc=bu.fk_bank AND ab.fk_docdet=b.rowid";
1051 }
1052 $sql .= " WHERE ba.entity IN (".getEntity('bank_account', 0).')'; // We don't share object for accountancy, we use source object sharing
1053 $sql .= " AND bu.fk_bank IN (".$db->sanitize(implode(',', $ids)).")";
1054 $sql .= " AND bu.type = '".$db->escape($type)."'";
1055 // Not already in bookkeeping
1056 if ($in_bookkeeping == 'notyet') {
1057 $sql .= " AND ab.rowid IS NULL";
1058 }
1059
1060 $resql = $db->query($sql);
1061 if ($resql) {
1062 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1063
1064 $static_account_line = new AccountLine($db);
1065 $account_transfer = getDolGlobalString('ACCOUNTING_ACCOUNT_TRANSFER_CASH', 'NotDefined'); // NotDefined is a reserved word
1066 $prefix_ref = getDolGlobalString('MAIN_PAYMENT_TRANSFER_CASH_REF_PREFIX', 'T');
1067
1068 while ($obj = $db->fetch_object($resql)) {
1069 $object_key = $obj->bu_type.'_'.$obj->rowid;
1070
1071 // Add object in payment
1072 if (!isset($tabpay[$obj->fk_bank]['objects'][$object_key])) {
1073 $tabpay[$obj->fk_bank]['objects'][$object_key] = array(
1074 'amount' => -$obj->amount,
1075 'bu_url_id' => $obj->bu_url_id,
1076 );
1077 }
1078
1079 // Set object infos
1080 if (!isset($tabobject[$object_key])) {
1081 $static_account_line->id = $obj->rowid;
1082 $static_account_line->rowid = $obj->rowid;
1083 $static_account_line->ref = $prefix_ref.$obj->rowid;
1084 $tabobject[$object_key] = array(
1085 'id' => $obj->rowid,
1086 'ref' => $prefix_ref.$obj->rowid,
1087 'total_ht' => -$obj->amount,
1088 'total_ttc' => -$obj->amount,
1089 'url' => $static_account_line->getNomUrl(1),
1090 'operations' => array(),
1091 'vats' => array(),
1092 );
1093 }
1094
1095 // Add amount for the accountancy code
1096 $tabobject[$object_key]['operations'][$account_transfer] = array(
1097 'total_ht' => -$obj->amount,
1098 'label' => $obj->label,
1099 );
1100 }
1101 } else {
1102 dol_print_error($db);
1103 }
1104 break;
1105 }
1106 }
1107} else {
1108 dol_print_error($db);
1109}
1110
1117function payment_filter($v)
1118{
1119 return isset($v['objects']) && count($v['objects']) > 0;
1120}
1121
1122$tabpay = array_filter($tabpay, 'payment_filter');
1123
1124$accountingaccount = new AccountingAccount($db);
1125
1126// Get code of finance journal
1127$accountingjournalstatic = new AccountingJournal($db);
1128$accountingjournalstatic->fetch($id_journal);
1129$journal = $accountingjournalstatic->code;
1130$journal_label = $langs->transnoentitiesnoconv($accountingjournalstatic->label);
1131$MAXNBERRORS = 5;
1132
1133// Write bookkeeping
1134if ($action == 'writebookkeeping' /* && $user->hasRight('accounting', 'bind', 'write') */) { // Test on permission already done
1135 foreach ($tabpay as $payment_id => $payment) {
1136 $accountInfos = $tabaccount[$payment["fk_bank_account"]];
1137
1138 // Set accounting account infos
1139 if (!isset($tabaccountingaccount[$accountInfos['account_number']])) {
1140 $result = $accountingaccount->fetch(0, $accountInfos['account_number'], true);
1141 if ($result < 0) {
1142 setEventMessages($accountingaccount->error, $accountingaccount->errors, 'errors');
1143 $error++;
1144 break;
1145 }
1146 $tabaccountingaccount[$accountInfos['account_number']] = array(
1147 'label' => $result > 0 ? $accountingaccount->label : $langs->trans('NotDefined'),
1148 );
1149 }
1150
1151
1152 $errorforline = 0;
1153 $db->begin();
1154
1155 foreach ($payment['objects'] as $object_key => $object_data) {
1156 $objectInfos = $tabobject[$object_key];
1157
1158 $total_check = 0;
1159
1160 // Show bank line
1161 if ($object_data['amount'] >= 0) {
1162 $amount = (float) price2num($object_data['amount'], 'MT');
1163 $total_check += $amount;
1164
1165 $bookkeepingToCreate = new BookKeeping($db);
1166
1167 // Unique key is on couple: $payment_id, $objectInfos['id']
1168 // For record in llx_accountaing_bookkeeping, for record with doc_type = 'bank', the value of fk_doc is ID in llx_bank and fk_docdet too. Wetry a fix this way;
1169 //$result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, $objectInfos['id'], $accountInfos['account_number'], $tabaccountingaccount[$accountInfos['account_number']]['label'], $accountInfos['account_ref'], $amount, $journal, $journal_label, '');
1170 $result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, 0, $accountInfos['account_number'], $tabaccountingaccount[$accountInfos['account_number']]['label'], $accountInfos['account_ref'], $amount, $journal, $journal_label, '');
1171
1172 if ($result < 0) {
1173 $errorforline++;
1174
1175 if (!empty($bookkeepingToCreate->warnings)) {
1176 setEventMessages(null, $bookkeepingToCreate->warnings, 'warnings');
1177 }
1178 if (!empty($bookkeepingToCreate->errors)) {
1179 setEventMessages(null, $bookkeepingToCreate->errors, 'errors');
1180 }
1181 }
1182 }
1183
1184 // Operations
1185 $payment_total_vat = (float) price2num($object_data['amount'] * ($objectInfos['total_ttc'] - $objectInfos['total_ht']) / $objectInfos['total_ttc'], 'MT');
1186 $payment_total_ht = $object_data['amount'] - $payment_total_vat;
1187 $total_operation = 0;
1188 $idx = 1;
1189 $nb_operation = count($objectInfos['operations']);
1190 foreach ($objectInfos['operations'] as $accountancy_code => $operation) {
1191 if (!empty($operation['total_ht'])) {
1192 // Set accounting account infos
1193 if (!isset($tabaccountingaccount[$accountancy_code])) {
1194 $result = $accountingaccount->fetch(0, $accountancy_code, true);
1195 if ($result < 0) {
1196 setEventMessages($accountingaccount->error, $accountingaccount->errors, 'errors');
1197 $accountancy_code_label = $accountingaccount->errorsToString();
1198 $errorforline++;
1199 } elseif ($result > 0) {
1200 $accountancy_code_label = $accountingaccount->label;
1201 } else {
1202 $accountancy_code_label = $langs->trans('NotDefined');
1203 }
1204 $tabaccountingaccount[$accountancy_code] = array('label' => $accountancy_code_label);
1205 }
1206 $accountingAccountInfos = $tabaccountingaccount[$accountancy_code];
1207 if ($idx < $nb_operation) {
1208 $amount = price2num($payment_total_ht * $operation['total_ht'] / $objectInfos['total_ht'], 'MT');
1209 $total_operation += $amount;
1210 } else {
1211 $amount = $payment_total_ht - $total_operation;
1212 }
1213 $total_check -= $amount;
1214
1215 $bookkeepingToCreate = new BookKeeping($db);
1216 //$result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, $objectInfos['id'], $accountancy_code, $accountingAccountInfos['label'], (!empty($operation['label']) ? $operation['label'] : $accountingAccountInfos['label']), -$amount, $journal, $journal_label, '');
1217 $result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, 0, $accountancy_code, $accountingAccountInfos['label'], (!empty($operation['label']) ? $operation['label'] : $accountingAccountInfos['label']), -$amount, $journal, $journal_label, '');
1218 if ($result < 0) {
1219 $errorforline++;
1220
1221 if (!empty($bookkeepingToCreate->warnings)) {
1222 setEventMessages(null, $bookkeepingToCreate->warnings, 'warnings');
1223 }
1224 if (!empty($bookkeepingToCreate->errors)) {
1225 setEventMessages(null, $bookkeepingToCreate->errors, 'errors');
1226 }
1227 }
1228 }
1229 $idx++;
1230 }
1231
1232 // VATs
1233 $total_vat = 0;
1234 $idx = 1;
1235 $nb_vat = 0;
1236 foreach ($objectInfos['vats'] as $accountancy_code => $vats) {
1237 foreach ($vats as $vat_tx => $vat_infos) {
1238 $nb_vat++;
1239 }
1240 }
1241 foreach ($objectInfos['vats'] as $accountancy_code => $vats) {
1242 foreach ($vats as $vat_tx => $vat_infos) {
1243 $amount = $vat_infos['total_tva'] + $vat_infos['total_localtax1'] + $vat_infos['total_localtax2'];
1244 if (!empty($amount)) {
1245 // Set accounting account infos
1246 if (!isset($tabaccountingaccount[$accountancy_code])) {
1247 $result = $accountingaccount->fetch(0, $accountancy_code, true);
1248 if ($result < 0) {
1249 setEventMessages($accountingaccount->error, $accountingaccount->errors, 'errors');
1250 $accountancy_code_label = $accountingaccount->errorsToString();
1251 $errorforline++;
1252 } elseif ($result > 0) {
1253 $accountancy_code_label = $accountingaccount->label;
1254 } else {
1255 $accountancy_code_label = $langs->trans('NotDefined');
1256 }
1257 $tabaccountingaccount[$accountancy_code] = array('label' => $accountancy_code_label);
1258 }
1259 $accountingAccountInfos = $tabaccountingaccount[$accountancy_code];
1260 $amount = (float) price2num($payment_total_vat * $amount / ($objectInfos['total_ttc'] - $objectInfos['total_ht']), 'MT');
1261 $total_vat += $amount;
1262 $total_check -= $amount;
1263
1264 $bookkeepingToCreate = new BookKeeping($db);
1265 //$result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, $objectInfos['id'], $accountancy_code, $accountingAccountInfos['label'], $langs->trans('VAT').' '.price($vat_infos['tva_tx']).'%', -$amount, $journal, $journal_label, '');
1266 $result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, 0, $accountancy_code, $accountingAccountInfos['label'], $langs->trans('VAT').' '.price($vat_infos['tva_tx']).'%', -$amount, $journal, $journal_label, '');
1267 if ($result < 0) {
1268 $errorforline++;
1269
1270 if (!empty($bookkeepingToCreate->warnings)) {
1271 setEventMessages(null, $bookkeepingToCreate->warnings, 'warnings');
1272 }
1273 if (!empty($bookkeepingToCreate->errors)) {
1274 setEventMessages(null, $bookkeepingToCreate->errors, 'errors');
1275 }
1276 }
1277 }
1278 $idx++;
1279 }
1280 }
1281
1282 // Show bank line
1283 if ($object_data['amount'] < 0) {
1284 $amount = (float) price2num($object_data['amount'], 'MT');
1285 $total_check += $amount;
1286
1287 $bookkeepingToCreate = new BookKeeping($db);
1288 //$result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, $objectInfos['id'], $accountInfos['account_number'], $tabaccountingaccount[$accountInfos['account_number']]['label'], $accountInfos['account_ref'], $amount, $journal, $journal_label, '');
1289 $result = $bookkeepingToCreate->createFromValues($payment["date"], $objectInfos['ref'], 'bank', $payment_id, 0, $accountInfos['account_number'], $tabaccountingaccount[$accountInfos['account_number']]['label'], $accountInfos['account_ref'], $amount, $journal, $journal_label, '');
1290 if ($result < 0) {
1291 $errorforline++;
1292
1293 if (!empty($bookkeepingToCreate->warnings)) {
1294 setEventMessages(null, $bookkeepingToCreate->warnings, 'warnings');
1295 }
1296 if (!empty($bookkeepingToCreate->errors)) {
1297 setEventMessages(null, $bookkeepingToCreate->errors, 'errors');
1298 }
1299 }
1300 }
1301
1302 $total_check = price2num($total_check, 'MT');
1303 if (!empty($total_check)) {
1304 $errorforline++;
1305 setEventMessages($langs->trans('ErrorBookkeepingTryInsertNotBalancedTransactionAndCanceled', $objectInfos['ref'], $object_data['bu_url_id']), null, 'errors');
1306 }
1307
1308 if ($errorforline) {
1309 $error++;
1310
1311 if ($error >= $MAXNBERRORS) {
1312 break; // Break in the foreach
1313 }
1314 }
1315 }
1316
1317 if (!$errorforline) {
1318 $db->commit();
1319 } else {
1320 //print 'KO for line '.$key.' '.$error.'<br>';
1321 $db->rollback();
1322
1323 $MAXNBERRORS = 5;
1324 if ($error >= $MAXNBERRORS) {
1325 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped").' (>'.$MAXNBERRORS.')', null, 'errors');
1326 break; // Break in the foreach
1327 }
1328 }
1329 }
1330
1331 if (empty($error) && count($tabpay) > 0) {
1332 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
1333 } elseif (count($tabpay) == $error) {
1334 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
1335 } else {
1336 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
1337 }
1338
1339 $action = '';
1340
1341 // Must reload data, so we make a redirect
1342 if (count($tabpay) != $error) {
1343 $param = 'id_journal='.$id_journal;
1344 $param .= '&date_startday='.$date_startday;
1345 $param .= '&date_startmonth='.$date_startmonth;
1346 $param .= '&date_startyear='.$date_startyear;
1347 $param .= '&date_endday='.$date_endday;
1348 $param .= '&date_endmonth='.$date_endmonth;
1349 $param .= '&date_endyear='.$date_endyear;
1350 $param .= '&in_bookkeeping='.$in_bookkeeping;
1351 header("Location: " . $_SERVER['PHP_SELF'] . '?' . $param);
1352 exit;
1353 }
1354}
1355
1356
1357/*
1358 * View
1359 */
1360
1361$form = new Form($db);
1362$description = null;
1363
1364if (empty($action) || $action == 'view') {
1365 llxHeader('', $langs->trans("FinanceJournal"));
1366
1367 $nom = $langs->trans("FinanceJournal").' | '.$accountingjournalstatic->getNomUrl(0, 1, 1, '', 1);
1368 $nomlink = '';
1369 $builddate = dol_now();
1370 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
1371
1372 $listofchoices = array(
1373 'notyet' => $langs->trans("NotYetInGeneralLedger"),
1374 'already' => $langs->trans("AlreadyInGeneralLedger")
1375 );
1376 $period = $form->selectDate($date_start ?: -1, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end ?: -1, 'date_end', 0, 0, 0, '', 1, 0);
1377 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
1378
1379 $varlink = 'id_journal='.$id_journal;
1380 $periodlink = '';
1381 $exportlink = '';
1382
1383 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
1384
1385 // Test that setup is complete
1386 $sql = "SELECT COUNT(rowid) as nb FROM ".$db->prefix()."bank_account WHERE fk_accountancy_journal IS NULL AND clos = 0";
1387 $resql = $db->query($sql);
1388 if ($resql) {
1389 $obj = $db->fetch_object($resql);
1390 if ($obj->nb > 0) {
1391 print '<br>'.img_warning().' '.$langs->trans("TheJournalCodeIsNotDefinedOnSomeBankAccount");
1392 print ' : '.$langs->trans("AccountancyAreaDescBank", 9, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("BankAccounts").'</strong>');
1393 }
1394 } else {
1395 dol_print_error($db);
1396 }
1397
1398 // Button to write into Ledger
1399 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER') || getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER') == '-1'
1400 || !getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER') || getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER') == '-1'
1401 || !getDolGlobalString('SALARIES_ACCOUNTING_ACCOUNT_PAYMENT') || getDolGlobalString('SALARIES_ACCOUNTING_ACCOUNT_PAYMENT') == '-1') {
1402 print '<br>'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
1403 print ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>');
1404 }
1405
1406 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
1407
1408 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL')) {
1409 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
1410 }
1411
1412 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER') || getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER') == '-1'
1413 || !getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER') || getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER') == '-1'
1414 || !getDolGlobalString('SALARIES_ACCOUNTING_ACCOUNT_PAYMENT') || getDolGlobalString('SALARIES_ACCOUNTING_ACCOUNT_PAYMENT') == '-1') {
1415 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
1416 } else {
1417 if ($in_bookkeeping == 'notyet') {
1418 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
1419 } else {
1420 print '<a class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
1421 }
1422 }
1423 print '</div>';
1424
1425 // TODO Avoid using js. We can use a direct link with $param
1426 print '
1427 <script type="text/javascript">
1428 function writebookkeeping() {
1429 console.log("Set value into form and submit");
1430 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
1431 $("div.fiche form input[type=\"submit\"]").click();
1432 $("div.fiche form input[name=\"action\"]").val("");
1433 }
1434 </script>';
1435
1436 /*
1437 * Show result array
1438 */
1439 print '<br>';
1440
1441 $i = 0;
1442 print '<div class="div-table-responsive">';
1443 print '<table class="noborder centpercent">';
1444 print '<tr class="liste_titre">';
1445 print "<td>".$langs->trans("Date")."</td>";
1446 print "<td>".$langs->trans("Piece").' ('.$langs->trans("ObjectsRef").')</td>';
1447 print "<td>".$langs->trans("AccountAccounting")."</td>";
1448 print "<td>".$langs->trans("LabelOperation")."</td>";
1449 print '<td class="center">'.$langs->trans("PaymentMode")."</td>";
1450 print '<td class="right">'.$langs->trans("AccountingDebit")."</td>";
1451 print '<td class="right">'.$langs->trans("AccountingCredit")."</td>";
1452 print "</tr>\n";
1453
1454 foreach ($tabpay as $payment_id => $payment) {
1455 $accountInfos = $tabaccount[$payment["fk_bank_account"]];
1456 $date = dol_print_date($payment["date"], 'day');
1457 $i++;
1458
1459 foreach ($payment['objects'] as $object_key => $object_data) {
1460 $objectInfos = $tabobject[$object_key];
1461
1462 // Show bank line
1463 if ($object_data['amount'] >= 0) {
1464 FormAccounting::printJournalLine($langs, $date, $objectInfos['url'], $accountInfos['account_number'], $accountInfos['account_ref'], $payment['type_payment'], $object_data['amount']);
1465 }
1466
1467 // Operations
1468 $payment_total_vat = (float) price2num($object_data['amount'] * ($objectInfos['total_ttc'] - $objectInfos['total_ht']) / $objectInfos['total_ttc'], 'MT');
1469 $payment_total_ht = $object_data['amount'] - $payment_total_vat;
1470 $total_operation = 0;
1471 $idx = 1;
1472 $nb_operation = count($objectInfos['operations']);
1473 foreach ($objectInfos['operations'] as $accountancy_code => $operation) {
1474 // Set accounting account infos
1475 if (!isset($tabaccountingaccount[$accountancy_code])) {
1476 $result = $accountingaccount->fetch(0, $accountancy_code, true);
1477 $tabaccountingaccount[$accountancy_code] = array(
1478 'label' => $result < 0 ? $accountingaccount->errorsToString() : ($result > 0 ? $accountingaccount->label : $langs->trans('NotDefined')),
1479 );
1480 }
1481 $accountingAccountInfos = $tabaccountingaccount[$accountancy_code];
1482 if (!empty($operation['total_ht'])) {
1483 if ($idx < $nb_operation) {
1484 $value = price2num($payment_total_ht * $operation['total_ht'] / $objectInfos['total_ht'], 'MT');
1485 $total_operation += $value;
1486 } else {
1487 $value = $payment_total_ht - $total_operation;
1488 }
1489 FormAccounting::printJournalLine($langs, $date, $objectInfos['url'], $accountancy_code, (!empty($operation['label']) ? $operation['label'] : $accountingAccountInfos['label']), $payment['type_payment'], -$value);
1490 }
1491 $idx++;
1492 }
1493
1494 // VATs
1495 $total_vat = 0;
1496 $idx = 1;
1497 $nb_vat = 0;
1498 foreach ($objectInfos['vats'] as $accountancy_code => $vats) {
1499 foreach ($vats as $vat_tx => $vat_infos) {
1500 $nb_vat++;
1501 }
1502 }
1503 foreach ($objectInfos['vats'] as $accountancy_code => $vats) {
1504 foreach ($vats as $vat_tx => $vat_infos) {
1505 $amount_vat = $vat_infos['total_tva'] + $vat_infos['total_localtax1'] + $vat_infos['total_localtax2'];
1506 if (!empty($amount_vat)) {
1507 $amount_vat = (float) price2num($payment_total_vat * $amount_vat / ($objectInfos['total_ttc'] - $objectInfos['total_ht']), 'MT');
1508 $total_vat += $amount_vat;
1509 FormAccounting::printJournalLine($langs, $date, $objectInfos['url'], $accountancy_code, $langs->trans('VAT').' '.price($vat_infos['tva_tx']).'%', $payment['type_payment'], -$amount_vat);
1510 }
1511 $idx++;
1512 }
1513 }
1514
1515 // Show bank line
1516 if ($object_data['amount'] < 0) {
1517 FormAccounting::printJournalLine($langs, $date, $objectInfos['url'], $accountInfos['account_number'], $accountInfos['account_ref'], $payment['type_payment'], $object_data['amount']);
1518 }
1519 }
1520 }
1521
1522 if (!$i) {
1523 $colspan = 8;
1524 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1525 }
1526
1527 print "</table>";
1528 print '</div>';
1529
1530 llxFooter();
1531}
1532
1533$db->close();
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.
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 bank accounts.
Class to manage bank transaction lines.
Class to manage accounting accounts.
Class to manage accounting journals.
Class to manage Ledger (General Ledger and Subledger)
Class for managing the social charges.
const TYPE_SITUATION
Situation invoice.
Class to manage donations.
Definition don.class.php:41
Class to manage Trips and Expenses.
Class to manage suppliers invoices.
const TYPE_DEPOSIT
Deposit invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
const TYPE_REPLACEMENT
Replacement invoice.
Class to manage invoices.
const TYPE_REPLACEMENT
Replacement invoice.
const TYPE_SITUATION
Situation invoice.
const TYPE_DEPOSIT
Deposit invoice.
const TYPE_CREDIT_NOTE
Credit note invoice.
static printJournalLine($langs, $date, $ref, $accountAccounting, $labelOperation, $paymentMode, $amount)
Print line into the journal table.
Class to manage generation of HTML components Only common components must be here.
Loan.
Class to manage payments of salaries.
Class to manage various payments.
Class to manage subscriptions of foundation members.
Class to manage VAT - Value-added tax (also known in French as TVA - Taxe sur la valeur ajoutée)
Definition tva.class.php:38
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:600
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:619
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.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
payment_filter($v)
Filter for payment.