25require 
'../../main.inc.php';
 
   26require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
 
   27require_once DOL_DOCUMENT_ROOT.
'/core/lib/accounting.lib.php';
 
   28require_once DOL_DOCUMENT_ROOT.
'/core/class/fiscalyear.class.php';
 
   29require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formaccounting.class.php';
 
   30require_once DOL_DOCUMENT_ROOT.
'/accountancy/class/bookkeeping.class.php';
 
   33$langs->loadLangs(array(
"compta", 
"bills", 
"other", 
"accountancy"));
 
   35$action = 
GETPOST(
'action', 
'aZ09');
 
   36$confirm = 
GETPOST(
'confirm', 
'aZ09');
 
   37$fiscal_period_id = 
GETPOST(
'fiscal_period_id', 
'int');
 
   38$validatemonth = 
GETPOST(
'validatemonth', 
'int');
 
   39$validateyear = 
GETPOST(
'validateyear', 
'int');
 
   42if (!isModEnabled(
'accounting')) {
 
   45if ($user->socid > 0) {
 
   48if (!$user->hasRight(
'accounting', 
'fiscalyear', 
'write')) {
 
   53$hookmanager->initHooks(array(
'accountancyclosure'));
 
   58$fiscal_periods = $object->getFiscalPeriods();
 
   59if (!is_array($fiscal_periods)) {
 
   64$active_fiscal_periods = array();
 
   65$first_active_fiscal_period = 
null;
 
   66$last_fiscal_period = 
null;
 
   67$current_fiscal_period = 
null;
 
   68$next_fiscal_period = 
null;
 
   69$next_active_fiscal_period = 
null;
 
   70if (is_array($fiscal_periods)) {
 
   71  foreach ($fiscal_periods as $fiscal_period) {   
 
   72    if (empty($first_active_fiscal_period) && empty($fiscal_period[
'status'])) {
 
   73      $first_active_fiscal_period = $fiscal_period;
 
   75    if (empty($fiscal_period[
'status'])) {  
 
   76      $active_fiscal_periods[] = $fiscal_period;
 
   78    if (isset($current_fiscal_period)) {  
 
   79      if (!isset($next_fiscal_period)) {
 
   80        $next_fiscal_period = $fiscal_period;
 
   82      if (!isset($next_active_fiscal_period) && empty($fiscal_period[
'status'])) {
 
   83        $next_active_fiscal_period = $fiscal_period;
 
   86      if ($fiscal_period_id == $fiscal_period[
'id'] || (empty($fiscal_period_id) && $fiscal_period[
'date_start'] <= $now && $now <= $fiscal_period[
'date_end'])) {
 
   87        $current_fiscal_period = $fiscal_period;
 
   89        $last_fiscal_period = $fiscal_period; 
 
   96if (empty($current_fiscal_period) && !empty($first_active_fiscal_period)) {
 
   97  $current_fiscal_period = $first_active_fiscal_period;
 
   98  $last_fiscal_period = 
null;
 
   99  $foundcurrent = 
false;
 
  100  foreach ($fiscal_periods as $fiscal_period) {   
 
  102      $next_fiscal_period = $fiscal_period;
 
  105    if ($fiscal_period[
'id'] == $current_fiscal_period[
'id']) {
 
  106      $foundcurrent = 
true;
 
  108    if (!$foundcurrent) {
 
  109      $last_fiscal_period = $fiscal_period;
 
  114$accounting_groups_used_for_balance_sheet_account = array_filter(array_map(
'trim', explode(
',', 
getDolGlobalString(
'ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_BALANCE_SHEET_ACCOUNT'))), 
'strlen');
 
  115$accounting_groups_used_for_income_statement = array_filter(array_map(
'trim', explode(
',', 
getDolGlobalString(
'ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT'))), 
'strlen');
 
  122$parameters = array(
'fiscal_periods' => $fiscal_periods, 
'last_fiscal_period' => $last_fiscal_period, 
'current_fiscal_period' => $current_fiscal_period, 
'next_fiscal_period' => $next_fiscal_period);
 
  123$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action); 
 
  128if (empty($reshook)) {
 
  129  if (isset($current_fiscal_period) && $user->hasRight(
'accounting', 
'fiscalyear', 
'write')) {
 
  130    if ($action == 
'confirm_step_1' && $confirm == 
"yes") {
 
  134      $result = $object->validateMovementForFiscalPeriod($date_start, $date_end);
 
  136        setEventMessages($langs->trans(
"AllMovementsWereRecordedAsValidated"), 
null, 
'mesgs');
 
  138        header(
"Location: " . $_SERVER[
'PHP_SELF'] . (isset($current_fiscal_period) ? 
'?fiscal_period_id=' . $current_fiscal_period[
'id'] : 
''));
 
  141        setEventMessages($langs->trans(
"NotAllMovementsCouldBeRecordedAsValidated"), 
null, 
'errors');
 
  145    } elseif ($action == 
'confirm_step_2' && $confirm == 
"yes") {
 
  146      $new_fiscal_period_id = 
GETPOST(
'new_fiscal_period_id', 
'int');
 
  147      $separate_auxiliary_account = 
GETPOST(
'separate_auxiliary_account', 
'aZ09');
 
  148      $generate_bookkeeping_records = 
GETPOST(
'generate_bookkeeping_records', 
'aZ09');
 
  151      if ($generate_bookkeeping_records) {
 
  152        if (!
getDolGlobalString(
'ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_BALANCE_SHEET_ACCOUNT')) {
 
  154          setEventMessages($langs->trans(
"ErrorAccountingClosureSetupNotComplete"), 
null, 
'errors');
 
  155        } elseif (!
getDolGlobalString(
'ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT')) {
 
  157          setEventMessages($langs->trans(
"ErrorAccountingClosureSetupNotComplete"), 
null, 
'errors');
 
  162        $result = $object->closeFiscalPeriod($current_fiscal_period[
'id'], $new_fiscal_period_id, $separate_auxiliary_account, $generate_bookkeeping_records);
 
  166          setEventMessages($langs->trans(
"AccountancyClosureCloseSuccessfully"), 
null, 
'mesgs');
 
  168          header(
"Location: " . $_SERVER[
'PHP_SELF'] . (isset($current_fiscal_period) ? 
'?fiscal_period_id=' . $current_fiscal_period[
'id'] : 
''));
 
  172    } elseif ($action == 
'confirm_step_3' && $confirm == 
"yes") {
 
  173      $inventory_journal_id = 
GETPOST(
'inventory_journal_id', 
'int');
 
  174      $new_fiscal_period_id = 
GETPOST(
'new_fiscal_period_id', 
'int');
 
  178      $result = $object->insertAccountingReversal($current_fiscal_period[
'id'], $inventory_journal_id, $new_fiscal_period_id, $date_start, $date_end);
 
  182        setEventMessages($langs->trans(
"AccountancyClosureInsertAccountingReversalSuccessfully"), 
null, 
'mesgs');
 
  184        header(
"Location: " . $_SERVER[
'PHP_SELF'] . (isset($current_fiscal_period) ? 
'?fiscal_period_id=' . $current_fiscal_period[
'id'] : 
''));
 
  196$form = 
new Form($db);
 
  199$title = $langs->trans(
'Closure');
 
  201$help_url =
'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilité_en_Partie_Double#Cl.C3.B4ture_annuelle';
 
  207if (isset($current_fiscal_period)) {
 
  208  if ($action == 
'step_1') {
 
  209    $form_question = array();
 
  211    $form_question[
'date_start'] = array(
 
  212      'name' => 
'date_start',
 
  214      'label' => $langs->trans(
'DateStart'),
 
  215      'value' => $current_fiscal_period[
'date_start']
 
  217    $form_question[
'date_end'] = array(
 
  218      'name' => 
'date_end',
 
  220      'label' => $langs->trans(
'DateEnd'),
 
  221      'value' => $current_fiscal_period[
'date_end']
 
  224    $formconfirm = $form->formconfirm(
 
  225      $_SERVER[
"PHP_SELF"] . 
'?fiscal_period_id=' . $current_fiscal_period[
'id'],
 
  226      $langs->trans(
'ValidateMovements'),
 
  227      $langs->trans(
'DescValidateMovements', $langs->transnoentitiesnoconv(
"RegistrationInAccounting")),
 
  234  } elseif ($action == 
'step_2') {
 
  235    $form_question = array();
 
  237    $fiscal_period_arr = array();
 
  238    foreach ($active_fiscal_periods as $info) {
 
  239      $fiscal_period_arr[$info[
'id']] = $info[
'label'];
 
  241    $form_question[
'new_fiscal_period_id'] = array(
 
  242      'name' => 
'new_fiscal_period_id',
 
  244      'label' => $langs->trans(
'AccountancyClosureStep3NewFiscalPeriod'),
 
  245      'values' => $fiscal_period_arr,
 
  246      'default' => isset($next_active_fiscal_period) ? $next_active_fiscal_period[
'id'] : 
'',
 
  248    $form_question[
'generate_bookkeeping_records'] = array(
 
  249      'name' => 
'generate_bookkeeping_records',
 
  250      'type' => 
'checkbox',
 
  251      'label' => $langs->trans(
'AccountancyClosureGenerateClosureBookkeepingRecords'),
 
  254    $form_question[
'separate_auxiliary_account'] = array(
 
  255      'name' => 
'separate_auxiliary_account',
 
  256      'type' => 
'checkbox',
 
  257      'label' => $langs->trans(
'AccountancyClosureSeparateAuxiliaryAccounts'),
 
  261    $formconfirm = $form->formconfirm(
 
  262      $_SERVER[
"PHP_SELF"] . 
'?fiscal_period_id=' . $current_fiscal_period[
'id'],
 
  263      $langs->trans(
'AccountancyClosureClose'),
 
  264      $langs->trans(
'AccountancyClosureConfirmClose'),
 
  271  } elseif ($action == 
'step_3') {
 
  272    $form_question = array();
 
  274    $form_question[
'inventory_journal_id'] = array(
 
  275      'name' => 
'inventory_journal_id',
 
  277      'label' => $langs->trans(
'InventoryJournal'),
 
  278      'value' => $formaccounting->select_journal(0, 
"inventory_journal_id", 8, 1, 0, 0)
 
  280    $fiscal_period_arr = array();
 
  281    foreach ($active_fiscal_periods as $info) {
 
  282      $fiscal_period_arr[$info[
'id']] = $info[
'label'];
 
  284    $form_question[
'new_fiscal_period_id'] = array(
 
  285      'name' => 
'new_fiscal_period_id',
 
  287      'label' => $langs->trans(
'AccountancyClosureStep3NewFiscalPeriod'),
 
  288      'values' => $fiscal_period_arr,
 
  289      'default' => isset($next_active_fiscal_period) ? $next_active_fiscal_period[
'id'] : 
'',
 
  291    $form_question[
'date_start'] = array(
 
  292      'name' => 
'date_start',
 
  294      'label' => $langs->trans(
'DateStart'),
 
  297    $form_question[
'date_end'] = array(
 
  298      'name' => 
'date_end',
 
  300      'label' => $langs->trans(
'DateEnd'),
 
  301      'value' => $current_fiscal_period[
'date_end']
 
  304    $formconfirm = $form->formconfirm(
 
  305      $_SERVER[
"PHP_SELF"] . 
'?fiscal_period_id=' . $current_fiscal_period[
'id'],
 
  306      $langs->trans(
'AccountancyClosureAccountingReversal'),
 
  307      $langs->trans(
'AccountancyClosureConfirmAccountingReversal'),
 
  318$parameters = array(
'formConfirm' => $formconfirm, 
'fiscal_periods' => $fiscal_periods, 
'last_fiscal_period' => $last_fiscal_period, 
'current_fiscal_period' => $current_fiscal_period, 
'next_fiscal_period' => $next_fiscal_period);
 
  319$reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action); 
 
  320if (empty($reshook)) {
 
  321  $formconfirm .= $hookmanager->resPrint;
 
  322} elseif ($reshook > 0) {
 
  323  $formconfirm = $hookmanager->resPrint;
 
  329$fiscal_period_nav_text = $langs->trans(
"FiscalPeriod");
 
  331$fiscal_period_nav_text .= 
' <a href="' . (isset($last_fiscal_period) ? $_SERVER[
"PHP_SELF"] . 
'?fiscal_period_id=' . $last_fiscal_period[
'id'] : 
'#" class="disabled') . 
'">' . 
img_previous() . 
'</a>';
 
  332$fiscal_period_nav_text .= 
' <a href="' . (isset($next_fiscal_period) ? $_SERVER[
"PHP_SELF"] . 
'?fiscal_period_id=' . $next_fiscal_period[
'id'] : 
'#" class="disabled') . 
'">' . 
img_next() . 
'</a>';
 
  333if (!empty($current_fiscal_period)) {
 
  334  $fiscal_period_nav_text .= $current_fiscal_period[
'label'].
'  (' . (isset($current_fiscal_period) ? 
dol_print_date($current_fiscal_period[
'date_start'], 
'day') . 
' - ' . 
dol_print_date($current_fiscal_period[
'date_end'], 
'day') . 
')' : 
'');
 
  337print 
load_fiche_titre($langs->trans(
"Closure") . 
" - " . $fiscal_period_nav_text, 
'', 
'title_accountancy');
 
  339if (empty($current_fiscal_period)) {
 
  340  print $langs->trans(
'ErrorNoFiscalPeriodActiveFound');
 
  344  $head[0][0] = DOL_URL_ROOT . 
'/accountancy/closure/index.php?fiscal_period_id=' . $current_fiscal_period[
'id'];
 
  345  $head[0][1] = $langs->trans(
"AccountancyClosureStep1");
 
  346  $head[0][2] = 
'step1';
 
  349  print 
'<span class="opacitymedium">' . $langs->trans(
"AccountancyClosureStep1Desc") . 
'</span><br>';
 
  351  $count_by_month = $object->getCountByMonthForFiscalPeriod($current_fiscal_period[
'date_start'], $current_fiscal_period[
'date_end']);
 
  352  if (!is_array($count_by_month)) {
 
  356  if (empty($count_by_month[
'total'])) {
 
  357    $buttonvalidate = 
'<a class="butActionRefused classfortooltip" href="#">' . $langs->trans(
"ValidateMovements") . 
'</a>';
 
  359    $buttonvalidate = 
'<a class="butAction" href="' . $_SERVER[
"PHP_SELF"] . 
'?action=step_1&fiscal_period_id=' . $current_fiscal_period[
'id'] . 
'">' . $langs->trans(
"ValidateMovements") . 
'</a>';
 
  361  print_barre_liste($langs->trans(
"OverviewOfMovementsNotValidated"), 
'', 
'', 
'', 
'', 
'', 
'', -1, 
'', 
'', 0, $buttonvalidate, 
'', 0, 1, 0);
 
  363  print 
'<div class="div-table-responsive-no-min">';
 
  364  print 
'<table class="noborder centpercent">';
 
  366  print 
'<tr class="liste_titre">';
 
  367  $nb_years = is_array($count_by_month[
'list']) ? count($count_by_month[
'list']) : 0;
 
  369    print 
'<td class="right">' . $langs->trans(
"Year") . 
'</td>';
 
  371  for ($i = 1; $i <= 12; $i++) {
 
  372    print 
'<td class="right">' . $langs->trans(
'MonthShort' . str_pad($i, 2, 
'0', STR_PAD_LEFT)) . 
'</td>';
 
  374  print 
'<td class="right"><b>' . $langs->trans(
"Total") . 
'</b></td>';
 
  377  if (is_array($count_by_month[
'list'])) {
 
  378    foreach ($count_by_month[
'list'] as $info) {
 
  379      print 
'<tr class="oddeven">';
 
  381        print 
'<td class="right">' . $info[
'year'] . 
'</td>';
 
  383      for ($i = 1; $i <= 12; $i++) {
 
  384        print 
'<td class="right">' . ((int) $info[
'count'][$i]) . 
'</td>';
 
  386      print 
'<td class="right"><b>' . $info[
'total'] . 
'</b></td></tr>';
 
  395  $head[0][0] = DOL_URL_ROOT . 
'/accountancy/closure/index.php?fiscal_period_id=' . $current_fiscal_period[
'id'];
 
  396  $head[0][1] = $langs->trans(
"AccountancyClosureStep2");
 
  397  $head[0][2] = 
'step2';
 
  402  if (empty($count_by_month[
'total']) && empty($current_fiscal_period[
'status'])) {
 
  403    $button = 
'<a class="butAction" href="' . $_SERVER[
"PHP_SELF"] . 
'?action=step_2&fiscal_period_id=' . $current_fiscal_period[
'id'] . 
'">' . $langs->trans(
"AccountancyClosureClose") . 
'</a>';
 
  405    $button = 
'<a class="butActionRefused classfortooltip" href="#" title="This fiscal period already has the status Closed. Feature disabled.">' . $langs->trans(
"AccountancyClosureClose") . 
'</a>';
 
  407  print_barre_liste(
'', 
'', 
'', 
'', 
'', 
'', 
'', -1, 
'', 
'', 0, $button, 
'', 0, 1, 0);
 
  411  $head[0][0] = DOL_URL_ROOT . 
'/accountancy/closure/index.php?fiscal_period_id=' . $current_fiscal_period[
'id'];
 
  412  $head[0][1] = $langs->trans(
"AccountancyClosureStep3");
 
  413  $head[0][2] = 
'step3';
 
  418  if (empty($current_fiscal_period[
'status'])) {
 
  419    $button = 
'<a class="butActionRefused classfortooltip" href="#">' . $langs->trans(
"AccountancyClosureAccountingReversal") . 
'</a>';
 
  421    $button = 
'<a class="butAction" href="' . $_SERVER[
"PHP_SELF"] . 
'?action=step_3&fiscal_period_id=' . $current_fiscal_period[
'id'] . 
'">' . $langs->trans(
"AccountancyClosureAccountingReversal") . 
'</a>';
 
  423  print_barre_liste(
'', 
'', 
'', 
'', 
'', 
'', 
'', -1, 
'', 
'', 0, $button, 
'', 0, 1, 0);
 
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Class to manage Ledger (General Ledger and Subledger)
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_previous($titlealt='default', $moreatt='')
Show previous logo.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_next($titlealt='default', $moreatt='')
Show next logo.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.