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