1<?php
2/* Copyright (C) 2016       Neil Orley          <neil.orley@oeris.fr>
3 * Copyright (C) 2013-2016  Olivier Geffroy     <jeff@jeffinfo.com>
4 * Copyright (C) 2013-2020  Florian Henry       <florian.henry@open-concept.pro>
5 * Copyright (C) 2013-2021  Alexandre Spangaro  <aspangaro@open-dsi.fr>
6 * Copyright (C) 2018       Frédéric France     <frederic.france@netlogic.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22/**
23 * \file 		htdocs/accountancy/bookkeeping/listbyaccount.php
24 * \ingroup 	Accountancy (Double entries)
25 * \brief 		List operation of ledger ordered by account number
26 */
27
28require '../../main.inc.php';
29
30require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
32require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
37
38// Load translation files required by the page
39$langs->loadLangs(array("accountancy", "compta"));
40
41$action = GETPOST('action', 'aZ09');
42$search_date_startyear =  GETPOST('search_date_startyear', 'int');
43$search_date_startmonth =  GETPOST('search_date_startmonth', 'int');
44$search_date_startday =  GETPOST('search_date_startday', 'int');
45$search_date_endyear =  GETPOST('search_date_endyear', 'int');
46$search_date_endmonth =  GETPOST('search_date_endmonth', 'int');
47$search_date_endday =  GETPOST('search_date_endday', 'int');
48$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear);
49$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
50$search_doc_date = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int'));
51$search_date_export_startyear =  GETPOST('search_date_export_startyear', 'int');
52$search_date_export_startmonth =  GETPOST('search_date_export_startmonth', 'int');
53$search_date_export_startday =  GETPOST('search_date_export_startday', 'int');
54$search_date_export_endyear =  GETPOST('search_date_export_endyear', 'int');
55$search_date_export_endmonth =  GETPOST('search_date_export_endmonth', 'int');
56$search_date_export_endday =  GETPOST('search_date_export_endday', 'int');
57$search_date_export_start = dol_mktime(0, 0, 0, $search_date_export_startmonth, $search_date_export_startday, $search_date_export_startyear);
58$search_date_export_end = dol_mktime(23, 59, 59, $search_date_export_endmonth, $search_date_export_endday, $search_date_export_endyear);
59$search_date_validation_startyear =  GETPOST('search_date_validation_startyear', 'int');
60$search_date_validation_startmonth =  GETPOST('search_date_validation_startmonth', 'int');
61$search_date_validation_startday =  GETPOST('search_date_validation_startday', 'int');
62$search_date_validation_endyear =  GETPOST('search_date_validation_endyear', 'int');
63$search_date_validation_endmonth =  GETPOST('search_date_validation_endmonth', 'int');
64$search_date_validation_endday =  GETPOST('search_date_validation_endday', 'int');
65$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear);
66$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear);
67
68$search_accountancy_code = GETPOST("search_accountancy_code");
69$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
70if ($search_accountancy_code_start == - 1) {
71	$search_accountancy_code_start = '';
72}
73$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha');
74if ($search_accountancy_code_end == - 1) {
75	$search_accountancy_code_end = '';
76}
77$search_doc_ref = GETPOST('search_doc_ref', 'alpha');
78$search_label_operation = GETPOST('search_label_operation', 'alpha');
79$search_mvt_num = GETPOST('search_mvt_num', 'int');
80$search_direction = GETPOST('search_direction', 'alpha');
81$search_ledger_code = GETPOST('search_ledger_code', 'array');
82$search_debit = GETPOST('search_debit', 'alpha');
83$search_credit = GETPOST('search_credit', 'alpha');
84$search_lettering_code = GETPOST('search_lettering_code', 'alpha');
85$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha');
86
87if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) {
88	$action = 'delbookkeepingyear';
89}
90
91// Load variable for pagination
92$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION);
93$sortfield = GETPOST('sortfield', 'aZ09comma');
94$sortorder = GETPOST('sortorder', 'aZ09comma');
95$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
96if (empty($page) || $page < 0) {
97	$page = 0;
98}
99$offset = $limit * $page;
100$pageprev = $page - 1;
101$pagenext = $page + 1;
102if ($sortorder == "") {
103	$sortorder = "ASC";
104}
105if ($sortfield == "") {
106	$sortfield = "t.doc_date,t.rowid";
107}
108
109// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
110$object = new BookKeeping($db);
111$formfile = new FormFile($db);
112$hookmanager->initHooks(array('bookkeepingbyaccountlist'));
113
114$formaccounting = new FormAccounting($db);
115$form = new Form($db);
116
117if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('search_date_startday') && !GETPOSTISSET('search_date_startmonth') && !GETPOSTISSET('search_date_starthour')) {
118	$sql = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear ";
119	$sql .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."'";
120	$sql .= $db->plimit(1);
121	$res = $db->query($sql);
122
123	if ($res->num_rows > 0) {
124		$fiscalYear = $db->fetch_object($res);
125		$search_date_start = strtotime($fiscalYear->date_start);
126		$search_date_end = strtotime($fiscalYear->date_end);
127	} else {
128		$month_start = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1);
129		$year_start = dol_print_date(dol_now(), '%Y');
130		if (dol_print_date(dol_now(), '%m') < $month_start) {
131			$year_start--; // If current month is lower that starting fiscal month, we start last year
132		}
133		$year_end = $year_start + 1;
134		$month_end = $month_start - 1;
135		if ($month_end < 1) {
136			$month_end = 12;
137			$year_end--;
138		}
139		$search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start);
140		$search_date_end = dol_get_last_day($year_end, $month_end);
141	}
142}
143
144$arrayfields = array(
145	// 't.subledger_account'=>array('label'=>$langs->trans("SubledgerAccount"), 'checked'=>1),
146	't.piece_num'=>array('label'=>$langs->trans("TransactionNumShort"), 'checked'=>1),
147	't.code_journal'=>array('label'=>$langs->trans("Codejournal"), 'checked'=>1),
148	't.doc_date'=>array('label'=>$langs->trans("Docdate"), 'checked'=>1),
149	't.doc_ref'=>array('label'=>$langs->trans("Piece"), 'checked'=>1),
150	't.label_operation'=>array('label'=>$langs->trans("Label"), 'checked'=>1),
151	't.debit'=>array('label'=>$langs->trans("Debit"), 'checked'=>1),
152	't.credit'=>array('label'=>$langs->trans("Credit"), 'checked'=>1),
153	't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1),
154	't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1),
155	't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1),
156);
157
158if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) {
159	unset($arrayfields['t.lettering_code']);
160}
161
162if ($search_date_start && empty($search_date_startyear)) {
163	$tmparray = dol_getdate($search_date_start);
164	$search_date_startyear = $tmparray['year'];
165	$search_date_startmonth = $tmparray['mon'];
166	$search_date_startday = $tmparray['mday'];
167}
168if ($search_date_end && empty($search_date_endyear)) {
169	$tmparray = dol_getdate($search_date_end);
170	$search_date_endyear = $tmparray['year'];
171	$search_date_endmonth = $tmparray['mon'];
172	$search_date_endday = $tmparray['mday'];
173}
174
175if (empty($conf->accounting->enabled)) {
176	accessforbidden();
177}
178if ($user->socid > 0) {
179	accessforbidden();
180}
181if (empty($user->rights->accounting->mouvements->lire)) {
182	accessforbidden();
183}
184
185
186/*
187 * Action
188 */
189
190if (GETPOST('cancel', 'alpha')) {
191	$action = 'list'; $massaction = '';
192}
193if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
194	$massaction = '';
195}
196
197$parameters = array('socid'=>$socid);
198$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
199if ($reshook < 0) {
200	setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
201}
202
203if (empty($reshook)) {
204	include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
205
206	if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
207		$search_doc_date = '';
208		$search_accountancy_code = '';
209		$search_accountancy_code_start = '';
210		$search_accountancy_code_end = '';
211		$search_label_account = '';
212		$search_doc_ref = '';
213		$search_label_operation = '';
214		$search_mvt_num = '';
215		$search_direction = '';
216		$search_ledger_code = array();
217		$search_date_start = '';
218		$search_date_end = '';
219		$search_date_startyear = '';
220		$search_date_startmonth = '';
221		$search_date_startday = '';
222		$search_date_endyear = '';
223		$search_date_endmonth = '';
224		$search_date_endday = '';
225		$search_date_export_start = '';
226		$search_date_export_end = '';
227		$search_date_export_startyear = '';
228		$search_date_export_startmonth = '';
229		$search_date_export_startday = '';
230		$search_date_export_endyear = '';
231		$search_date_export_endmonth = '';
232		$search_date_export_endday = '';
233		$search_date_validation_start = '';
234		$search_date_validation_end = '';
235		$search_date_validation_startyear = '';
236		$search_date_validation_startmonth = '';
237		$search_date_validation_startday = '';
238		$search_date_validation_endyear = '';
239		$search_date_validation_endmonth = '';
240		$search_date_validation_endday = '';
241		$search_debit = '';
242		$search_credit = '';
243		$search_lettering_code = '';
244		$search_not_reconciled = '';
245	}
246
247	// Must be after the remove filter action, before the export.
248	$param = '';
249	$filter = array();
250
251	if (!empty($search_date_start)) {
252		$filter['t.doc_date>='] = $search_date_start;
253		$param .= '&search_date_startmonth='.$search_date_startmonth.'&search_date_startday='.$search_date_startday.'&search_date_startyear='.$search_date_startyear;
254	}
255	if (!empty($search_date_end)) {
256		$filter['t.doc_date<='] = $search_date_end;
257		$param .= '&search_date_endmonth='.$search_date_endmonth.'&search_date_endday='.$search_date_endday.'&search_date_endyear='.$search_date_endyear;
258	}
259	if (!empty($search_doc_date)) {
260		$filter['t.doc_date'] = $search_doc_date;
261		$param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int');
262	}
263	if (!empty($search_accountancy_code_start)) {
264		$filter['t.numero_compte>='] = $search_accountancy_code_start;
265		$param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start);
266	}
267	if (!empty($search_accountancy_code_end)) {
268		$filter['t.numero_compte<='] = $search_accountancy_code_end;
269		$param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end);
270	}
271	if (!empty($search_label_account)) {
272		$filter['t.label_compte'] = $search_label_account;
273		$param .= '&search_label_compte='.urlencode($search_label_account);
274	}
275	if (!empty($search_mvt_num)) {
276		$filter['t.piece_num'] = $search_mvt_num;
277		$param .= '&search_mvt_num='.urlencode($search_mvt_num);
278	}
279	if (!empty($search_doc_ref)) {
280		$filter['t.doc_ref'] = $search_doc_ref;
281		$param .= '&search_doc_ref='.urlencode($search_doc_ref);
282	}
283	if (!empty($search_label_operation)) {
284		$filter['t.label_operation'] = $search_label_operation;
285		$param .= '&search_label_operation='.urlencode($search_label_operation);
286	}
287	if (!empty($search_direction)) {
288		$filter['t.sens'] = $search_direction;
289		$param .= '&search_direction='.urlencode($search_direction);
290	}
291	if (!empty($search_ledger_code)) {
292		$filter['t.code_journal'] = $search_ledger_code;
293		foreach ($search_ledger_code as $code) {
294			$param .= '&search_ledger_code[]='.urlencode($code);
295		}
296	}
297	if (!empty($search_debit)) {
298		$filter['t.debit'] = $search_debit;
299		$param .= '&search_debit='.urlencode($search_debit);
300	}
301	if (!empty($search_credit)) {
302		$filter['t.credit'] = $search_credit;
303		$param .= '&search_credit='.urlencode($search_credit);
304	}
305	if (!empty($search_lettering_code)) {
306		$filter['t.lettering_code'] = $search_lettering_code;
307		$param .= '&search_lettering_code='.urlencode($search_lettering_code);
308	}
309	if (!empty($search_not_reconciled)) {
310		$filter['t.reconciled_option'] = $search_not_reconciled;
311		$param .= '&search_not_reconciled='.urlencode($search_not_reconciled);
312	}
313	if (!empty($search_date_export_start)) {
314		$filter['t.date_export>='] = $search_date_export_start;
315		$param .= '&search_date_export_startmonth='.$search_date_export_startmonth.'&search_date_export_startday='.$search_date_export_startday.'&search_date_export_startyear='.$search_date_export_startyear;
316	}
317	if (!empty($search_date_export_end)) {
318		$filter['t.date_export<='] = $search_date_export_end;
319		$param .= '&search_date_export_endmonth='.$search_date_export_endmonth.'&search_date_export_endday='.$search_date_export_endday.'&search_date_export_endyear='.$search_date_export_endyear;
320	}
321	if (!empty($search_date_validation_start)) {
322		$filter['t.date_validated>='] = $search_date_validation_start;
323		$param .= '&search_date_validation_startmonth='.$search_date_validation_startmonth.'&search_date_validation_startday='.$search_date_validation_startday.'&search_date_validation_startyear='.$search_date_validation_startyear;
324	}
325	if (!empty($search_date_validation_end)) {
326		$filter['t.date_validated<='] = $search_date_validation_end;
327		$param .= '&search_date_validation_endmonth='.$search_date_validation_endmonth.'&search_date_validation_endday='.$search_date_validation_endday.'&search_date_validation_endyear='.$search_date_validation_endyear;
328	}
329}
330
331if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) {
332	$import_key = GETPOST('importkey', 'alpha');
333
334	if (!empty($import_key)) {
335		$result = $object->deleteByImportkey($import_key);
336		if ($result < 0) {
337			setEventMessages($object->error, $object->errors, 'errors');
338		}
339
340		// Make a redirect to avoid to launch the delete later after a back button
341		header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
342		exit;
343	}
344}
345if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
346	$delmonth = GETPOST('delmonth', 'int');
347	$delyear = GETPOST('delyear', 'int');
348	if ($delyear == -1) {
349		$delyear = 0;
350	}
351	$deljournal = GETPOST('deljournal', 'alpha');
352	if ($deljournal == -1) {
353		$deljournal = 0;
354	}
355
356	if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
357		$result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
358		if ($result < 0) {
359			setEventMessages($object->error, $object->errors, 'errors');
360		} else {
361			setEventMessages("RecordDeleted", null, 'mesgs');
362		}
363
364		// Make a redirect to avoid to launch the delete later after a back button
365		header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
366		exit;
367	} else {
368		setEventMessages("NoRecordDeleted", null, 'warnings');
369	}
370}
371if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) {
372	$mvt_num = GETPOST('mvt_num', 'int');
373
374	if (!empty($mvt_num)) {
375		$result = $object->deleteMvtNum($mvt_num);
376		if ($result < 0) {
377			setEventMessages($object->error, $object->errors, 'errors');
378		} else {
379			setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
380		}
381
382		header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : ''));
383		exit;
384	}
385}
386
387
388/*
389 * View
390 */
391
392$formaccounting = new FormAccounting($db);
393$formfile = new FormFile($db);
394$formother = new FormOther($db);
395$form = new Form($db);
396
397$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('.$langs->trans("Bookkeeping").')';
398
399llxHeader('', $title_page);
400
401// List
402$nbtotalofrecords = '';
403if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
404	$nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
405	if ($nbtotalofrecords < 0) {
406		setEventMessages($object->error, $object->errors, 'errors');
407	}
408}
409
410$result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter);
411
412if ($result < 0) {
413	setEventMessages($object->error, $object->errors, 'errors');
414}
415
416$num = count($object->lines);
417
418
419if ($action == 'delmouv') {
420	$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1);
421	print $formconfirm;
422}
423if ($action == 'delbookkeepingyear') {
424	$form_question = array();
425	$delyear = GETPOST('delyear', 'int');
426	$deljournal = GETPOST('deljournal', 'alpha');
427
428	if (empty($delyear)) {
429		$delyear = dol_print_date(dol_now(), '%Y');
430	}
431	$month_array = array();
432	for ($i = 1; $i <= 12; $i++) {
433		$month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
434	}
435	$year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
436	$journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
437
438	$form_question['delmonth'] = array(
439		'name' => 'delmonth',
440		'type' => 'select',
441		'label' => $langs->trans('DelMonth'),
442		'values' => $month_array,
443		'default' => ''
444	);
445	$form_question['delyear'] = array(
446		'name' => 'delyear',
447		'type' => 'select',
448		'label' => $langs->trans('DelYear'),
449		'values' => $year_array,
450		'default' => $delyear
451	);
452	$form_question['deljournal'] = array(
453		'name' => 'deljournal',
454		'type' => 'other', // We don't use select here, the journal_array is already a select html component
455		'label' => $langs->trans('DelJournal'),
456		'value' => $journal_array,
457		'default' => $deljournal
458	);
459
460	$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300);
461	print $formconfirm;
462}
463
464
465print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
466print '<input type="hidden" name="token" value="'.newToken().'">';
467print '<input type="hidden" name="action" value="list">';
468if ($optioncss != '') {
469	print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
470}
471print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
472print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
473print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
474
475$parameters = array();
476$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
477if (empty($reshook)) {
478	$newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param);
479	$newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected'));
480	$newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbysubaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly'));
481	$newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create');
482}
483
484if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
485	$param .= '&contextpage='.urlencode($contextpage);
486}
487if ($limit > 0 && $limit != $conf->liste_limit) {
488	$param .= '&limit='.urlencode($limit);
489}
490
491print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1);
492
493$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
494$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
495if ($massactionbutton) {
496	$selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
497}
498
499// Reverse sort order
500if (preg_match('/^asc/i', $sortorder)) {
501	$sortorder = "asc";
502} else {
503	$sortorder = "desc";
504}
505
506$moreforfilter = '';
507
508// Accountancy account
509$moreforfilter .= '<div class="divsearchfield">';
510$moreforfilter .= $langs->trans('AccountAccounting').': ';
511$moreforfilter .= '<div class="nowrap inline-block">';
512$moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200');
513$moreforfilter .= ' ';
514$moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200');
515$moreforfilter .= '</div>';
516$moreforfilter .= '</div>';
517
518$parameters = array();
519$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
520if (empty($reshook)) {
521	$moreforfilter .= $hookmanager->resPrint;
522} else {
523	$moreforfilter = $hookmanager->resPrint;
524}
525
526print '<div class="liste_titre liste_titre_bydiv centpercent">';
527print $moreforfilter;
528print '</div>';
529
530print '<div class="div-table-responsive">';
531print '<table class="tagtable liste centpercent">';
532
533// Filters lines
534print '<tr class="liste_titre_filter">';
535
536// Movement number
537if (!empty($arrayfields['t.piece_num']['checked'])) {
538	print '<td class="liste_titre"><input type="text" name="search_mvt_num" size="6" value="'.dol_escape_htmltag($search_mvt_num).'"></td>';
539}
540// Code journal
541if (!empty($arrayfields['t.code_journal']['checked'])) {
542	print '<td class="liste_titre center">';
543	print $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1);
544	print '</td>';
545}
546// Date document
547if (!empty($arrayfields['t.doc_date']['checked'])) {
548	print '<td class="liste_titre center">';
549	print '<div class="nowrap">';
550	print $form->selectDate($search_date_start, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
551	print '</div>';
552	print '<div class="nowrap">';
553	print $form->selectDate($search_date_end, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
554	print '</div>';
555	print '</td>';
556}
557// Ref document
558if (!empty($arrayfields['t.doc_ref']['checked'])) {
559	print '<td class="liste_titre"><input type="text" size="7" class="flat" name="search_doc_ref" value="'.dol_escape_htmltag($search_doc_ref).'"/></td>';
560}
561// Label operation
562if (!empty($arrayfields['t.label_operation']['checked'])) {
563	print '<td class="liste_titre"><input type="text" size="7" class="flat" name="search_label_operation" value="'.dol_escape_htmltag($search_label_operation).'"/></td>';
564}
565// Debit
566if (!empty($arrayfields['t.debit']['checked'])) {
567	print '<td class="liste_titre right"><input type="text" class="flat" name="search_debit" size="4" value="'.dol_escape_htmltag($search_debit).'"></td>';
568}
569// Credit
570if (!empty($arrayfields['t.credit']['checked'])) {
571	print '<td class="liste_titre right"><input type="text" class="flat" name="search_credit" size="4" value="'.dol_escape_htmltag($search_credit).'"></td>';
572}
573// Lettering code
574if (!empty($arrayfields['t.lettering_code']['checked'])) {
575	print '<td class="liste_titre center">';
576	print '<input type="text" size="3" class="flat" name="search_lettering_code" value="'.$search_lettering_code.'"/>';
577	print '<br><span class="nowrap"><input type="checkbox" name="search_not_reconciled" value="notreconciled"'.($search_not_reconciled == 'notreconciled' ? ' checked' : '').'>'.$langs->trans("NotReconciled").'</span>';
578	print '</td>';
579}
580// Date export
581if (!empty($arrayfields['t.date_export']['checked'])) {
582	print '<td class="liste_titre center">';
583	print '<div class="nowrap">';
584	print $form->selectDate($search_date_export_start, 'search_date_export_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
585	print '</div>';
586	print '<div class="nowrap">';
587	print $form->selectDate($search_date_export_end, 'search_date_export_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
588	print '</div>';
589	print '</td>';
590}
591// Date validation
592if (!empty($arrayfields['t.date_validated']['checked'])) {
593	print '<td class="liste_titre center">';
594	print '<div class="nowrap">';
595	print $form->selectDate($search_date_validation_start, 'search_date_validation_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
596	print '</div>';
597	print '<div class="nowrap">';
598	print $form->selectDate($search_date_validation_end, 'search_date_validation_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
599	print '</div>';
600	print '</td>';
601}
602
603// Fields from hook
604$parameters = array('arrayfields'=>$arrayfields);
605$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
606print $hookmanager->resPrint;
607
608// Action column
609print '<td class="liste_titre center">';
610$searchpicto = $form->showFilterButtons();
611print $searchpicto;
612print '</td>';
613print "</tr>\n";
614
615print '<tr class="liste_titre">';
616if (!empty($arrayfields['t.piece_num']['checked'])) {
617	print_liste_field_titre($arrayfields['t.piece_num']['label'], $_SERVER['PHP_SELF'], "t.piece_num", "", $param, '', $sortfield, $sortorder);
618}
619if (!empty($arrayfields['t.code_journal']['checked'])) {
620	print_liste_field_titre($arrayfields['t.code_journal']['label'], $_SERVER['PHP_SELF'], "t.code_journal", "", $param, '', $sortfield, $sortorder, 'center ');
621}
622if (!empty($arrayfields['t.doc_date']['checked'])) {
623	print_liste_field_titre($arrayfields['t.doc_date']['label'], $_SERVER['PHP_SELF'], "t.doc_date", "", $param, '', $sortfield, $sortorder, 'center ');
624}
625if (!empty($arrayfields['t.doc_ref']['checked'])) {
626	print_liste_field_titre($arrayfields['t.doc_ref']['label'], $_SERVER['PHP_SELF'], "t.doc_ref", "", $param, "", $sortfield, $sortorder);
627}
628if (!empty($arrayfields['t.label_operation']['checked'])) {
629	print_liste_field_titre($arrayfields['t.label_operation']['label'], $_SERVER['PHP_SELF'], "t.label_operation", "", $param, "", $sortfield, $sortorder);
630}
631if (!empty($arrayfields['t.debit']['checked'])) {
632	print_liste_field_titre($arrayfields['t.debit']['label'], $_SERVER['PHP_SELF'], "t.debit", "", $param, '', $sortfield, $sortorder, 'right ');
633}
634if (!empty($arrayfields['t.credit']['checked'])) {
635	print_liste_field_titre($arrayfields['t.credit']['label'], $_SERVER['PHP_SELF'], "t.credit", "", $param, '', $sortfield, $sortorder, 'right ');
636}
637if (!empty($arrayfields['t.lettering_code']['checked'])) {
638	print_liste_field_titre($arrayfields['t.lettering_code']['label'], $_SERVER['PHP_SELF'], "t.lettering_code", "", $param, '', $sortfield, $sortorder, 'center ');
639}
640if (!empty($arrayfields['t.date_export']['checked'])) {
641	print_liste_field_titre($arrayfields['t.date_export']['label'], $_SERVER['PHP_SELF'], "t.date_export", "", $param, '', $sortfield, $sortorder, 'center ');
642}
643if (!empty($arrayfields['t.date_validated']['checked'])) {
644	print_liste_field_titre($arrayfields['t.date_validated']['label'], $_SERVER['PHP_SELF'], "t.date_validated", "", $param, '', $sortfield, $sortorder, 'center ');
645}
646// Hook fields
647$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
648$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
649print $hookmanager->resPrint;
650print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
651print "</tr>\n";
652
653
654$total_debit = 0;
655$total_credit = 0;
656$sous_total_debit = 0;
657$sous_total_credit = 0;
658$displayed_account_number = null; // Start with undefined to be able to distinguish with empty
659
660// Loop on record
661// --------------------------------------------------------------------
662$i = 0;
663$totalarray = array();
664while ($i < min($num, $limit)) {
665	$line = $object->lines[$i];
666
667	$total_debit += $line->debit;
668	$total_credit += $line->credit;
669
670	$accountg = length_accountg($line->numero_compte);
671	//if (empty($accountg)) $accountg = '-';
672
673	$colspan = 0;			// colspan before field 'label of operation'
674	$colspanend = 3;		// colspan after debit/credit
675	if (!empty($arrayfields['t.piece_num']['checked'])) { $colspan++; }
676	if (!empty($arrayfields['t.code_journal']['checked'])) { $colspan++; }
677	if (!empty($arrayfields['t.doc_date']['checked'])) { $colspan++; }
678	if (!empty($arrayfields['t.doc_ref']['checked'])) { $colspan++; }
679	if (!empty($arrayfields['t.label_operation']['checked'])) { $colspan++; }
680	if (!empty($arrayfields['t.date_export']['checked'])) { $colspanend++; }
681	if (!empty($arrayfields['t.date_validating']['checked'])) { $colspanend++; }
682	if (!empty($arrayfields['t.lettering_code']['checked'])) { $colspanend++; }
683
684	// Is it a break ?
685	if ($accountg != $displayed_account_number || !isset($displayed_account_number)) {
686		// Show a subtotal by accounting account
687		if (isset($displayed_account_number)) {
688			print '<tr class="liste_total">';
689			print '<td class="right" colspan="'.$colspan.'">'.$langs->trans("TotalForAccount").' '.length_accountg($displayed_account_number).':</td>';
690			print '<td class="nowrap right">'.price($sous_total_debit).'</td>';
691			print '<td class="nowrap right">'.price($sous_total_credit).'</td>';
692			print '<td colspan="'.$colspanend.'"></td>';
693			print '</tr>';
694			// Show balance of last shown account
695			$balance = $sous_total_debit - $sous_total_credit;
696			print '<tr class="liste_total">';
697			print '<td class="right" colspan="'.$colspan.'">'.$langs->trans("Balance").':</td>';
698			if ($balance > 0) {
699				print '<td class="nowraponall right">';
700				print price($sous_total_debit - $sous_total_credit);
701				print '</td>';
702				print '<td></td>';
703			} else {
704				print '<td></td>';
705				print '<td class="nowraponall right">';
706				print price($sous_total_credit - $sous_total_debit);
707				print '</td>';
708			}
709			print '<td colspan="'.$colspanend.'"></td>';
710			print '</tr>';
711		}
712
713		// Show the break account
714		print "<tr>";
715		print '<td colspan="'.($totalarray['nbfield'] ? $totalarray['nbfield'] : 10).'" style="font-weight:bold; border-bottom: 1pt solid black;">';
716		if ($line->numero_compte != "" && $line->numero_compte != '-1') {
717			print length_accountg($line->numero_compte).' : '.$object->get_compte_desc($line->numero_compte);
718		} else {
719			print '<span class="error">'.$langs->trans("Unknown").'</span>';
720		}
721		print '</td>';
722		print '</tr>';
723
724		$displayed_account_number = $accountg;
725		//if (empty($displayed_account_number)) $displayed_account_number='-';
726		$sous_total_debit = 0;
727		$sous_total_credit = 0;
728
729		$colspan = 0;
730	}
731
732	print '<tr class="oddeven">';
733
734	// Piece number
735	if (!empty($arrayfields['t.piece_num']['checked'])) {
736		print '<td>';
737		$object->id = $line->id;
738		$object->piece_num = $line->piece_num;
739		print $object->getNomUrl(1, '', 0, '', 1);
740		print '</td>';
741		if (!$i) {
742			$totalarray['nbfield']++;
743		}
744	}
745
746	// Journal code
747	if (!empty($arrayfields['t.code_journal']['checked'])) {
748		$accountingjournal = new AccountingJournal($db);
749		$result = $accountingjournal->fetch('', $line->code_journal);
750		$journaltoshow = (($result > 0) ? $accountingjournal->getNomUrl(0, 0, 0, '', 0) : $line->code_journal);
751		print '<td class="center">'.$journaltoshow.'</td>';
752		if (!$i) {
753			$totalarray['nbfield']++;
754		}
755	}
756
757	// Document date
758	if (!empty($arrayfields['t.doc_date']['checked'])) {
759		print '<td class="center">'.dol_print_date($line->doc_date, 'day').'</td>';
760		if (!$i) {
761			$totalarray['nbfield']++;
762		}
763	}
764
765	// Document ref
766	if (!empty($arrayfields['t.doc_ref']['checked'])) {
767		if ($line->doc_type == 'customer_invoice') {
768			$langs->loadLangs(array('bills'));
769
770			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
771			$objectstatic = new Facture($db);
772			$objectstatic->fetch($line->fk_doc);
773			//$modulepart = 'facture';
774
775			$filename = dol_sanitizeFileName($line->doc_ref);
776			$filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($line->doc_ref);
777			$urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id;
778			$documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir);
779		} elseif ($line->doc_type == 'supplier_invoice') {
780			$langs->loadLangs(array('bills'));
781
782			require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
783			$objectstatic = new FactureFournisseur($db);
784			$objectstatic->fetch($line->fk_doc);
785			//$modulepart = 'invoice_supplier';
786
787			$filename = dol_sanitizeFileName($line->doc_ref);
788			$filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($line->fk_doc, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref);
789			$subdir = get_exdir($objectstatic->id, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref);
790			$documentlink = $formfile->getDocumentsLink($objectstatic->element, $subdir, $filedir);
791		} elseif ($line->doc_type == 'expense_report') {
792			$langs->loadLangs(array('trips'));
793
794			require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
795			$objectstatic = new ExpenseReport($db);
796			$objectstatic->fetch($line->fk_doc);
797			//$modulepart = 'expensereport';
798
799			$filename = dol_sanitizeFileName($line->doc_ref);
800			$filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($line->doc_ref);
801			$urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id;
802			$documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir);
803		} elseif ($line->doc_type == 'bank') {
804			require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
805			$objectstatic = new AccountLine($db);
806			$objectstatic->fetch($line->fk_doc);
807		} else {
808			// Other type
809		}
810
811		print '<td class="maxwidth400">';
812
813		print '<table class="nobordernopadding"><tr class="nocellnopadd">';
814		// Picto + Ref
815		print '<td class="nobordernopadding">';
816
817		if ($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice' || $line->doc_type == 'expense_report') {
818			print $objectstatic->getNomUrl(1, '', 0, 0, '', 0, -1, 1);
819			print $documentlink;
820		} elseif ($line->doc_type == 'bank') {
821			print $objectstatic->getNomUrl(1);
822			$bank_ref = strstr($line->doc_ref, '-');
823			print " " . $bank_ref;
824		} else {
825			print $line->doc_ref;
826		}
827		print '</td></tr></table>';
828
829		print "</td>\n";
830		if (!$i) {
831			$totalarray['nbfield']++;
832		}
833	}
834
835	// Label operation
836	if (!empty($arrayfields['t.label_operation']['checked'])) {
837		// Affiche un lien vers la facture client/fournisseur
838		$doc_ref = preg_replace('/\(.*\)/', '', $line->doc_ref);
839		print strlen(length_accounta($line->subledger_account)) == 0 ? '<td>'.$line->label_operation.'</td>' : '<td>'.$line->label_operation.'<br><span style="font-size:0.8em">('.length_accounta($line->subledger_account).')</span></td>';
840		if (!$i) {
841			$totalarray['nbfield']++;
842		}
843	}
844
845	// Amount debit
846	if (!empty($arrayfields['t.debit']['checked'])) {
847		print '<td class="right nowraponall amount">'.($line->debit ? price($line->debit) : '').'</td>';
848		if (!$i) {
849			$totalarray['nbfield']++;
850		}
851		if (!$i) {
852			$totalarray['pos'][$totalarray['nbfield']] = 'totaldebit';
853		}
854		$totalarray['val']['totaldebit'] += $line->debit;
855	}
856
857	// Amount credit
858	if (!empty($arrayfields['t.credit']['checked'])) {
859		print '<td class="right nowraponall amount">'.($line->credit ? price($line->credit) : '').'</td>';
860		if (!$i) {
861			$totalarray['nbfield']++;
862		}
863		if (!$i) {
864			$totalarray['pos'][$totalarray['nbfield']] = 'totalcredit';
865		}
866		$totalarray['val']['totalcredit'] += $line->credit;
867	}
868
869	// Lettering code
870	if (!empty($arrayfields['t.lettering_code']['checked'])) {
871		print '<td class="center">'.$line->lettering_code.'</td>';
872		if (!$i) {
873			$totalarray['nbfield']++;
874		}
875	}
876
877	// Exported operation date
878	if (!empty($arrayfields['t.date_export']['checked'])) {
879		print '<td class="center">'.dol_print_date($line->date_export, 'dayhour').'</td>';
880		if (!$i) {
881			$totalarray['nbfield']++;
882		}
883	}
884
885	// Validated operation date
886	if (!empty($arrayfields['t.date_validated']['checked'])) {
887		print '<td class="center">'.dol_print_date($line->date_validation, 'dayhour').'</td>';
888		if (!$i) {
889			$totalarray['nbfield']++;
890		}
891	}
892
893	// Fields from hook
894	$parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj);
895	$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
896	print $hookmanager->resPrint;
897
898	// Action column
899	print '<td class="nowraponall center">';
900	if (empty($line->date_export) && empty($line->date_validation)) {
901		if ($user->rights->accounting->mouvements->creer) {
902			print '<a class="editfielda paddingleft marginrightonly" href="' . DOL_URL_ROOT . '/accountancy/bookkeeping/card.php?piece_num=' . $line->piece_num . $param . '&page=' . $page . ($sortfield ? '&sortfield=' . $sortfield : '') . ($sortorder ? '&sortorder=' . $sortorder : '') . '">' . img_edit() . '</a>';
903		}
904	}
905	if (empty($line->date_validation)) {
906		if ($user->rights->accounting->mouvements->supprimer) {
907			print '<a class="reposition paddingleft marginrightonly" href="'.$_SERVER['PHP_SELF'].'?action=delmouv&mvt_num='.$line->piece_num.$param.'&page='.$page.($sortfield ? '&sortfield='.$sortfield : '').($sortorder ? '&sortorder='.$sortorder : '').'">'.img_delete().'</a>';
908		}
909	}
910	print '</td>';
911	if (!$i) {
912		$totalarray['nbfield']++;
913	}
914
915	// Comptabilise le sous-total
916	$sous_total_debit += $line->debit;
917	$sous_total_credit += $line->credit;
918
919	print "</tr>\n";
920
921	$i++;
922}
923
924if ($num > 0 && $colspan > 0) {
925	print '<tr class="liste_total">';
926	print '<td class="right" colspan="'.$colspan.'">'.$langs->trans("TotalForAccount").' '.$accountg.':</td>';
927	print '<td class="nowrap right">'.price($sous_total_debit).'</td>';
928	print '<td class="nowrap right">'.price($sous_total_credit).'</td>';
929	print '<td colspan="'.$colspanend.'"></td>';
930	print '</tr>';
931	// Show balance of last shown account
932	$balance = $sous_total_debit - $sous_total_credit;
933	print '<tr class="liste_total">';
934	print '<td class="right" colspan="'.$colspan.'">'.$langs->trans("Balance").':</td>';
935	if ($balance > 0) {
936		print '<td class="nowraponall right">';
937		print price($sous_total_debit - $sous_total_credit);
938		print '</td>';
939		print '<td></td>';
940	} else {
941		print '<td></td>';
942		print '<td class="nowraponall right">';
943		print price($sous_total_credit - $sous_total_debit);
944		print '</td>';
945	}
946	print '<td colspan="'.$colspanend.'"></td>';
947	print '</tr>';
948}
949
950// Show total line
951include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
952
953
954print "</table>";
955print '</div>';
956
957// TODO Replace this with mass delete action
958if ($user->rights->accounting->mouvements->supprimer_tous) {
959	print '<div class="tabsAction tabsActionNoBottom">'."\n";
960	print '<a class="butActionDelete" name="button_delmvt" href="'.$_SERVER["PHP_SELF"].'?action=delbookkeepingyear'.($param ? '&'.$param : '').'">'.$langs->trans("DeleteMvt").'</a>';
961	print '</div>';
962}
963
964print '</form>';
965
966// End of page
967llxFooter();
968$db->close();
969