diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php
index a760a550bef..bc7ea7c7072 100644
--- a/htdocs/accountancy/bookkeeping/list.php
+++ b/htdocs/accountancy/bookkeeping/list.php
@@ -28,6 +28,7 @@
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
@@ -42,6 +43,10 @@ $langs->loadLangs(array("accountancy", "compta"));
$socid = GETPOST('socid', 'int');
$action = GETPOST('action', 'aZ09');
+$massaction = GETPOST('massaction', 'alpha');
+$confirm = GETPOST('confirm', 'alpha');
+$toselect = GETPOST('toselect', 'array');
+$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepinglist';
$search_mvt_num = GETPOST('search_mvt_num', 'int');
$search_doc_type = GETPOST("search_doc_type", 'alpha');
$search_doc_ref = GETPOST("search_doc_ref", 'alpha');
@@ -86,6 +91,7 @@ $search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', '
$search_date_validation_endday = GETPOST('search_date_validation_endday', 'int');
$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear);
$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear);
+$search_import_key = GETPOST("search_import_key", 'alpha');
//var_dump($search_date_start);exit;
if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) {
@@ -191,6 +197,7 @@ $arrayfields = array(
't.tms'=>array('label'=>$langs->trans("DateModification"), 'checked'=>0),
't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1),
't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1),
+ 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100),
);
if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) {
@@ -220,10 +227,12 @@ if (empty($user->rights->accounting->mouvements->lire)) {
* Actions
*/
+$param = '';
+
if (GETPOST('cancel', 'alpha')) {
$action = 'list'; $massaction = '';
}
-if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
+if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'preunlettering' && $massaction != 'predeletebookkeepingwriting') {
$massaction = '';
}
@@ -294,10 +303,11 @@ if (empty($reshook)) {
$search_credit = '';
$search_lettering_code = '';
$search_not_reconciled = '';
+ $search_import_key = '';
+ $toselect = '';
}
// Must be after the remove filter action, before the export.
- $param = '';
$filter = array();
if (!empty($search_date_start)) {
$filter['t.doc_date>='] = $search_date_start;
@@ -416,77 +426,143 @@ if (empty($reshook)) {
$filter['t.reconciled_option'] = $search_not_reconciled;
$param .= '&search_not_reconciled='.urlencode($search_not_reconciled);
}
-}
+ if (!empty($search_import_key)) {
+ $filter['t.import_key'] = $search_import_key;
+ $param .= '&search_import_key='.urlencode($search_import_key);
+ }
-if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) {
- $import_key = GETPOST('importkey', 'alpha');
-
- if (!empty($import_key)) {
- $result = $object->deleteByImportkey($import_key);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
+ //if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
+ // $delmonth = GETPOST('delmonth', 'int');
+ // $delyear = GETPOST('delyear', 'int');
+ // if ($delyear == -1) {
+ // $delyear = 0;
+ // }
+ // $deljournal = GETPOST('deljournal', 'alpha');
+ // if ($deljournal == -1) {
+ // $deljournal = 0;
+ // }
+ //
+ // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
+ // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
+ // if ($result < 0) {
+ // setEventMessages($object->error, $object->errors, 'errors');
+ // } else {
+ // setEventMessages("RecordDeleted", null, 'mesgs');
+ // }
+ //
+ // // Make a redirect to avoid to launch the delete later after a back button
+ // header("Location: list.php".($param ? '?'.$param : ''));
+ // exit;
+ // } else {
+ // setEventMessages("NoRecordDeleted", null, 'warnings');
+ // }
+ //}
+ if ($action == 'setreexport') {
+ $setreexport = GETPOST('value', 'int');
+ if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) {
+ $error++;
}
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: list.php".($param ? '?'.$param : ''));
- exit;
- }
-}
-if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
- $delmonth = GETPOST('delmonth', 'int');
- $delyear = GETPOST('delyear', 'int');
- if ($delyear == -1) {
- $delyear = 0;
- }
- $deljournal = GETPOST('deljournal', 'alpha');
- if ($deljournal == -1) {
- $deljournal = 0;
- }
-
- if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
- $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
+ if (!$error) {
+ if ($conf->global->ACCOUNTING_REEXPORT == 1) {
+ setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs');
+ } else {
+ setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs');
+ }
} else {
- setEventMessages("RecordDeleted", null, 'mesgs');
+ setEventMessages($langs->trans("Error"), null, 'errors');
}
-
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: list.php".($param ? '?'.$param : ''));
- exit;
- } else {
- setEventMessages("NoRecordDeleted", null, 'warnings');
- }
-}
-if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) {
- $mvt_num = GETPOST('mvt_num', 'int');
-
- if (!empty($mvt_num)) {
- $result = $object->deleteMvtNum($mvt_num);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- } else {
- setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
- }
-
- header("Location: list.php?noreset=1".($param ? '&'.$param : ''));
- exit;
- }
-}
-if ($action == 'setreexport') {
- $setreexport = GETPOST('value', 'int');
- if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) {
- $error++;
}
- if (!$error) {
- if ($conf->global->ACCOUNTING_REEXPORT == 1) {
- setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs');
- } else {
- setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs');
+ // Mass actions
+ $objectclass = 'Bookkeeping';
+ $objectlabel = 'Bookkeeping';
+ $permissiontoread = $user->rights->societe->lire;
+ $permissiontodelete = $user->rights->societe->supprimer;
+ $permissiontoadd = $user->rights->societe->creer;
+ $uploaddir = $conf->societe->dir_output;
+ include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+
+ if (!$error && $action == 'deletebookkeepingwriting' && $confirm == "yes" && $user->rights->accounting->mouvements->supprimer) {
+ $nbok = 0;
+ foreach ($toselect as $toselectid) {
+ $result = $object->fetch($toselectid);
+ if ($result > 0 && (!isset($object->date_validation) || $object->date_validation === '')) {
+ $result = $object->deleteMvtNum($object->piece_num);
+ if ($result > 0) {
+ $nbok++;
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $error++;
+ break;
+ }
+ } elseif ($result < 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $error++;
+ break;
+ }
+ }
+
+ // Message for elements well deleted
+ if ($nbok > 1) {
+ setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
+ } elseif ($nbok > 0) {
+ setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
+ } elseif (!$error) {
+ setEventMessages($langs->trans("NoRecordDeleted"), null, 'mesgs');
+ }
+
+ if (!$error) {
+ header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : ''));
+ exit;
+ }
+ }
+
+ // others mass actions
+ if (!$error && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) {
+ if ($massaction == 'lettering') {
+ $lettering = new Lettering($db);
+ $nb_lettering = $lettering->bookkeepingLetteringAll($toselect);
+ if ($nb_lettering < 0) {
+ setEventMessages('', $lettering->errors, 'errors');
+ $error++;
+ $nb_lettering = max(0, abs($nb_lettering) - 2);
+ } elseif ($nb_lettering == 0) {
+ $nb_lettering = 0;
+ setEventMessages($langs->trans('AccountancyNoLetteringModified'), array(), 'mesgs');
+ }
+ if ($nb_lettering == 1) {
+ setEventMessages($langs->trans('AccountancyOneLetteringModifiedSuccessfully'), array(), 'mesgs');
+ } elseif ($nb_lettering > 1) {
+ setEventMessages($langs->trans('AccountancyLetteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs');
+ }
+
+ if (!$error) {
+ header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param);
+ exit();
+ }
+ } elseif ($action == 'unlettering' && $confirm == "yes") {
+ $lettering = new Lettering($db);
+ $nb_lettering = $lettering->bookkeepingLetteringAll($toselect, true);
+ if ($nb_lettering < 0) {
+ setEventMessages('', $lettering->errors, 'errors');
+ $error++;
+ $nb_lettering = max(0, abs($nb_lettering) - 2);
+ } elseif ($nb_lettering == 0) {
+ $nb_lettering = 0;
+ setEventMessages($langs->trans('AccountancyNoUnletteringModified'), array(), 'mesgs');
+ }
+ if ($nb_lettering == 1) {
+ setEventMessages($langs->trans('AccountancyOneUnletteringModifiedSuccessfully'), array(), 'mesgs');
+ } elseif ($nb_lettering > 1) {
+ setEventMessages($langs->trans('AccountancyUnletteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs');
+ }
+
+ if (!$error) {
+ header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param);
+ exit();
+ }
}
- } else {
- setEventMessages($langs->trans("Error"), null, 'errors');
}
}
@@ -520,7 +596,8 @@ $sql .= " t.piece_num,";
$sql .= " t.date_creation,";
$sql .= " t.tms as date_modification,";
$sql .= " t.date_export,";
-$sql .= " t.date_validated as date_validation";
+$sql .= " t.date_validated as date_validation,";
+$sql .= " t.import_key";
$sql .= ' FROM '.MAIN_DB_PREFIX.$object->table_element.' as t';
// Manage filter
$sqlwhere = array();
@@ -667,6 +744,7 @@ if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) {
$num = $db->num_rows($resql);
}
+$arrayofselected = is_array($toselect) ? $toselect : array();
// Output page
// --------------------------------------------------------------------
@@ -684,7 +762,7 @@ if ($action == 'export_file') {
'name' => 'notifiedexportdate',
'type' => 'checkbox',
'label' => $langs->trans('NotifiedExportDate'),
- 'value' => $checked,
+ 'value' => (!empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) ? 'false' : 'true'),
);
$form_question['separator'] = array('name'=>'separator', 'type'=>'separator');
@@ -703,50 +781,46 @@ if ($action == 'export_file') {
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 300, 600);
}
-if ($action == 'delmouv') {
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.urlencode(GETPOST('mvt_num')).$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1);
-}
-
-if ($action == 'delbookkeepingyear') {
- $form_question = array();
- $delyear = GETPOST('delyear', 'int');
- $deljournal = GETPOST('deljournal', 'alpha');
-
- if (empty($delyear)) {
- $delyear = dol_print_date(dol_now(), '%Y');
- }
- $month_array = array();
- for ($i = 1; $i <= 12; $i++) {
- $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
- }
- $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
- $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
-
- $form_question['delmonth'] = array(
- 'name' => 'delmonth',
- 'type' => 'select',
- 'label' => $langs->trans('DelMonth'),
- 'values' => $month_array,
- 'morecss' => 'minwidth150',
- 'default' => ''
- );
- $form_question['delyear'] = array(
- 'name' => 'delyear',
- 'type' => 'select',
- 'label' => $langs->trans('DelYear'),
- 'values' => $year_array,
- 'default' => $delyear
- );
- $form_question['deljournal'] = array(
- 'name' => 'deljournal',
- 'type' => 'other', // We don't use select here, the journal_array is already a select html component
- 'label' => $langs->trans('DelJournal'),
- 'value' => $journal_array,
- 'default' => $deljournal
- );
-
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 320);
-}
+//if ($action == 'delbookkeepingyear') {
+// $form_question = array();
+// $delyear = GETPOST('delyear', 'int');
+// $deljournal = GETPOST('deljournal', 'alpha');
+//
+// if (empty($delyear)) {
+// $delyear = dol_print_date(dol_now(), '%Y');
+// }
+// $month_array = array();
+// for ($i = 1; $i <= 12; $i++) {
+// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
+// }
+// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
+// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
+//
+// $form_question['delmonth'] = array(
+// 'name' => 'delmonth',
+// 'type' => 'select',
+// 'label' => $langs->trans('DelMonth'),
+// 'values' => $month_array,
+// 'morecss' => 'minwidth150',
+// 'default' => ''
+// );
+// $form_question['delyear'] = array(
+// 'name' => 'delyear',
+// 'type' => 'select',
+// 'label' => $langs->trans('DelYear'),
+// 'values' => $year_array,
+// 'default' => $delyear
+// );
+// $form_question['deljournal'] = array(
+// 'name' => 'deljournal',
+// 'type' => 'other', // We don't use select here, the journal_array is already a select html component
+// 'label' => $langs->trans('DelJournal'),
+// 'value' => $journal_array,
+// 'default' => $deljournal
+// );
+//
+// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 320);
+//}
// Print form confirm
print $formconfirm;
@@ -759,6 +833,22 @@ if ($limit > 0 && $limit != $conf->liste_limit) {
$param .= '&limit='.urlencode($limit);
}
+// List of mass actions available
+$arrayofmassactions = array();
+/*
+if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) {
+ $arrayofmassactions['lettering'] = img_picto('', 'check', 'class="pictofixedwidth"') . $langs->trans('Lettering');
+ $arrayofmassactions['preunlettering'] = img_picto('', 'uncheck', 'class="pictofixedwidth"') . $langs->trans('Unlettering');
+}
+*/
+if ($user->rights->accounting->mouvements->supprimer) {
+ $arrayofmassactions['predeletebookkeepingwriting'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
+}
+if (GETPOST('nomassaction', 'int') || in_array($massaction, array('preunlettering', 'predeletebookkeepingwriting'))) {
+ $arrayofmassactions = array();
+}
+$massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions);
+
print '
';
diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php
index 837a372a32d..5650cce8767 100644
--- a/htdocs/accountancy/bookkeeping/listbyaccount.php
+++ b/htdocs/accountancy/bookkeeping/listbyaccount.php
@@ -28,6 +28,7 @@
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
@@ -39,6 +40,16 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
$langs->loadLangs(array("accountancy", "compta"));
$action = GETPOST('action', 'aZ09');
+$massaction = GETPOST('massaction', 'alpha');
+$confirm = GETPOST('confirm', 'alpha');
+$toselect = GETPOST('toselect', 'array');
+$type = GETPOST('type', 'alpha');
+if ($type == 'sub') {
+ $context_default = 'bookkeepingbysubaccountlist';
+} else {
+ $context_default = 'bookkeepingbyaccountlist';
+}
+$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : $context_default;
$search_date_startyear = GETPOST('search_date_startyear', 'int');
$search_date_startmonth = GETPOST('search_date_startmonth', 'int');
$search_date_startday = GETPOST('search_date_startday', 'int');
@@ -64,6 +75,7 @@ $search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', '
$search_date_validation_endday = GETPOST('search_date_validation_endday', 'int');
$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear);
$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear);
+$search_import_key = GETPOST("search_import_key", 'alpha');
$search_accountancy_code = GETPOST("search_accountancy_code");
$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
@@ -109,7 +121,7 @@ if ($sortfield == "") {
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$object = new BookKeeping($db);
$formfile = new FormFile($db);
-$hookmanager->initHooks(array('bookkeepingbyaccountlist'));
+$hookmanager->initHooks(array($context_default));
$formaccounting = new FormAccounting($db);
$form = new Form($db);
@@ -153,6 +165,7 @@ $arrayfields = array(
't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1),
't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1),
't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1),
+ 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100),
);
if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) {
@@ -187,10 +200,13 @@ if (empty($user->rights->accounting->mouvements->lire)) {
* Action
*/
+$param = '';
+
if (GETPOST('cancel', 'alpha')) {
- $action = 'list'; $massaction = '';
+ $action = 'list';
+ $massaction = '';
}
-if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
+if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'preunlettering' && $massaction != 'predeletebookkeepingwriting') {
$massaction = '';
}
@@ -242,10 +258,11 @@ if (empty($reshook)) {
$search_credit = '';
$search_lettering_code = '';
$search_not_reconciled = '';
+ $search_import_key = '';
+ $toselect = '';
}
// Must be after the remove filter action, before the export.
- $param = '';
$filter = array();
if (!empty($search_date_start)) {
@@ -261,12 +278,20 @@ if (empty($reshook)) {
$param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int');
}
if (!empty($search_accountancy_code_start)) {
- $filter['t.numero_compte>='] = $search_accountancy_code_start;
- $param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start);
+ if ($type == 'sub') {
+ $filter['t.subledger_account>='] = $search_accountancy_code_start;
+ } else {
+ $filter['t.numero_compte>='] = $search_accountancy_code_start;
+ }
+ $param .= '&search_accountancy_code_start=' . urlencode($search_accountancy_code_start);
}
if (!empty($search_accountancy_code_end)) {
- $filter['t.numero_compte<='] = $search_accountancy_code_end;
- $param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end);
+ if ($type == 'sub') {
+ $filter['t.subledger_account<='] = $search_accountancy_code_end;
+ } else {
+ $filter['t.numero_compte<='] = $search_accountancy_code_end;
+ }
+ $param .= '&search_accountancy_code_end=' . urlencode($search_accountancy_code_end);
}
if (!empty($search_label_account)) {
$filter['t.label_compte'] = $search_label_account;
@@ -326,61 +351,133 @@ if (empty($reshook)) {
$filter['t.date_validated<='] = $search_date_validation_end;
$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;
}
-}
+ if (!empty($search_import_key)) {
+ $filter['t.import_key'] = $search_import_key;
+ $param .= '&search_import_key='.urlencode($search_import_key);
+ }
-if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) {
- $import_key = GETPOST('importkey', 'alpha');
+ // param with type of list
+ $url_param = substr($param, 1); // remove first "&"
+ if (!empty($type)) {
+ $param = '&type='.$type.$param;
+ }
- if (!empty($import_key)) {
- $result = $object->deleteByImportkey($import_key);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
+ //if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
+ // $delmonth = GETPOST('delmonth', 'int');
+ // $delyear = GETPOST('delyear', 'int');
+ // if ($delyear == -1) {
+ // $delyear = 0;
+ // }
+ // $deljournal = GETPOST('deljournal', 'alpha');
+ // if ($deljournal == -1) {
+ // $deljournal = 0;
+ // }
+ //
+ // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
+ // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
+ // if ($result < 0) {
+ // setEventMessages($object->error, $object->errors, 'errors');
+ // } else {
+ // setEventMessages("RecordDeleted", null, 'mesgs');
+ // }
+ //
+ // // Make a redirect to avoid to launch the delete later after a back button
+ // header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
+ // exit;
+ // } else {
+ // setEventMessages("NoRecordDeleted", null, 'warnings');
+ // }
+ //}
+
+ // Mass actions
+ $objectclass = 'Bookkeeping';
+ $objectlabel = 'Bookkeeping';
+ $permissiontoread = $user->rights->societe->lire;
+ $permissiontodelete = $user->rights->societe->supprimer;
+ $permissiontoadd = $user->rights->societe->creer;
+ $uploaddir = $conf->societe->dir_output;
+ include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
+
+ if (!$error && $action == 'deletebookkeepingwriting' && $confirm == "yes" && $user->rights->accounting->mouvements->supprimer) {
+ $nbok = 0;
+ foreach ($toselect as $toselectid) {
+ $result = $object->fetch($toselectid);
+ if ($result > 0 && (!isset($object->date_validation) || $object->date_validation === '')) {
+ $result = $object->deleteMvtNum($object->piece_num);
+ if ($result > 0) {
+ $nbok++;
+ } else {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $error++;
+ break;
+ }
+ } elseif ($result < 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ $error++;
+ break;
+ }
}
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
- exit;
- }
-}
-if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
- $delmonth = GETPOST('delmonth', 'int');
- $delyear = GETPOST('delyear', 'int');
- if ($delyear == -1) {
- $delyear = 0;
- }
- $deljournal = GETPOST('deljournal', 'alpha');
- if ($deljournal == -1) {
- $deljournal = 0;
- }
-
- if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
- $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- } else {
- setEventMessages("RecordDeleted", null, 'mesgs');
+ // Message for elements well deleted
+ if ($nbok > 1) {
+ setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
+ } elseif ($nbok > 0) {
+ setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
+ } elseif (!$error) {
+ setEventMessages($langs->trans("NoRecordDeleted"), null, 'mesgs');
}
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
- exit;
- } else {
- setEventMessages("NoRecordDeleted", null, 'warnings');
- }
-}
-if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) {
- $mvt_num = GETPOST('mvt_num', 'int');
-
- if (!empty($mvt_num)) {
- $result = $object->deleteMvtNum($mvt_num);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- } else {
- setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
+ if (!$error) {
+ header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : ''));
+ exit;
}
+ }
- header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : ''));
- exit;
+ // others mass actions
+ if (!$error && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) {
+ if ($massaction == 'lettering') {
+ $lettering = new Lettering($db);
+ $nb_lettering = $lettering->bookkeepingLetteringAll($toselect);
+ if ($nb_lettering < 0) {
+ setEventMessages('', $lettering->errors, 'errors');
+ $error++;
+ $nb_lettering = max(0, abs($nb_lettering) - 2);
+ } elseif ($nb_lettering == 0) {
+ $nb_lettering = 0;
+ setEventMessages($langs->trans('AccountancyNoLetteringModified'), array(), 'mesgs');
+ }
+ if ($nb_lettering == 1) {
+ setEventMessages($langs->trans('AccountancyOneLetteringModifiedSuccessfully'), array(), 'mesgs');
+ } elseif ($nb_lettering > 1) {
+ setEventMessages($langs->trans('AccountancyLetteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs');
+ }
+
+ if (!$error) {
+ header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param);
+ exit();
+ }
+ } elseif ($action == 'unlettering' && $confirm == "yes") {
+ $lettering = new Lettering($db);
+ $nb_lettering = $lettering->bookkeepingLetteringAll($toselect, true);
+ if ($nb_lettering < 0) {
+ setEventMessages('', $lettering->errors, 'errors');
+ $error++;
+ $nb_lettering = max(0, abs($nb_lettering) - 2);
+ } elseif ($nb_lettering == 0) {
+ $nb_lettering = 0;
+ setEventMessages($langs->trans('AccountancyNoUnletteringModified'), array(), 'mesgs');
+ }
+ if ($nb_lettering == 1) {
+ setEventMessages($langs->trans('AccountancyOneUnletteringModifiedSuccessfully'), array(), 'mesgs');
+ } elseif ($nb_lettering > 1) {
+ setEventMessages($langs->trans('AccountancyUnletteringModifiedSuccessfully', $nb_lettering), array(), 'mesgs');
+ }
+
+ if (!$error) {
+ header('Location: ' . $_SERVER['PHP_SELF'] . '?noreset=1' . $param);
+ exit();
+ }
+ }
}
}
@@ -394,73 +491,101 @@ $formfile = new FormFile($db);
$formother = new FormOther($db);
$form = new Form($db);
-$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('.$langs->trans("Bookkeeping").')';
+$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' (';
+if ($type == 'sub') {
+ $title_page .= $langs->trans("BookkeepingSubAccount");
+} else {
+ $title_page .= $langs->trans("Bookkeeping");
+}
+$title_page .= ')';
llxHeader('', $title_page);
// List
$nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
- $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
+ if ($type == 'sub') {
+ $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
+ } else {
+ $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter);
+ }
+
if ($nbtotalofrecords < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
}
-$result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter);
+if ($type == 'sub') {
+ $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
+} else {
+ $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter);
+}
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
+$arrayofselected = is_array($toselect) ? $toselect : array();
+
$num = count($object->lines);
-if ($action == 'delmouv') {
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1);
- print $formconfirm;
+///if ($action == 'delbookkeepingyear') {
+// $form_question = array();
+// $delyear = GETPOST('delyear', 'int');
+// $deljournal = GETPOST('deljournal', 'alpha');
+//
+// if (empty($delyear)) {
+// $delyear = dol_print_date(dol_now(), '%Y');
+// }
+// $month_array = array();
+// for ($i = 1; $i <= 12; $i++) {
+// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
+// }
+// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
+// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
+//
+// $form_question['delmonth'] = array(
+// 'name' => 'delmonth',
+// 'type' => 'select',
+// 'label' => $langs->trans('DelMonth'),
+// 'values' => $month_array,
+// 'default' => ''
+// );
+// $form_question['delyear'] = array(
+// 'name' => 'delyear',
+// 'type' => 'select',
+// 'label' => $langs->trans('DelYear'),
+// 'values' => $year_array,
+// 'default' => $delyear
+// );
+// $form_question['deljournal'] = array(
+// 'name' => 'deljournal',
+// 'type' => 'other', // We don't use select here, the journal_array is already a select html component
+// 'label' => $langs->trans('DelJournal'),
+// 'value' => $journal_array,
+// 'default' => $deljournal
+// );
+//
+// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300);
+//}
+
+// Print form confirm
+print $formconfirm;
+
+// List of mass actions available
+$arrayofmassactions = array();
+if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && $user->rights->accounting->mouvements->creer) {
+ $arrayofmassactions['lettering'] = img_picto('', 'check', 'class="pictofixedwidth"') . $langs->trans('Lettering');
+ $arrayofmassactions['preunlettering'] = img_picto('', 'uncheck', 'class="pictofixedwidth"') . $langs->trans('Unlettering');
}
-if ($action == 'delbookkeepingyear') {
- $form_question = array();
- $delyear = GETPOST('delyear', 'int');
- $deljournal = GETPOST('deljournal', 'alpha');
-
- if (empty($delyear)) {
- $delyear = dol_print_date(dol_now(), '%Y');
- }
- $month_array = array();
- for ($i = 1; $i <= 12; $i++) {
- $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
- }
- $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
- $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
-
- $form_question['delmonth'] = array(
- 'name' => 'delmonth',
- 'type' => 'select',
- 'label' => $langs->trans('DelMonth'),
- 'values' => $month_array,
- 'default' => ''
- );
- $form_question['delyear'] = array(
- 'name' => 'delyear',
- 'type' => 'select',
- 'label' => $langs->trans('DelYear'),
- 'values' => $year_array,
- 'default' => $delyear
- );
- $form_question['deljournal'] = array(
- 'name' => 'deljournal',
- 'type' => 'other', // We don't use select here, the journal_array is already a select html component
- 'label' => $langs->trans('DelJournal'),
- 'value' => $journal_array,
- 'default' => $deljournal
- );
-
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300);
- print $formconfirm;
+if ($user->rights->accounting->mouvements->supprimer) {
+ $arrayofmassactions['predeletebookkeepingwriting'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
}
-
+if (GETPOST('nomassaction', 'int') || in_array($massaction, array('preunlettering', 'predeletebookkeepingwriting'))) {
+ $arrayofmassactions = array();
+}
+$massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions);
print '';
diff --git a/htdocs/accountancy/bookkeeping/listbysubaccount.php b/htdocs/accountancy/bookkeeping/listbysubaccount.php
deleted file mode 100644
index c6fb95d5ab7..00000000000
--- a/htdocs/accountancy/bookkeeping/listbysubaccount.php
+++ /dev/null
@@ -1,979 +0,0 @@
-
- * Copyright (C) 2013-2016 Olivier Geffroy
- * Copyright (C) 2013-2020 Florian Henry
- * Copyright (C) 2013-2021 Alexandre Spangaro
- * Copyright (C) 2018-2020 Frédéric France
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/**
- * \file htdocs/accountancy/bookkeeping/listbysubaccount.php
- * \ingroup Accountancy (Double entries)
- * \brief List operation of ledger ordered by subaccount number
- */
-
-require '../../main.inc.php';
-
-require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
-require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
-require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
-require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
-require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
-require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
-require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
-
-// Load translation files required by the page
-$langs->loadLangs(array("accountancy", "compta"));
-
-$action = GETPOST('action', 'aZ09');
-$search_date_startyear = GETPOST('search_date_startyear', 'int');
-$search_date_startmonth = GETPOST('search_date_startmonth', 'int');
-$search_date_startday = GETPOST('search_date_startday', 'int');
-$search_date_endyear = GETPOST('search_date_endyear', 'int');
-$search_date_endmonth = GETPOST('search_date_endmonth', 'int');
-$search_date_endday = GETPOST('search_date_endday', 'int');
-$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear);
-$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
-$search_doc_date = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int'));
-$search_date_export_startyear = GETPOST('search_date_export_startyear', 'int');
-$search_date_export_startmonth = GETPOST('search_date_export_startmonth', 'int');
-$search_date_export_startday = GETPOST('search_date_export_startday', 'int');
-$search_date_export_endyear = GETPOST('search_date_export_endyear', 'int');
-$search_date_export_endmonth = GETPOST('search_date_export_endmonth', 'int');
-$search_date_export_endday = GETPOST('search_date_export_endday', 'int');
-$search_date_export_start = dol_mktime(0, 0, 0, $search_date_export_startmonth, $search_date_export_startday, $search_date_export_startyear);
-$search_date_export_end = dol_mktime(23, 59, 59, $search_date_export_endmonth, $search_date_export_endday, $search_date_export_endyear);
-$search_date_validation_startyear = GETPOST('search_date_validation_startyear', 'int');
-$search_date_validation_startmonth = GETPOST('search_date_validation_startmonth', 'int');
-$search_date_validation_startday = GETPOST('search_date_validation_startday', 'int');
-$search_date_validation_endyear = GETPOST('search_date_validation_endyear', 'int');
-$search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', 'int');
-$search_date_validation_endday = GETPOST('search_date_validation_endday', 'int');
-$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear);
-$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear);
-
-$search_accountancy_code = GETPOST("search_accountancy_code");
-$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
-if ($search_accountancy_code_start == - 1) {
- $search_accountancy_code_start = '';
-}
-$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha');
-if ($search_accountancy_code_end == - 1) {
- $search_accountancy_code_end = '';
-}
-$search_doc_ref = GETPOST('search_doc_ref', 'alpha');
-$search_label_operation = GETPOST('search_label_operation', 'alpha');
-$search_mvt_num = GETPOST('search_mvt_num', 'int');
-$search_direction = GETPOST('search_direction', 'alpha');
-$search_ledger_code = GETPOST('search_ledger_code', 'array');
-$search_debit = GETPOST('search_debit', 'alpha');
-$search_credit = GETPOST('search_credit', 'alpha');
-$search_lettering_code = GETPOST('search_lettering_code', 'alpha');
-$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha');
-
-if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) {
- $action = 'delbookkeepingyear';
-}
-
-// Load variable for pagination
-$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION);
-$sortfield = GETPOST('sortfield', 'aZ09comma');
-$sortorder = GETPOST('sortorder', 'aZ09comma');
-$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
-if (empty($page) || $page < 0) {
- $page = 0;
-}
-$offset = $limit * $page;
-$pageprev = $page - 1;
-$pagenext = $page + 1;
-if ($sortorder == "") {
- $sortorder = "ASC";
-}
-if ($sortfield == "") {
- $sortfield = "t.doc_date,t.rowid";
-}
-
-// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
-$object = new BookKeeping($db);
-$formfile = new FormFile($db);
-$hookmanager->initHooks(array('bookkeepingbysubaccountlist'));
-
-$formaccounting = new FormAccounting($db);
-$form = new Form($db);
-
-if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('search_date_startday') && !GETPOSTISSET('search_date_startmonth') && !GETPOSTISSET('search_date_starthour')) {
- $sql = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear ";
- $sql .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."'";
- $sql .= $db->plimit(1);
- $res = $db->query($sql);
-
- if ($res->num_rows > 0) {
- $fiscalYear = $db->fetch_object($res);
- $search_date_start = strtotime($fiscalYear->date_start);
- $search_date_end = strtotime($fiscalYear->date_end);
- } else {
- $month_start = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1);
- $year_start = dol_print_date(dol_now(), '%Y');
- if (dol_print_date(dol_now(), '%m') < $month_start) {
- $year_start--; // If current month is lower that starting fiscal month, we start last year
- }
- $year_end = $year_start + 1;
- $month_end = $month_start - 1;
- if ($month_end < 1) {
- $month_end = 12;
- $year_end--;
- }
- $search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start);
- $search_date_end = dol_get_last_day($year_end, $month_end);
- }
-}
-
-$arrayfields = array(
- // 't.subledger_account'=>array('label'=>$langs->trans("SubledgerAccount"), 'checked'=>1),
- 't.piece_num'=>array('label'=>$langs->trans("TransactionNumShort"), 'checked'=>1),
- 't.code_journal'=>array('label'=>$langs->trans("Codejournal"), 'checked'=>1),
- 't.doc_date'=>array('label'=>$langs->trans("Docdate"), 'checked'=>1),
- 't.doc_ref'=>array('label'=>$langs->trans("Piece"), 'checked'=>1),
- 't.label_operation'=>array('label'=>$langs->trans("Label"), 'checked'=>1),
- 't.debit'=>array('label'=>$langs->trans("Debit"), 'checked'=>1),
- 't.credit'=>array('label'=>$langs->trans("Credit"), 'checked'=>1),
- 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1),
- 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1),
- 't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1),
-);
-
-if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) {
- unset($arrayfields['t.lettering_code']);
-}
-
-if ($search_date_start && empty($search_date_startyear)) {
- $tmparray = dol_getdate($search_date_start);
- $search_date_startyear = $tmparray['year'];
- $search_date_startmonth = $tmparray['mon'];
- $search_date_startday = $tmparray['mday'];
-}
-if ($search_date_end && empty($search_date_endyear)) {
- $tmparray = dol_getdate($search_date_end);
- $search_date_endyear = $tmparray['year'];
- $search_date_endmonth = $tmparray['mon'];
- $search_date_endday = $tmparray['mday'];
-}
-
-if (empty($conf->accounting->enabled)) {
- accessforbidden();
-}
-if ($user->socid > 0) {
- accessforbidden();
-}
-if (empty($user->rights->accounting->mouvements->lire)) {
- accessforbidden();
-}
-
-
-/*
- * Action
- */
-
-if (GETPOST('cancel', 'alpha')) {
- $action = 'list'; $massaction = '';
-}
-if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
- $massaction = '';
-}
-
-$parameters = array('socid'=>$socid);
-$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
-if ($reshook < 0) {
- setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
-}
-
-if (empty($reshook)) {
- include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
-
- 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
- $search_doc_date = '';
- $search_accountancy_code = '';
- $search_accountancy_code_start = '';
- $search_accountancy_code_end = '';
- $search_label_account = '';
- $search_doc_ref = '';
- $search_label_operation = '';
- $search_mvt_num = '';
- $search_direction = '';
- $search_ledger_code = array();
- $search_date_start = '';
- $search_date_end = '';
- $search_date_startyear = '';
- $search_date_startmonth = '';
- $search_date_startday = '';
- $search_date_endyear = '';
- $search_date_endmonth = '';
- $search_date_endday = '';
- $search_date_export_start = '';
- $search_date_export_end = '';
- $search_date_export_startyear = '';
- $search_date_export_startmonth = '';
- $search_date_export_startday = '';
- $search_date_export_endyear = '';
- $search_date_export_endmonth = '';
- $search_date_export_endday = '';
- $search_date_validation_start = '';
- $search_date_validation_end = '';
- $search_date_validation_startyear = '';
- $search_date_validation_startmonth = '';
- $search_date_validation_startday = '';
- $search_date_validation_endyear = '';
- $search_date_validation_endmonth = '';
- $search_date_validation_endday = '';
- $search_debit = '';
- $search_credit = '';
- $search_lettering_code = '';
- $search_not_reconciled = '';
- }
-
- // Must be after the remove filter action, before the export.
- $param = '';
- $filter = array();
-
- if (!empty($search_date_start)) {
- $filter['t.doc_date>='] = $search_date_start;
- $param .= '&search_date_startmonth='.$search_date_startmonth.'&search_date_startday='.$search_date_startday.'&search_date_startyear='.$search_date_startyear;
- }
- if (!empty($search_date_end)) {
- $filter['t.doc_date<='] = $search_date_end;
- $param .= '&search_date_endmonth='.$search_date_endmonth.'&search_date_endday='.$search_date_endday.'&search_date_endyear='.$search_date_endyear;
- }
- if (!empty($search_doc_date)) {
- $filter['t.doc_date'] = $search_doc_date;
- $param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int');
- }
- if (!empty($search_accountancy_code_start)) {
- $filter['t.subledger_account>='] = $search_accountancy_code_start;
- $param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start);
- }
- if (!empty($search_accountancy_code_end)) {
- $filter['t.subledger_account<='] = $search_accountancy_code_end;
- $param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end);
- }
- if (!empty($search_label_account)) {
- $filter['t.label_compte'] = $search_label_account;
- $param .= '&search_label_compte='.urlencode($search_label_account);
- }
- if (!empty($search_mvt_num)) {
- $filter['t.piece_num'] = $search_mvt_num;
- $param .= '&search_mvt_num='.urlencode($search_mvt_num);
- }
- if (!empty($search_doc_ref)) {
- $filter['t.doc_ref'] = $search_doc_ref;
- $param .= '&search_doc_ref='.urlencode($search_doc_ref);
- }
- if (!empty($search_label_operation)) {
- $filter['t.label_operation'] = $search_label_operation;
- $param .= '&search_label_operation='.urlencode($search_label_operation);
- }
- if (!empty($search_direction)) {
- $filter['t.sens'] = $search_direction;
- $param .= '&search_direction='.urlencode($search_direction);
- }
- if (!empty($search_ledger_code)) {
- $filter['t.code_journal'] = $search_ledger_code;
- foreach ($search_ledger_code as $code) {
- $param .= '&search_ledger_code[]='.urlencode($code);
- }
- }
- if (!empty($search_debit)) {
- $filter['t.debit'] = $search_debit;
- $param .= '&search_debit='.urlencode($search_debit);
- }
- if (!empty($search_credit)) {
- $filter['t.credit'] = $search_credit;
- $param .= '&search_credit='.urlencode($search_credit);
- }
- if (!empty($search_lettering_code)) {
- $filter['t.lettering_code'] = $search_lettering_code;
- $param .= '&search_lettering_code='.urlencode($search_lettering_code);
- }
- if (!empty($search_not_reconciled)) {
- $filter['t.reconciled_option'] = $search_not_reconciled;
- $param .= '&search_not_reconciled='.urlencode($search_not_reconciled);
- }
- if (!empty($search_date_export_start)) {
- $filter['t.date_export>='] = $search_date_export_start;
- $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;
- }
- if (!empty($search_date_export_end)) {
- $filter['t.date_export<='] = $search_date_export_end;
- $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;
- }
- if (!empty($search_date_validation_start)) {
- $filter['t.date_validated>='] = $search_date_validation_start;
- $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;
- }
- if (!empty($search_date_validation_end)) {
- $filter['t.date_validated<='] = $search_date_validation_end;
- $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;
- }
-}
-
-if ($action == 'delbookkeeping' && $user->rights->accounting->mouvements->supprimer) {
- $import_key = GETPOST('importkey', 'alpha');
-
- if (!empty($import_key)) {
- $result = $object->deleteByImportkey($import_key);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- }
-
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
- exit;
- }
-}
-if ($action == 'delbookkeepingyearconfirm' && $user->rights->accounting->mouvements->supprimer_tous) {
- $delmonth = GETPOST('delmonth', 'int');
- $delyear = GETPOST('delyear', 'int');
- if ($delyear == -1) {
- $delyear = 0;
- }
- $deljournal = GETPOST('deljournal', 'alpha');
- if ($deljournal == -1) {
- $deljournal = 0;
- }
-
- if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) {
- $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0));
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- } else {
- setEventMessages("RecordDeleted", null, 'mesgs');
- }
-
- // Make a redirect to avoid to launch the delete later after a back button
- header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : ''));
- exit;
- } else {
- setEventMessages("NoRecordDeleted", null, 'warnings');
- }
-}
-if ($action == 'delmouvconfirm' && $user->rights->accounting->mouvements->supprimer) {
- $mvt_num = GETPOST('mvt_num', 'int');
-
- if (!empty($mvt_num)) {
- $result = $object->deleteMvtNum($mvt_num);
- if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- } else {
- setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
- }
-
- header("Location: ".$_SERVER["PHP_SELF"]."?noreset=1".($param ? '&'.$param : ''));
- exit;
- }
-}
-
-
-/*
- * View
- */
-
-$formaccounting = new FormAccounting($db);
-$formfile = new FormFile($db);
-$formother = new FormOther($db);
-$form = new Form($db);
-
-$title_page = $langs->trans("Operations").' - '.$langs->trans("VueByAccountAccounting").' ('.$langs->trans("BookkeepingSubAccount").')';
-
-llxHeader('', $title_page);
-
-// List
-$nbtotalofrecords = '';
-if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
- $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
- if ($nbtotalofrecords < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
- }
-}
-
-$result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
-
-if ($result < 0) {
- setEventMessages($object->error, $object->errors, 'errors');
-}
-
-$num = count($object->lines);
-
-
-if ($action == 'delmouv') {
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?mvt_num='.GETPOST('mvt_num'), $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvtPartial'), 'delmouvconfirm', '', 0, 1);
- print $formconfirm;
-}
-if ($action == 'delbookkeepingyear') {
- $form_question = array();
- $delyear = GETPOST('delyear', 'int');
- $deljournal = GETPOST('deljournal', 'alpha');
-
- if (empty($delyear)) {
- $delyear = dol_print_date(dol_now(), '%Y');
- }
- $month_array = array();
- for ($i = 1; $i <= 12; $i++) {
- $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i));
- }
- $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array');
- $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1);
-
- $form_question['delmonth'] = array(
- 'name' => 'delmonth',
- 'type' => 'select',
- 'label' => $langs->trans('DelMonth'),
- 'values' => $month_array,
- 'default' => ''
- );
- $form_question['delyear'] = array(
- 'name' => 'delyear',
- 'type' => 'select',
- 'label' => $langs->trans('DelYear'),
- 'values' => $year_array,
- 'default' => $delyear
- );
- $form_question['deljournal'] = array(
- 'name' => 'deljournal',
- 'type' => 'other', // We don't use select here, the journal_array is already a select html component
- 'label' => $langs->trans('DelJournal'),
- 'value' => $journal_array,
- 'default' => $deljournal
- );
-
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300);
- print $formconfirm;
-}
-
-
-print '';
-
-// End of page
-llxFooter();
-$db->close();
diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php
index a83a311010d..21b723b003b 100644
--- a/htdocs/accountancy/class/bookkeeping.class.php
+++ b/htdocs/accountancy/class/bookkeeping.class.php
@@ -852,7 +852,8 @@ class BookKeeping extends CommonObject
$sql .= " t.piece_num,";
$sql .= " t.date_creation,";
$sql .= " t.date_export,";
- $sql .= " t.date_validated as date_validation";
+ $sql .= " t.date_validated as date_validation,";
+ $sql .= " t.import_key";
// Manage filter
$sqlwhere = array();
if (count($filter) > 0) {
@@ -947,6 +948,7 @@ class BookKeeping extends CommonObject
$line->date_creation = $this->db->jdate($obj->date_creation);
$line->date_export = $this->db->jdate($obj->date_export);
$line->date_validation = $this->db->jdate($obj->date_validation);
+ $line->import_key = $obj->import_key;
$this->lines[] = $line;
diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php
index f722a716b79..a2718973185 100644
--- a/htdocs/accountancy/class/lettering.class.php
+++ b/htdocs/accountancy/class/lettering.class.php
@@ -33,6 +33,12 @@ include_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
*/
class Lettering extends BookKeeping
{
+ /**
+ * @var BookKeeping[] Bookkeeping cached
+ */
+ public static $bookkeeping_cached = array();
+
+
/**
* letteringThirdparty
*
@@ -119,6 +125,7 @@ class Lettering extends BookKeeping
$ids[$obj2->rowid] = $obj2->rowid;
$ids_fact[] = $obj2->fact_id;
}
+ $this->db->free($resql2);
} else {
$this->errors[] = $this->db->lasterror;
return -1;
@@ -146,6 +153,7 @@ class Lettering extends BookKeeping
while ($obj2 = $this->db->fetch_object($resql2)) {
$ids[$obj2->rowid] = $obj2->rowid;
}
+ $this->db->free($resql2);
} else {
$this->errors[] = $this->db->lasterror;
return -1;
@@ -205,6 +213,7 @@ class Lettering extends BookKeeping
while ($obj2 = $this->db->fetch_object($resql2)) {
$ids[$obj2->rowid] = $obj2->rowid;
}
+ $this->db->free($resql2);
} else {
$this->errors[] = $this->db->lasterror;
return -1;
@@ -216,6 +225,7 @@ class Lettering extends BookKeeping
$result = $this->updateLettering($ids);
}
}
+ $this->db->free($resql);
}
if ($error) {
foreach ($this->errors as $errmsg) {
@@ -230,17 +240,31 @@ class Lettering extends BookKeeping
/**
*
- * @param array $ids ids array
- * @param boolean $notrigger no trigger
- * @return number
+ * @param array $ids ids array
+ * @param boolean $notrigger no trigger
+ * @return int
*/
public function updateLettering($ids = array(), $notrigger = false)
{
$error = 0;
$lettre = 'AAA';
- $sql = "SELECT DISTINCT lettering_code FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE ";
- $sql .= " lettering_code != '' ORDER BY lettering_code DESC limit 1";
+ $sql = "SELECT DISTINCT ab2.lettering_code";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping As ab";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu2 ON bu2.url_id = bu.url_id";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab2 ON ab2.fk_doc = bu2.fk_bank";
+ $sql .= " WHERE ab.rowid IN (" . $this->db->sanitize(implode(',', $ids)) . ")";
+ $sql .= " AND ab.doc_type = 'bank'";
+ $sql .= " AND ab2.doc_type = 'bank'";
+ $sql .= " AND bu.type = 'company'";
+ $sql .= " AND bu2.type = 'company'";
+ $sql .= " AND ab.subledger_account != ''";
+ $sql .= " AND ab2.subledger_account != ''";
+ $sql .= " AND ab.lettering_code IS NULL";
+ $sql .= " AND ab2.lettering_code != ''";
+ $sql .= " ORDER BY ab2.lettering_code DESC";
+ $sql .= " LIMIT 1 ";
$result = $this->db->query($sql);
if ($result) {
@@ -249,13 +273,14 @@ class Lettering extends BookKeeping
if (!empty($obj->lettering_code)) {
$lettre++;
}
+ $this->db->free($result);
} else {
$this->errors[] = 'Error'.$this->db->lasterror();
$error++;
}
$sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE ";
- $sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL";
+ $sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
$result = $this->db->query($sql);
if ($result) {
$obj = $this->db->fetch_object($result);
@@ -263,6 +288,7 @@ class Lettering extends BookKeeping
$this->errors[] = 'Total not exacts '.round(abs($obj->deb), 2).' vs '.round(abs($obj->cred), 2);
$error++;
}
+ $this->db->free($result);
} else {
$this->errors[] = 'Erreur sql'.$this->db->lasterror();
$error++;
@@ -276,8 +302,7 @@ class Lettering extends BookKeeping
$sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
$sql .= " lettering_code='".$this->db->escape($lettre)."'";
$sql .= " , date_lettering = '".$this->db->idate($now)."'"; // todo correct date it's false
- $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL ";
- $this->db->begin();
+ $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND lettering_code IS NULL AND subledger_account != ''";
dol_syslog(get_class($this)."::update", LOG_DEBUG);
$resql = $this->db->query($sql);
@@ -293,11 +318,429 @@ class Lettering extends BookKeeping
dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
}
- $this->db->rollback();
return -1 * $error;
} else {
- $this->db->commit();
return 1;
}
}
+
+ /**
+ *
+ * @param array $ids ids array
+ * @param boolean $notrigger no trigger
+ * @return int
+ */
+ public function deleteLettering($ids, $notrigger = false)
+ {
+ $error = 0;
+
+ $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
+ $sql .= " lettering_code = NULL";
+ $sql .= " , date_lettering = NULL";
+ $sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).")";
+ $sql .= " AND subledger_account != ''";
+
+ dol_syslog(get_class($this)."::update", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $error++;
+ $this->errors[] = "Error ".$this->db->lasterror();
+ }
+
+ // Commit or rollback
+ if ($error) {
+ foreach ($this->errors as $errmsg) {
+ dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
+ $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
+ }
+ return -1 * $error;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Lettering bookkeeping lines all types
+ *
+ * @param array $bookkeeping_ids Lettering specific list of bookkeeping id
+ * @param bool $unlettering Do unlettering
+ * @return int <0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered)
+ */
+ public function bookkeepingLetteringAll($bookkeeping_ids, $unlettering = false)
+ {
+ dol_syslog(__METHOD__ . " - ", LOG_DEBUG);
+
+ $error = 0;
+ $errors = array();
+ $nb_lettering = 0;
+
+ $result = $this->bookkeepingLettering($bookkeeping_ids, 'customer_invoice', $unlettering);
+ if ($result < 0) {
+ $error++;
+ $errors = array_merge($errors, $this->errors);
+ $nb_lettering += abs($result) - 2;
+ } else {
+ $nb_lettering += $result;
+ }
+
+ $result = $this->bookkeepingLettering($bookkeeping_ids, 'supplier_invoice', $unlettering);
+ if ($result < 0) {
+ $error++;
+ $errors = array_merge($errors, $this->errors);
+ $nb_lettering += abs($result) - 2;
+ } else {
+ $nb_lettering += $result;
+ }
+
+ if ($error) {
+ $this->errors = $errors;
+ return -2 - $nb_lettering;
+ } else {
+ return $nb_lettering;
+ }
+ }
+
+ /**
+ * Lettering bookkeeping lines
+ *
+ * @param array $bookkeeping_ids Lettering specific list of bookkeeping id
+ * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
+ * @param bool $unlettering Do unlettering
+ * @return int <0 if error (nb lettered = result -1), 0 if noting to lettering, >0 if OK (nb lettered)
+ */
+ public function bookkeepingLettering($bookkeeping_ids, $type = 'customer_invoice', $unlettering = false)
+ {
+ global $langs;
+
+ $this->errors = array();
+
+ // Clean parameters
+ $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
+ $type = trim($type);
+
+ $error = 0;
+ $nb_lettering = 0;
+ $grouped_lines = $this->getLinkedLines($bookkeeping_ids, $type);
+ foreach ($grouped_lines as $lines) {
+ $group_error = 0;
+ $total = 0;
+ $do_it = !$unlettering;
+ $lettering_code = null;
+ $piece_num_lines = array();
+ $bookkeeping_lines = array();
+ foreach ($lines as $line_infos) {
+ $bookkeeping_lines[$line_infos['id']] = $line_infos['id'];
+ $piece_num_lines[$line_infos['piece_num']] = $line_infos['piece_num'];
+ $total += ($line_infos['credit'] > 0 ? $line_infos['credit'] : -$line_infos['debit']);
+
+ // Check lettering code
+ if ($unlettering) {
+ if (isset($lettering_code) && $lettering_code != $line_infos['lettering_code']) {
+ $this->errors[] = $langs->trans('AccountancyErrorMismatchLetteringCode');
+ $group_error++;
+ break;
+ }
+ if (!isset($lettering_code)) $lettering_code = (string) $line_infos['lettering_code'];
+ if (!empty($line_infos['lettering_code'])) $do_it = true;
+ } elseif (!empty($line_infos['lettering_code'])) $do_it = false;
+ }
+
+ // Check balance amount
+ if (!$group_error && !$unlettering && price2num($total) != 0) {
+ $this->errors[] = $langs->trans('AccountancyErrorMismatchBalanceAmount', $total);
+ $group_error++;
+ }
+
+ // Lettering/Unlettering the group of bookkeeping lines
+ if (!$group_error && $do_it) {
+ if ($unlettering) $result = $this->deleteLettering($bookkeeping_lines);
+ else $result = $this->updateLettering($bookkeeping_lines);
+ if ($result < 0) {
+ $group_error++;
+ } else {
+ $nb_lettering++;
+ }
+ }
+
+ if ($group_error) {
+ $this->errors[] = $langs->trans('AccountancyErrorLetteringBookkeeping', implode(', ', $piece_num_lines));
+ $error++;
+ }
+ }
+
+ if ($error) {
+ return -2 - $nb_lettering;
+ } else {
+ return $nb_lettering;
+ }
+ }
+
+ /**
+ * Lettering bookkeeping lines
+ *
+ * @param array $bookkeeping_ids Lettering specific list of bookkeeping id
+ * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
+ * @return array|int <0 if error otherwise all linked lines by block
+ */
+ public function getLinkedLines($bookkeeping_ids, $type = 'customer_invoice')
+ {
+ global $conf, $langs;
+ $this->errors = array();
+
+ // Clean parameters
+ $bookkeeping_ids = is_array($bookkeeping_ids) ? $bookkeeping_ids : array();
+ $type = trim($type);
+
+ if ($type == 'customer_invoice') {
+ $doc_type = 'customer_invoice';
+ $bank_url_type = 'payment';
+ $payment_element = 'paiement_facture';
+ $fk_payment_element = 'fk_paiement';
+ $fk_element = 'fk_facture';
+ $account_number = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
+ } elseif ($type == 'supplier_invoice') {
+ $doc_type = 'supplier_invoice';
+ $bank_url_type = 'payment_supplier';
+ $payment_element = 'paiementfourn_facturefourn';
+ $fk_payment_element = 'fk_paiementfourn';
+ $fk_element = 'fk_facturefourn';
+ $account_number = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
+ } else {
+ $langs->load('errors');
+ $this->errors[] = $langs->trans('ErrorBadParameters');
+ return -1;
+ }
+
+ $payment_ids = array();
+
+ // Get all payment id from bank lines
+ $sql = "SELECT DISTINCT bu.url_id AS payment_id";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url AS bu ON bu.fk_bank = ab.fk_doc";
+ $sql .= " WHERE ab.doc_type = 'bank'";
+ // $sql .= " AND ab.subledger_account != ''";
+ // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
+ $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
+ if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
+
+ dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->errors[] = "Error " . $this->db->lasterror();
+ return -1;
+ }
+
+ while ($obj = $this->db->fetch_object($resql)) {
+ $payment_ids[$obj->payment_id] = $obj->payment_id;
+ }
+ $this->db->free($resql);
+
+ // Get all payment id from payment lines
+ $sql = "SELECT DISTINCT pe.$fk_payment_element AS payment_id";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe ON pe.$fk_element = ab.fk_doc";
+ $sql .= " WHERE ab.doc_type = '" . $this->db->escape($doc_type) . "'";
+ // $sql .= " AND ab.subledger_account != ''";
+ // $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
+ $sql .= " AND pe.$fk_payment_element IS NOT NULL";
+ if (!empty($bookkeeping_ids)) $sql .= " AND ab.rowid IN (" . $this->db->sanitize(implode(',', $bookkeeping_ids)) . ")";
+
+ dol_syslog(__METHOD__ . " - Get all payment id from bank lines", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->errors[] = "Error " . $this->db->lasterror();
+ return -1;
+ }
+
+ while ($obj = $this->db->fetch_object($resql)) {
+ $payment_ids[$obj->payment_id] = $obj->payment_id;
+ }
+ $this->db->free($resql);
+
+ if (empty($payment_ids)) {
+ return array();
+ }
+
+ // Get all payments linked by group
+ $payment_by_group = $this->getLinkedPaymentByGroup($payment_ids, $type);
+
+ $groups = array();
+ foreach ($payment_by_group as $payment_list) {
+ $lines = array();
+
+ // Get bank lines
+ $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "bank_url AS bu";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = bu.fk_bank";
+ $sql .= " WHERE bu.url_id IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
+ $sql .= " AND bu.type = '" . $this->db->escape($bank_url_type) . "'";
+ $sql .= " AND ab.doc_type = 'bank'";
+ $sql .= " AND ab.subledger_account != ''";
+ $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
+
+ dol_syslog(__METHOD__ . " - Get bank lines", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->errors[] = "Error " . $this->db->lasterror();
+ return -1;
+ }
+
+ while ($obj = $this->db->fetch_object($resql)) {
+ $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
+ }
+ $this->db->free($resql);
+
+ // Get payment lines
+ $sql = "SELECT DISTINCT ab.rowid, ab.piece_num, ab.lettering_code, ab.debit, ab.credit";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping AS ab ON ab.fk_doc = pe.$fk_element";
+ $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_list)) . ")";
+ $sql .= " AND ab.doc_type = '" . $this->db->escape($doc_type) . "'";
+ $sql .= " AND ab.subledger_account != ''";
+ $sql .= " AND ab.numero_compte = '" . $this->db->escape($account_number) . "'";
+
+ dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->errors[] = "Error " . $this->db->lasterror();
+ return -1;
+ }
+
+ while ($obj = $this->db->fetch_object($resql)) {
+ $lines[$obj->rowid] = array('id' => $obj->rowid, 'piece_num' => $obj->piece_num, 'lettering_code' => $obj->lettering_code, 'debit' => $obj->debit, 'credit' => $obj->credit);
+ }
+ $this->db->free($resql);
+
+ if (!empty($lines)) {
+ $groups[] = $lines;
+ }
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Linked payment by group
+ *
+ * @param array $payment_ids list of payment id
+ * @param string $type Type of bookkeeping type to lettering ('customer_invoice' or 'supplier_invoice')
+ * @return array|int <0 if error otherwise all linked lines by block
+ */
+ public function getLinkedPaymentByGroup($payment_ids, $type)
+ {
+ global $langs;
+
+ // Clean parameters
+ $payment_ids = is_array($payment_ids) ? $payment_ids : array();
+ $type = trim($type);
+
+ if (empty($payment_ids)) {
+ return array();
+ }
+
+ if ($type == 'customer_invoice') {
+ $payment_element = 'paiement_facture';
+ $fk_payment_element = 'fk_paiement';
+ $fk_element = 'fk_facture';
+ } elseif ($type == 'supplier_invoice') {
+ $payment_element = 'paiementfourn_facturefourn';
+ $fk_payment_element = 'fk_paiementfourn';
+ $fk_element = 'fk_facturefourn';
+ } else {
+ $langs->load('errors');
+ $this->errors[] = $langs->trans('ErrorBadParameters');
+ return -1;
+ }
+
+ // Get payment lines
+ $sql = "SELECT DISTINCT pe2.$fk_payment_element, pe2.$fk_element";
+ $sql .= " FROM " . MAIN_DB_PREFIX . "$payment_element AS pe";
+ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "$payment_element AS pe2 ON pe2.$fk_element = pe.$fk_element";
+ $sql .= " WHERE pe.$fk_payment_element IN (" . $this->db->sanitize(implode(',', $payment_ids)) . ")";
+
+ dol_syslog(__METHOD__ . " - Get payment lines", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $this->errors[] = "Error " . $this->db->lasterror();
+ return -1;
+ }
+
+ $current_payment_ids = array();
+ $payment_by_element = array();
+ $element_by_payment = array();
+ while ($obj = $this->db->fetch_object($resql)) {
+ $current_payment_ids[$obj->$fk_payment_element] = $obj->$fk_payment_element;
+ $element_by_payment[$obj->$fk_payment_element][$obj->$fk_element] = $obj->$fk_element;
+ $payment_by_element[$obj->$fk_element][$obj->$fk_payment_element] = $obj->$fk_payment_element;
+ }
+ $this->db->free($resql);
+
+ if (count(array_diff($payment_ids, $current_payment_ids))) {
+ return $this->getLinkedPaymentByGroup($current_payment_ids, $type);
+ }
+
+ return $this->getGroupElements($payment_by_element, $element_by_payment);
+ }
+
+ /**
+ * Get payment ids grouped by payment id and element id in common
+ *
+ * @param array $payment_by_element List of payment ids by element id
+ * @param array $element_by_payment List of element ids by payment id
+ * @param int $element_id Element Id (used for recursive function)
+ * @param array $current_group Current group (used for recursive function)
+ * @return array List of payment ids grouped by payment id and element id in common
+ */
+ public function getGroupElements(&$payment_by_element, &$element_by_payment, $element_id = 0, &$current_group = array())
+ {
+ $grouped_payments = array();
+ if ($element_id > 0 && !isset($payment_by_element[$element_id])) {
+ // Return if specific element id not found
+ return $grouped_payments;
+ }
+
+ if ($element_id == 0) {
+ // Save list when is the begin of recursive function
+ $save_payment_by_element = $payment_by_element;
+ $save_element_by_payment = $element_by_payment;
+ }
+
+ do {
+ // Get current element id, get this payment id list and delete the entry
+ $current_element_id = $element_id > 0 ? $element_id : array_keys($payment_by_element)[0];
+ $payment_ids = $payment_by_element[$current_element_id];
+ unset($payment_by_element[$current_element_id]);
+
+ foreach ($payment_ids as $payment_id) {
+ // Continue if payment id in not found
+ if (!isset($element_by_payment[$payment_id])) continue;
+
+ // Set the payment in the current group
+ $current_group[$payment_id] = $payment_id;
+
+ // Get current element ids, get this payment id list and delete the entry
+ $element_ids = $element_by_payment[$payment_id];
+ unset($element_by_payment[$payment_id]);
+
+ // Set payment id on the current group for each element id of the payment
+ foreach ($element_ids as $id) {
+ $this->getGroupElements($payment_by_element, $element_by_payment, $id, $current_group);
+ }
+ }
+
+ if ($element_id == 0) {
+ // Save current group and reset the current group when is the begin of recursive function
+ $grouped_payments[] = $current_group;
+ $current_group = array();
+ }
+ } while (!empty($payment_by_element) && $element_id == 0);
+
+ if ($element_id == 0) {
+ // Restore list when is the begin of recursive function
+ $payment_by_element = $save_payment_by_element;
+ $element_by_payment = $save_element_by_payment;
+ }
+
+ return $grouped_payments;
+ }
}
diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php
index 4841b8bf171..8a02ac3849a 100644
--- a/htdocs/accountancy/journal/bankjournal.php
+++ b/htdocs/accountancy/journal/bankjournal.php
@@ -665,6 +665,8 @@ if (!$error && $action == 'writebookkeeping') {
// Line into thirdparty account
foreach ($tabtp[$key] as $k => $mt) {
if ($mt) {
+ $lettering = false;
+
$reflabel = '';
if (!empty($val['lib'])) {
$reflabel .= dol_string_nohtmltag($val['lib']).($val['soclib'] ? " - " : "");
@@ -693,11 +695,13 @@ if (!$error && $action == 'writebookkeeping') {
$bookkeeping->date_creation = $now;
if ($tabtype[$key] == 'payment') { // If payment is payment of customer invoice, we get ref of invoice
+ $lettering = true;
$bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp
$bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction
$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER;
$bookkeeping->label_compte = $accountingaccountcustomer->label;
} elseif ($tabtype[$key] == 'payment_supplier') { // If payment is payment of supplier invoice, we get ref of invoice
+ $lettering = true;
$bookkeeping->subledger_account = $k; // For payment, the subledger account is stored as $key of $tabtp
$bookkeeping->subledger_label = $tabcompany[$key]['name']; // $tabcompany is defined only if we are sure there is 1 thirdparty for the bank transaction
$bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER;
@@ -780,6 +784,12 @@ if (!$error && $action == 'writebookkeeping') {
$errorforline++;
setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
}
+ } else {
+ if ($lettering && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) {
+ require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
+ $lettering_static = new Lettering($db);
+ $nb_lettering = $lettering_static->bookkeepingLetteringAll(array($bookkeeping->id));
+ }
}
}
}
diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php
index 8b1ac0d3de3..7c0a8b90f7d 100644
--- a/htdocs/accountancy/journal/purchasesjournal.php
+++ b/htdocs/accountancy/journal/purchasesjournal.php
@@ -377,6 +377,12 @@ if ($action == 'writebookkeeping') {
$errorforinvoice[$key] = 'other';
setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
}
+ } else {
+ if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) {
+ require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
+ $lettering_static = new Lettering($db);
+ $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id), 'supplier_invoice');
+ }
}
}
}
diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php
index 7a5ccd79b21..7cc7f0effbc 100644
--- a/htdocs/accountancy/journal/sellsjournal.php
+++ b/htdocs/accountancy/journal/sellsjournal.php
@@ -390,6 +390,12 @@ if ($action == 'writebookkeeping') {
$errorforinvoice[$key] = 'other';
setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
}
+ } else {
+ if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) {
+ require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php';
+ $lettering_static = new Lettering($db);
+ $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id), 'customer_invoice');
+ }
}
}
}
diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang
index c66e0295bfa..568263b0ca5 100644
--- a/htdocs/langs/en_US/accountancy.lang
+++ b/htdocs/langs/en_US/accountancy.lang
@@ -396,6 +396,21 @@ Range=Range of accounting account
Calculated=Calculated
Formula=Formula
+## Reconcile
+Unlettering=Unreconcile
+AccountancyNoLetteringModified=No reconcile modified
+AccountancyOneLetteringModifiedSuccessfully=One reconcile successfully modified
+AccountancyLetteringModifiedSuccessfully=%s reconcile successfully modified
+AccountancyNoUnletteringModified=No unreconcile modified
+AccountancyOneUnletteringModifiedSuccessfully=One unreconcile successfully modified
+AccountancyUnletteringModifiedSuccessfully=%s unreconcile successfully modified
+
+## Confirm box
+ConfirmMassUnlettering=Bulk Unreconcile confirmation
+ConfirmMassUnletteringQuestion=Are you sure you want to Unreconcile the %s selected record(s)?
+ConfirmMassDeleteBookkeepingWriting=Bulk Delete confirmation
+ConfirmMassDeleteBookkeepingWritingQuestion=This will delete the transaction from the accounting (all lines related to the same transaction will be deleted) Are you sure you want to delete the %s selected record(s)?
+
## Error
SomeMandatoryStepsOfSetupWereNotDone=Some mandatory steps of setup was not done, please complete them
ErrorNoAccountingCategoryForThisCountry=No accounting account group available for country %s (See Home - Setup - Dictionaries)
@@ -408,6 +423,9 @@ Binded=Lines bound
ToBind=Lines to bind
UseMenuToSetBindindManualy=Lines not yet bound, use menu %s to make the binding manually
SorryThisModuleIsNotCompatibleWithTheExperimentalFeatureOfSituationInvoices=Sorry this module is not compatible with the experimental feature of situation invoices
+AccountancyErrorMismatchLetterCode=Mismatch in reconcile code
+AccountancyErrorMismatchBalanceAmount=The balance (%s) is not equal to 0
+AccountancyErrorLetteringBookkeeping=Errors have occurred concerning the transactions: %s
## Import
ImportAccountingEntries=Accounting entries