# Dialup/VPN functions
#
#

use Dv;
use Finance;
use Fees;
use Dv_Sessions;
use Shedule;
use Tariffs;
use Nas;
use Log;
use POSIX;

my $Dv       = Dv->new($db, $admin, \%conf);
my $fees     = Fees->new($db, $admin, \%conf);
my $payments = Payments->new($db, $admin, \%conf);
my $tariffs  = Tariffs->new($db, \%conf, $admin);
my $sessions = Dv_Sessions->new($db, $admin, \%conf);
my $Nas      = Nas->new($db, \%conf);
$Log         = Log->new($db, \%conf);

my %FORM_BASE     = ();
my %TRAFFIC_NAMES = ();
my @service_status_colors = ("$_COLORS[9]", "$_COLORS[6]", '#808080', '#0000FF', '#FF8000', '#009999');
my @service_status = ("$_ENABLE", "$_DISABLE", "$_NOT_ACTIVE", "$_HOLD_UP", "$_DISABLE: $_NON_PAYMENT", "$ERR_SMALL_DEPOSIT");

#*******************************************************************
# Delete user from module
# dv_user_del()
#*******************************************************************
sub dv_user_del {
  my ($uid, $attr) = @_;

  $Dv->{UID} = $uid;
  $Dv->del({ UID => $uid });
  $Log->log_del({ LOGIN => $attr->{LOGIN} });

  return 0;
}

#*******************************************************************
# Change user variant form
# form_chg_vid()
#*******************************************************************
sub dv_chg_tp {
  my ($attr) = @_;

  my $user;
  if (defined($attr->{USER_INFO})) {
    $user = $attr->{USER_INFO};
    $Dv   = $Dv->info($user->{UID});
    if ($Dv->{TOTAL} < 1) {
      $html->message('info', $_INFO, "$_NOT_ACTIVE");
      return 0;
    }
  }
  else {
    $html->message('err', $_ERROR, "$_USER_NOT_EXIST");
    return 0;
  }

  if (!$permissions{0}{10}) {
    $html->message('err', $_ERROR, "$ERR_ACCESS_DENY");
    return 0;
  }

  my $TARIF_PLAN = $FORM{tarif_plan} || $_DEFAULT_TARIF_PLAN;
  my $period     = $FORM{period}     || 0;
  my $Shedule = Shedule->new($db, $admin, \%conf);

  #Get next period
  if (
       $Dv->{MONTH_ABON} > 0
    && !$Dv->{STATUS}
    && !$users->{DISABLE}
    && ( $users->{DEPOSIT} + $users->{CREDIT} > 0
      || $Dv->{POSTPAID_ABON}
      || $Dv->{PAYMENT_TYPE} == 1)
  )
  {

    if ($users->{ACTIVATE} ne '0000-00-00') {
      my ($Y, $M, $D) = split(/-/, $users->{ACTIVATE}, 3);
      $M--;
      $Dv->{ABON_DATE} = strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, $M, ($Y - 1900), 0, 0, 0) + 31 * 86400 + (($conf{START_PERIOD_DAY}) ? $conf{START_PERIOD_DAY} * 86400 : 0))));
    }
    else {
      my ($Y, $M, $D) = split(/-/, $DATE, 3);
      $M++;
      if ($M == 13) {
        $M = 1;
        $Y++;
      }

      if ($conf{START_PERIOD_DAY}) {
        $D = $conf{START_PERIOD_DAY};
      }
      else {
        $D = '01';
      }
      $Dv->{ABON_DATE} = sprintf("%d-%02d-%02d", $Y, $M, $D);
    }
  }

  if ($FORM{set}) {
    if (!$permissions{0}{4}) {
      $html->message('err', $_ERROR, "$ERR_ACCESS_DENY");
      return 0;
    }

    if ($period > 0) {
      my ($year, $month, $day);
      if ($period == 1) {
        ($year, $month, $day) = split(/-/, $Dv->{ABON_DATE}, 3);
      }
      else {
        ($year, $month, $day) = split(/-/, $FORM{DATE}, 3);
      }

      my $seltime = POSIX::mktime(0, 0, 0, $day, ($month - 1), ($year - 1900));

      if ($seltime <= time()) {
        $html->message('info', $_INFO, "$ERR_WRONG_DATA " . $html->color_mark("$_DATE: $year-$month-$day", $_COLORS[6]));
        return 0;
      }
      elsif ($FORM{date_D} > ($month != 2 ? (($month % 2) ^ ($month > 7)) + 30 : (!($year % 400) || !($year % 4) && ($year % 25) ? 29 : 28))) {
        $html->message('info', $_INFO, "$ERR_WRONG_DATA " . $html->color_mark("$_DATE: $year-$month-$day", $_COLORS[6]));
        return 0;
      }

      $Shedule->add(
        {
          UID          => $Dv->{UID},
          TYPE         => 'tp',
          ACTION       => $FORM{TP_ID},
          D            => $day,
          M            => $month,
          Y            => $year,
          MODULE       => 'Dv',
          COMMENTS     => "$_FROM: $Dv->{TP_ID}:$Dv->{TP_NAME}",
          ADMIN_ACTION => 1
        }
      );

      if ($Shedule->{errno}) {
        $html->message('err', $_ERROR, "[$Shedule->{errno}] $err_strs{$Shedule->{errno}}");
      }
      else {
        $html->message('info', $_CHANGED, "$_TARIF_PLAN $_CHANGED");
        $Dv->info($Dv->{UID});
      }
    }
    else {
      $Dv->change({%FORM});

      if ($Dv->{errno}) {
        $html->message('err', $_ERROR, "[$Dv->{errno}] $err_strs{$Dv->{errno}}");
      }
      else {
        #Take fees
        if (!$Dv->{STATUS} && $FORM{GET_ABON}) {
          dv_get_month_fee($Dv);
        }
        $html->message('info', $_CHANGED, "$_TARIF_PLAN $_CHANGED");
        $Dv->info($Dv->{UID});
      }
    }
  }
  elsif ($FORM{del}) {
    $Shedule->del(
      {
        UID => $Dv->{UID},
        ID  => $FORM{SHEDULE_ID}
      }
    );

    $html->message('info', $_DELETED, "$_DELETED [$FORM{SHEDULE_ID}]");
  }

  $Shedule->info(
    {
      UID      => $Dv->{UID},
      TYPE     => 'tp',
      DESCRIBE => "$message\n$_FROM: '$FORM{date_y}-$FORM{date_m}-$FORM{date_d}'",
      MODULE   => 'Dv'
    }
  );

  if ($Shedule->{TOTAL} > 0 && !$conf{DV_TP_MULTISHEDULE}) {
    $table = $html->table(
      {
        width      => '100%',
        caption    => "$_SHEDULE",
        cols_align => [ 'left', 'left' ],
        rows       => [ [ "$_TARIF_PLAN:", "$Shedule->{ACTION}" ], [ "$_DATE:", "$Shedule->{D}-$Shedule->{M}-$Shedule->{Y}" ], [ "$_ADMIN:", "$Shedule->{ADMIN_NAME}" ], [ "$_ADDED:", "$Shedule->{DATE}" ], [ "ID:", "$Shedule->{SHEDULE_ID}" ] ]
      }
    );
    $tariffs->{TARIF_PLAN_SEL} = $table->show() . $html->form_input('SHEDULE_ID', "$Shedule->{SHEDULE_ID}", { TYPE => 'HIDDEN' });
    $tariffs->{ACTION}         = 'del';
    $tariffs->{LNG_ACTION}     = $_DEL;
  }
  else {
    my $tp_list = $tariffs->list({ MODULE => 'Dv', DOMAIN_ID => $admin->{DOMAIN_ID} });

    #Sheduler fot TP change
    if ($conf{DV_TP_MULTISHEDULE}) {
      if ($FORM{del_Shedule} && $FORM{is_js_confirmed}) {
        $Shedule->del({ ID => $FORM{del_Shedule} });
        if (!$Shedule->{errno}) {
          $html->message('info', $_INFO, "$_SHEDULE $_DELETED $FORM{del_Shedule}");
        }
        $Shedule->{TOTAL} = 1;
      }

      $table = $html->table(
        {
          width      => '100%',
          caption    => "$_SHEDULE",
          cols_align => [ 'right', 'left', 'left' ],
          title      => [ $_DATE, "$_TARIF_PLAN", '-' ],
        }
      );

      if ($Shedule->{TOTAL} > 0) {
        my $list = $Shedule->list(
          {
            UID      => $Dv->{UID},
            TYPE     => 'tp',
            DESCRIBE => "$message\n$_FROM: '$FORM{date_y}-$FORM{date_m}-$FORM{date_d}'",
            MODULE   => 'Dv'
          }
        );

        my %TP_HASH = ();
        foreach my $line (@$tp_list) {
          $TP_HASH{ $line->[0] } = $line->[1];
        }

        foreach my $line (@$list) {
          $table->addrow("$line->[3]-$line->[2]-$line->[1]", "$line->[7] : $TP_HASH{$line->[7]}", $html->button($_DEL, "index=$index&del_Shedule=$line->[14]&UID=$FORM{UID}", { MESSAGE => "$_DEL $line->[3]-$line->[2]-$line->[1]?", CLASS => 'del' }));
        }

        $tariffs->{SHEDULE_LIST} .= $table->show();
      }
    }

    $tariffs->{TARIF_PLAN_SEL} = $html->form_select(
      'TP_ID',
      {
        SELECTED          => $Dv->{TP_ID},
        SEL_MULTI_ARRAY   => $tp_list,
        MULTI_ARRAY_KEY   => 0,
        MULTI_ARRAY_VALUE => 1,
        MAIN_MENU         => ($permissions{0}{10}) ? get_function_index('dv_tp') : undef,
        MAIN_MENU_AGRV    => "TP_ID=$Dv->{TP_NUM}"
      }
    );

    $tariffs->{PARAMS} .= form_period($period, { ABON_DATE => $Dv->{ABON_DATE} });

    if ($permissions{0}{4}) {
      $tariffs->{ACTION} = 'set';
    }

    $tariffs->{LNG_ACTION} = $_CHANGE;
  }

  $tariffs->{UID}   = $attr->{USER_INFO}->{UID};
  $tariffs->{m}     = $m;
  $tariffs->{TP_ID} = $Dv->{TP_NUM};

  $tariffs->{TP_NAME} = "$Dv->{TP_ID}:$Dv->{TP_NAME} ";    #. $html->button("$_TARIF_PLANS", "index=". get_function_index('dv_tp') ."&TP_ID=$Dv->{TP_NUM}", { TITLE => "$_TP", CLASS => 'show rightAlignText' });
  $html->tpl_show(templates('form_chg_tp'), $tariffs);
}

#**********************************************************
# user_dv
#**********************************************************
sub dv_users_list {
  my ($attr) = @_;

  if (!$permissions{0}{2}) {
    return 0;
  }

  if ($attr->{TP}) {
    $FORM{TP_ID} = $FORM{TP_NUM} if ($FORM{TP_NUM});
    $LIST_PARAMS{TP_ID} = $FORM{TP_ID};
  }
  elsif ($FORM{TP_ID} || $FORM{TP_NUM}) {
    $FORM{TP_ID} = $FORM{TP_NUM} if ($FORM{TP_NUM});
    $FORM{subf} = $index;
    dv_tp();
    return 0;
  }

  $Dv->{GROUP_SEL}  = sel_groups();
  $Dv->{STATUS_SEL} = $html->form_select(
    'STATUS',
    {
      SELECTED => $FORM{STATUS} || 0,
      SEL_HASH => {
        '' => "$_ALL",
        0  => $service_status[0],
        1  => $service_status[1],
        2  => $service_status[2],
        3  => $service_status[3],
        4  => $service_status[4],
        5  => $service_status[5]
      },
      NO_ID => 1,
      STYLE => \@service_status_colors,
    }
  );

  form_search({ SEARCH_FORM  => $html->tpl_show(_include('dv_users_search', 'Dv'), 
  	  { %$Dv, %FORM }, 
  	  { OUTPUT2RETURN => 1 }),
  	  ADDRESS_FORM => 1 
  	});

  my $i            = 0;
  my $users_status = 0;
  foreach my $name (@service_status) {
    if (defined($FORM{STATUS}) && $FORM{STATUS} == $i && $FORM{STATUS} ne '') {
      $LIST_PARAMS{STATUS} = $FORM{STATUS};
      $pages_qs   .= "&STATUS=$i";
      $status_bar .= ' ' . $html->b($name);
      $users_status = $i;
    }
    else {
      my $qs = $pages_qs;
      $qs =~ s/\&STATUS=\d//;
      $status_bar .= ' ' . $html->button($html->color_mark($name, $service_status_colors[$i]), "index=$index&STATUS=$i$qs");
    }
    $i++;
  }

  print $html->letters_list({ pages_qs => $pages_qs });

  if ($FORM{letter}) {
    $LIST_PARAMS{FIRST_LETTER} = $FORM{letter};
    $pages_qs .= "&letter=$FORM{letter}";
  }

  my $list = $Dv->list({%LIST_PARAMS, COLS_NAME => 1 });
  my $TITLE = title_former({
     INPUT_DATA      => $Dv,
  	 BASE_FIELDS     => 6,
  	 FUNCTION_FIELDS => 'payments, stats',
  	 EXT_TITLES      => {
       'ip'          => 'IP',
       'netmask'     => 'NETMASK',
       'speed'       => $_SPEED,
       'port'        => $_PORT,
       'cid'         => 'CID',
       'filter_id'   => 'Filter ID',
       'tp_name'     => "$_TARIF_PLAN",
       'dv_status'   => "$_STATUS"
         }
    });


  if ($Dv->{errno}) {
    $html->message('err', $_ERROR, "[$Dv->{errno}] $err_strs{$Dv->{errno}}");
    return 0;
  }
  elsif ($Dv->{TOTAL} == 1) {
    delete $FORM{LOGIN};
    $ui = user_info($list->[0]->{uid});
    print $ui->{TABLE_SHOW};
    form_users({ USER_INFO => $ui });
    return 0;
  }

  my $table = $html->table(
    {
      width      => '100%',
      caption    => "Internet - $_USERS",
      border     => 1,
      title      => $TITLE,
      cols_align => [ 'left', 'left', 'right', 'right', 'left', 'center', 'center:noprint', 'center:noprint' ],
      qs         => $pages_qs,
      pages      => $Dv->{TOTAL},
      ID         => 'INTERNET_USERS_LIST',
      header     => $status_bar
    }
  );

  foreach my $line (@$list) {
    my $payments = ($permissions{1}) ? $html->button("$_PAYMENTS", "index=2&UID=" . $line->{uid}, { CLASS => 'payments' }) : '';

    my @fields_array = ();
    for (my $i = 6; $i < 6+$Dv->{SEARCH_FIELDS_COUNT} ; $i++) {
      push @fields_array, $line->{$Dv->{COL_NAMES_ARR}->[$i]};
    }

    $table->addrow(
      user_ext_menu($line->{uid}, $line->{id}),
      "$line->{fio}",
      "$line->{deposit}",
      "$line->{credit}",
      "$line->{tp_name}",
      ($line->{status} > 0) ? $html->color_mark($service_status[ $line->{status} ], $service_status_colors[ $line->{status} ]) : "$service_status[$line->{status}]",
      @fields_array,
      $payments,
      $html->button("$_STATS", "index=" . get_function_index('dv_stats') . "&UID=" . $line->{uid}, { CLASS => 'stats' })
    );
  }
  print $table->show();

  if (!$admin->{MAX_ROWS}) {
    $table = $html->table(
      {
        width      => '100%',
        cols_align => [ 'right', 'right' ],
        rows       => [ [ "$_TOTAL:", $html->b($Dv->{TOTAL}) ] ]
      }
    );
    print $table->show();
  }

  return 0;
}

#**********************************************************
# user_dv
#**********************************************************
sub dv_user {
  my ($attr) = @_;

  $Dv->{UID} = $FORM{UID} || $LIST_PARAMS{UID};
  undef $Dv->{errno};
  if ($FORM{REGISTRATION_INFO}) {

    # Info
    load_module('Docs', $html);
    my $users = Users->new($db, $admin, \%conf);
    $Dv       = $Dv->info($Dv->{UID});
    my $pi    = $users->pi({ UID => $Dv->{UID} });
    my $user  = $users->info($Dv->{UID}, { SHOW_PASSWORD => $permissions{0}{3} });
    $pi->{ADDRESS_FULL} = "$pi->{ADDRESS_STREET} $pi->{ADDRESS_BUILD}, $pi->{ADDRESS_FLAT}";

    ($Dv->{Y}, $Dv->{M}, $Dv->{D}) = split(/-/, (($pi->{CONTRACT_DATE}) ? $pi->{CONTRACT_DATE} : $DATE), 3);
    $pi->{CONTRACT_DATE_LIT} = "$Dv->{D} " . $MONTHES_LIT[ int($Dv->{M}) - 1 ] . " $Dv->{Y} $_YEAR";

    $Dv->{MONTH_LIT}         = $MONTHES_LIT[ int($Dv->{M}) - 1 ];
    if ($Dv->{Y}=~/(\d{2})$/) {
      $Dv->{YY}=$1;
    }

    if ($FORM{pdf}) {
      print $html->header();
      $html->tpl_show(
        _include('dv_user_info', 'Dv', { pdf => 1 }),
        {
          %$user,
          %$pi,
          DATE => $DATE,
          TIME => $TIME,
          %$Dv,
        }
      );
    }
    else {
      $html->tpl_show(templates('form_user_info'), { %$user, %$pi, DATE => $DATE, TIME => $TIME });
      $html->tpl_show(_include('dv_user_info', 'Dv'), $dv);

      if (in_array('Mail', \@MODULES)) {
        require "Abills/modules/Mail/webinterface";
        my $Mail = Mail->new($db, $admin, \%conf);

        my $list = $Mail->mbox_list({ UID => $Dv->{UID} });
        foreach my $line (@$list) {
          $Mail->{EMAIL_ADDR} = $line->[0] . '@' . $line->[1];
          $html->tpl_show(_include('mail_user_info', 'Mail'), $Mail);
        }
      }
    }

    return 0;
  }
  elsif ($FORM{Shedule}) {

  }
  elsif ($FORM{add}) {
    if (!$permissions{0}{1}) {
      $html->message('err', $_ERROR, "$ERR_ACCESS_DENY");
      return 0;
    }

    if (($FORM{IP} eq '0.0.0.0' || $FORM{IP} eq '') && $FORM{STATIC_IP_POOL}) {
      $FORM{IP} = dv_get_static_ip($FORM{STATIC_IP_POOL});
    }

    if ($FORM{IP} =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $FORM{IP} ne '0.0.0.0') {
      my $list = $Dv->list({ IP => $FORM{IP} });
      if ($Dv->{TOTAL} > 0 && $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ] != $FORM{UID}) {
        $html->message('err', $_ERROR, "IP: $FORM{IP} $_EXIST. $_LOGIN: " . $html->button("$list->[0][0]", "index=15&UID=" . $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ]));
        return 0;
      }
    }

    $Dv->add({%FORM});
    if (!$Dv->{errno}) {
      #Make month feee
      $Dv->{ACCOUNT_ACTIVATE} = $attr->{USER_INFO}->{ACTIVATE};
      $Dv->info($Dv->{UID});
      dv_get_month_fee($Dv) if (!$FORM{STATUS});

      if ($attr->{REGISTRATION}) {
        $html->tpl_show(_include('dv_user_info', 'Dv'), $Dv);
        return 0;
      }
      else {
        $html->message('info', $_INFO, "$_ADDED");
      }
    }

  }
  elsif ($FORM{change}) {
    if (!$permissions{0}{4}) {
      $html->message('err', $_ERROR, "$ERR_ACCESS_DENY");
      return 0;
    }

    if ($FORM{IP} eq '0.0.0.0' && $FORM{STATIC_IP_POOL}) {
      $FORM{IP} = dv_get_static_ip($FORM{STATIC_IP_POOL});
    }

    if ($FORM{IP} =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $FORM{IP} ne '0.0.0.0') {
      my $list = $Dv->list({ IP => $FORM{IP} });
      if ($Dv->{TOTAL} > 0 && $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ] != $FORM{UID}) {
        $html->message('err', $_ERROR, "IP: $FORM{IP} $_EXIST. $_LOGIN: " . $html->button("$list->[0][0]", "index=15&UID=" . $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ]));
        return 0;
      }
    }
    $Dv->change({%FORM});

    if ($FORM{STATUS} == 0) {
      my $Shedule = Shedule->new($db, $admin, \%conf);
      my $list = $Shedule->list(
        {
          UID    => $FORM{UID},
          MODULE => 'Dv',
          TYPE   => 'status',
          ACTION => '0'
        }
      );
      if ($Shedule->{TOTAL} == 1) {
        $Shedule->del(
          {
            UID => $FORM{UID},
            IDS => $list->[0][14]
          }
        );
      }
    }

    if (!$Dv->{errno}) {
      $Dv->{ACCOUNT_ACTIVATE} = $attr->{USER_INFO}->{ACTIVATE};
      if (!$FORM{STATUS} && ($FORM{GET_ABON} || !$FORM{TP_ID})) {
        dv_get_month_fee($Dv);
      }

      $html->message('info', "Internet", "$_CHANGED");
      return 0 if ($attr->{REGISTRATION});
    }
  }
  elsif ($FORM{del}) {
    $Dv->del();
    if (!$Dv->{errno}) {
      $html->message('info', $_INFO, "$_DELETED");
    }
  }

  if ($Dv->{errno}) {
    if ($Dv->{errno} == 15) {
      $html->message('err', "Internet:$_ERROR", "$ERR_SMALL_DEPOSIT");
    }
    elsif ($Dv->{errno} == 7) {
      $html->message('err', "Internet:$_ERROR", "$_SERVISE $_EXIST");
      return 1 if ($attr->{REGISTRATION});
    }
    else {
      $html->message('err', "$Dv->{errno} $Dv->{err_str} Internet:$_ERROR", "[$Dv->{errno}] $err_strs{$Dv->{errno}}");
      return 1 if ($attr->{REGISTRATION});
    }
  }

  $Dv->info($Dv->{UID});

  if ($Dv->{TOTAL} < 1) {
    $Dv->{TP_ID} = $html->form_select(
      'TP_ID',
      {
        SELECTED => $Dv->{TP_ID} || $FORM{TP_ID},
        SEL_MULTI_ARRAY   => $tariffs->list({ MODULE => 'Dv' }),
        MULTI_ARRAY_KEY   => 0,
        MULTI_ARRAY_VALUE => 1,
      }
    );

    if ($attr->{ACTION}) {
      $Dv->{ACTION}     = $attr->{ACTION};
      $Dv->{LNG_ACTION} = $attr->{LNG_ACTION};
    }
    else {
      $Dv->{ACTION}     = 'add';
      $Dv->{LNG_ACTION} = $_ACTIVATE;
      $html->message('info', $_INFO, $_NOT_ACTIVE);
    }
  }
  else {
    if ($FORM{pay_to}) {
      dv_pay_to({ Dv => $Dv });
      return 0;
    }

    if ($attr->{ACTION}) {
      $Dv->{ACTION}     = 'change';
      $Dv->{LNG_ACTION} = $attr->{LNG_ACTION};
    }
    else {
      $Dv->{ACTION}     = 'change';
      $Dv->{LNG_ACTION} = $_CHANGE;
    }

    if ($permissions{0}{10}) {
      $Dv->{CHANGE_TP_BUTTON} = $html->button($_CHANGE, 'UID=' . $Dv->{UID} . '&index=' . get_function_index('dv_chg_tp'), { CLASS => 'change rightAlignText' });
    }

    # Get next payment period
    if (
         $Dv->{MONTH_ABON} > 0
      && !$Dv->{STATUS}
      && !$users->{DISABLE}
      && ( $users->{DEPOSIT} + $users->{CREDIT} > 0
        || $Dv->{POSTPAID_ABON}
        || $Dv->{PAYMENT_TYPE} == 1)
    )
    {

      if ($Dv->{ABON_DISTRIBUTION} && $Dv->{MONTH_ABON} > 0) {
        my $days_to_fees = int(($users->{DEPOSIT} + $users->{CREDIT}) / ($Dv->{MONTH_ABON} / 30));

        $Dv->{NEXT_FEES_WARNING} = "$_SERVICE_ENDED";
        $Dv->{NEXT_FEES_WARNING} =~ s/\%DAYS\%/$days_to_fees/g;
        if ($days_to_fees < 5) {
          $Dv->{NEXT_FEES_WARNING} = $html->color_mark($Dv->{NEXT_FEES_WARNING}, "red");
        }
      }
      else {
        $Dv->{NEXT_FEES_WARNING} = "$_ABON";
        if ($users->{ACTIVATE} ne '0000-00-00') {
          my ($Y, $M, $D) = split(/-/, $users->{ACTIVATE}, 3);
          $M--;
          $Dv->{ABON_DATE} = strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, $M, ($Y - 1900), 0, 0, 0) + 31 * 86400)));
        }
        else {
          my ($Y, $M, $D) = split(/-/, $DATE, 3);
          if ($conf{START_PERIOD_DAY} && $conf{START_PERIOD_DAY} > $D) {
          }
          else {
            $M++;
          }

          if ($M == 13) {
            $M = 1;
            $Y++;
          }
          if ($conf{START_PERIOD_DAY}) {
            $D = $conf{START_PERIOD_DAY};
          }
          else {
            $D = '01';
          }
          $Dv->{ABON_DATE} = sprintf("%d-%02d-%02d", $Y, $M, $D);
        }
      }
    }

    $Dv->{NETMASK_COLOR} = ($Dv->{NETMASK} ne '255.255.255.255') ? $_COLORS[0] : $_COLORS[1];
    my $shedule_index = get_function_index('dv_sheduler');
    $Dv->{SHEDULE} = $html->button("$_SHEDULE", "UID=$FORM{UID}&Shedule=status&index=" . (($shedule_index) ? $shedule_index : $index + 4), { CLASS => 'shedule rightAlignText' });

    my $list = $sessions->online(
      {
        UID          => $Dv->{UID},
        FIELDS_NAMES => [ CLIENT_IP_NUM, DURATION, INPUT_OCTETS, OUTPUT_OCTETS, NAS_NAME, UID, NAS_ID, NAS_PORT_ID, ACCT_SESSION_ID, USER_NAME ]
      }
    );

    if ($sessions->{TOTAL} > 0) {
      my $online_index = get_function_index('dv_online');

      my $table = $html->table(
        {
          width   => '450',
          caption => "Online",
        }
      );

      foreach my $line (@$list) {
        my ($nas_id, $nas_port_id, $acct_session_id, $user_name) = split(/ /, $FORM{hangup}, 4);
        $table->addrow(
          int2ip($line->[0]),
          $line->[1],
          int2byte($line->[2]),
          int2byte($line->[3]),
          $html->button("$line->[4]", "index=$online_index&NAS_ID=$line->[6]"),
          $html->button('Z', "index=$online_index&zap=$Dv->{UID}" . '+' . $line->[6] . '+' . $line->[7] . '+' . $line->[8] . $pages_qs,                       { TITLE => 'Zap',    CLASS => 'del', NO_LINK_FORMER => 1 }),
          $html->button('H', "index=$online_index&FRAMED_IP_ADDRESS=" . int2ip($line->[0]) . "&hangup=$line->[6]+$line->[7]+$line->[8]+$line->[9]&$pages_qs", { TITLE => 'Hangup', CLASS => 'off', NO_LINK_FORMER => 1 })
        );
      }

      $Dv->{ONLINE_TABLE} = $table->show();
    }

    $list = $admin->action_list({ TYPE => '4;14', UID => $FORM{UID}, PAGE_ROWS => 1, DESC => 'desc' });
    if ($admin->{TOTAL} > 0) {
      $list->[0]->[2] =~ /(\d{4}-\d{2}-\d{2})/;
      my $status_date = $1;

      my ($from_year, $from_month, $from_day) = split(/-/, $status_date, 3);
      my ($to_year,   $to_month,   $to_day)   = split(/-/, $DATE,        3);
      my $from_seltime = POSIX::mktime(0, 0, 0, $from_day, ($from_month - 1), ($from_year - 1900));
      my $to_seltime   = POSIX::mktime(0, 0, 0, $to_day,   ($to_month - 1),   ($to_year - 1900));

      my $days = int(($to_seltime - $from_seltime) / 86400);

      $Dv->{STATUS_INFO} = "$_FROM: $status_date ($_DAYS: $days)";
      if ($conf{DV_REACTIVE_PERIOD}) {
        my ($period, $sum) = split(/:/, $conf{DV_REACTIVE_PERIOD});
        $Dv->{STATUS_DAYS}  = $days if ($period < $days);
        $Dv->{REACTIVE_SUM} = $sum  if ($period < $days);
      }
    }

    $Dv->{CALLBACK} = ($Dv->{CALLBACK} == 1) ? ' checked' : '';
    $Dv->{REGISTRATION_INFO} = $html->button("$_REGISTRATION", "index=$index&UID=$Dv->{UID}&REGISTRATION_INFO=1", { BUTTON => 1 });

    if ($conf{DOCS_PDF_PRINT}) {
      $Dv->{REGISTRATION_INFO_PDF} = $html->button("PDF", "qindex=$index&UID=$Dv->{UID}&REGISTRATION_INFO=1&pdf=1", { ex_params => 'target=_new', BUTTON => 1 });
    }
  }

  $Dv->{STATUS_SEL} = $html->form_select(
    'STATUS',
    {
      SELECTED => $Dv->{STATUS} || $FORM{STATUS},
      SEL_ARRAY    => \@service_status,
      STYLE        => \@service_status_colors,
      ARRAY_NUM_ID => 1
    }
  );

  if ($Dv->{STATUS} > 0) {
    $Dv->{STATUS_COLOR} = $service_status_colors[ $Dv->{STATUS} ];
  }

  $Dv->{TURBO_MODE_SEL} = $html->form_select(
    'TURBO_MODE',
    {
      SELECTED => $Dv->{TURBO_MODE} || $FORM{TURBO_MODE},
      SEL_ARRAY    => [ $_ENABLE, $_DISABLE, $_NOT_ACTIVE, ],
      ARRAY_NUM_ID => 1
    }
  );

  #Join Service
  if ($attr->{USER_INFO}->{COMPANY_ID}) {
    my $list = $Dv->list(
      {
        JOIN_SERVICE => 1,
        COMPANY_ID   => $attr->{USER_INFO}->{COMPANY_ID}
      }
    );

    $Dv->{JOIN_SERVICES_SEL} = $html->form_select(
      'JOIN_SERVICE',
      {
        SELECTED          => $Dv->{JOIN_SERVICE},
        SEL_MULTI_ARRAY   => [ [ '', '', '', '', '', '', '', 0 ], [ $_MAIN, '', '', '', '', '', '', 1 ], @$list ],
        MULTI_ARRAY_KEY   => $Dv->{SEARCH_FIELDS_COUNT} + 6,
        MULTI_ARRAY_VALUE => 0,
        NO_ID             => undef

      }
    );

    if ($Dv->{JOIN_SERVICE} == 1) {
      my $list = $Dv->list(
        {
          JOIN_SERVICE => $Dv->{UID},
          COMPANY_ID   => $attr->{USER_INFO}->{COMPANY_ID},
          PAGE_ROWS    => 1000,
          COLS_NAME    => 1
        }
      );

      foreach my $line (@$list) {
        $Dv->{JOIN_SERVICES_USERS} .= $html->button("$line->{id}", "&index=15&UID=$line->{uid}"). ' :: ';
      }
    }
    elsif ($Dv->{JOIN_SERVICE} > 1) {
      $Dv->{JOIN_SERVICES_USERS} = $html->button("$_MAIN", "index=15&UID=$Dv->{JOIN_SERVICE}", { BUTTON => 1 });
    }

    $Dv->{JOIN_SERVICE} = $html->tpl_show(_include('dv_user_join_service', 'Dv'), $Dv, { OUTPUT2RETURN => 1 });
  }
  else {
    $Dv->{JOIN_SERVICE} = '';
  }

  $list = $Nas->ip_pools_list({ STATIC => 1 });
  $Dv->{STATIC_IP_POOL} = $html->form_select(
    'STATIC_IP_POOL',
    {
      SELECTED          => $FORM{STATIC_POOL},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @$list ],
      MULTI_ARRAY_KEY   => 8,
      MULTI_ARRAY_VALUE => '1',
      NO_ID             => 1
    }
  );

  $html->tpl_show(_include('dv_user', 'Dv'), { %$attr, %$Dv }, {});
  return 0;
}

#**********************************************************
# Get static ip from pool
# form_tp
#**********************************************************
sub dv_get_static_ip {
  my ($pool_id) = @_;
  my $ip = '0.0.0.0';

  $Nas->ip_pools_info($pool_id);

  my $start_ip = ip2int($Nas->{NAS_IP_SIP});
  my $end_ip   = $start_ip + $Nas->{NAS_IP_COUNT};

  my %users_ips = ();

  my $list = $Dv->list(
    {
      PAGE_ROWS => 100000,
      IP        => ">=$Nas->{NAS_IP_SIP}"
    }
  );

  foreach my $line (@$list) {
    $users_ips{ $line->[6] } = 1;
  }

  for (my $ip_cur = $start_ip ; $ip_cur <= $end_ip ; $ip_cur++) {
    if (!$users_ips{ int2ip($ip_cur) }) {
      return int2ip($ip_cur);
    }
  }

  $html->message('err', $_ERROR, "$ERR_NO_FREE_IP_IN_POOL");

  return $ip;
}

#**********************************************************
# Tarif plans
# form_tp
#**********************************************************
sub dv_tp {

  my $tarif_info;

  my @Octets_Direction = ("$_RECV + $_SEND", $_RECV, $_SEND);
  my @Payment_Types = ($_PREPAID, $_POSTPAID);

  $tarif_info               = $tariffs->defaults();
  $tarif_info->{LNG_ACTION} = $_ADD;
  $tarif_info->{ACTION}     = 'ADD_TP';

  if ($FORM{ADD_TP}) {
    $FORM{TP_ID} = $FORM{CHG_TP_ID};
    $tariffs->add({ %FORM, MODULE => 'Dv' });
    if (!$tariffs->{errno}) {
      $html->message('info', $_ADDED, "$_ADDED $tariffs->{ID}");
    }
  }
  elsif (defined($FORM{TP_ID})) {
    $tarif_info = $tariffs->info($FORM{TP_ID}, { ID => $FORM{TP_NUM} });
    $FORM{TP_SHOW} = 1;

    if ($tariffs->{errno}) {
      if ($tariffs->{errno} == 2) {
        $html->message('err', $_ERROR, "$_TARIF_PLAN $_NOT_EXIST");
      }
      else {
        $html->message('err', $_ERROR, "$_TARIF_PLAN [$tariffs->{errno}] $err_strs{$tariffs->{errno}}");
      }
      return 0;
    }

    $pages_qs .= "&TP_ID=$FORM{TP_ID}&subf=$FORM{subf}";
    $LIST_PARAMS{TP} = $FORM{TP_ID};
    $FORM{TP_NUM}    = $tarif_info->{ID};
    %F_ARGS = (TP => $tariffs);

    $tariffs->{NAME_SEL} = $html->form_main(
      {
        CONTENT => $html->form_select(
          'TP_ID',
          {
            SELECTED          => $FORM{TP_ID},
            SEL_MULTI_ARRAY   => $tariffs->list({%LIST_PARAMS}),
            MULTI_ARRAY_KEY   => 18,
            MULTI_ARRAY_VALUE => '0,1',
            NO_ID             => 1
          }
        ),
        HIDDEN => { index => "$index" },
        SUBMIT => { show  => "$_SHOW" }
      }
    );

    func_menu(
      {
        'ID'   => $tariffs->{ID},
        $_NAME => $tariffs->{NAME_SEL}
      },
      {},
      { f_args => {%F_ARGS} }
    );

    if ($FORM{subf}) {
      return 0;
    }
    elsif ($FORM{change}) {
      $tariffs->change($FORM{TP_ID}, {%FORM});
      if (!$tariffs->{errno}) {
        $html->message('info', $_CHANGED, "$_CHANGED $tariffs->{ID}");
      }
    }

    $tarif_info->{LNG_ACTION} = $_CHANGE;
    $tarif_info->{ACTION}     = 'change';
  }
  elsif (defined($FORM{del}) && $FORM{is_js_confirmed}) {
    $tariffs->del($FORM{del});

    if (!$tariffs->{errno}) {
      $html->message('info', $_DELETE, "$_DELETED $FORM{del}");
    }
  }

  if ($tariffs->{errno}) {
    if ($tariffs->{errno} == 7) {
      $html->message('err', $_ERROR, "$_TARIF_PLAN $_EXIST");
    }
    else {
      $html->message('err', $_ERROR, "[$tariffs->{errno}] $err_strs{$tariffs->{errno}}");
    }
  }

  $tarif_info->{SEL_OCTETS_DIRECTION} = $html->form_select(
    'OCTETS_DIRECTION',
    {
      SELECTED     => $tarif_info->{OCTETS_DIRECTION},
      SEL_ARRAY    => \@Octets_Direction,
      ARRAY_NUM_ID => 1
    }
  );

  $tarif_info->{PAYMENT_TYPE_SEL} = $html->form_select(
    'PAYMENT_TYPE',
    {
      SELECTED     => $tarif_info->{PAYMENT_TYPE},
      SEL_ARRAY    => \@Payment_Types,
      ARRAY_NUM_ID => 1
    }
  );

  $tarif_info->{GROUPS_SEL} = $html->form_select(
    'TP_GID',
    {
      SELECTED          => $tarif_info->{TP_GID},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @{ $tariffs->tp_group_list() } ],
      MULTI_ARRAY_KEY   => 0,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  my $nas_ip_pools_list = $Nas->ip_pools_list({ STATIC => 0 });

  $tarif_info->{IP_POOLS_SEL} = $html->form_select(
    'IPPOOL',
    {
      SELECTED          => $tarif_info->{IPPOOL},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @{$nas_ip_pools_list} ],
      MULTI_ARRAY_KEY   => 8,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  $tarif_info->{NEG_DEPOSIT_IPPOOL_SEL} = $html->form_select(
    'NEG_DEPOSIT_IPPOOL',
    {
      SELECTED          => $tarif_info->{NEG_DEPOSIT_IPPOOL},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @{$nas_ip_pools_list} ],
      MULTI_ARRAY_KEY   => 8,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  $tarif_info->{REDUCTION_FEE}      = ($tarif_info->{REDUCTION_FEE})      ? 'checked' : '';
  $tarif_info->{POSTPAID_DAY_FEE}   = ($tarif_info->{POSTPAID_DAY_FEE})   ? 'checked' : '';
  $tarif_info->{POSTPAID_MONTH_FEE} = ($tarif_info->{POSTPAID_MONTH_FEE}) ? 'checked' : '';
  $tarif_info->{PERIOD_ALIGNMENT}   = ($tarif_info->{PERIOD_ALIGNMENT})   ? 'checked' : '';
  $tarif_info->{ABON_DISTRIBUTION}  = ($tarif_info->{ABON_DISTRIBUTION})  ? 'checked' : '';
  $tarif_info->{ACTIVE_DAY_FEE}     = ($tarif_info->{ACTIVE_DAY_FEE})     ? 'checked' : '';

  %FEES_METHODS = %{ get_fees_types() };
  $FEES_METHODS{0} = '';

  $tarif_info->{SEL_METHOD} = $html->form_select(
    'FEES_METHOD',
    {
      SELECTED => $tarif_info->{FEES_METHOD} || 1,
      SEL_HASH => \%FEES_METHODS,
      NO_ID    => 1,
      SORT_KEY => 1,
      MAIN_MENU => get_function_index('form_fees_types'),
    }
  );

  my $tp_list = $tariffs->list({ MODULE => 'Dv', DOMAIN_ID => $admin->{DOMAIN_ID} });

  $tarif_info->{SMALL_DEPOSIT_ACTION_SEL} = $html->form_select(
    'SMALL_DEPOSIT_ACTION',
    {
      SELECTED          => $tarif_info->{SMALL_DEPOSIT_ACTION},
      SEL_MULTI_ARRAY   => [ [ '', '' ], [ '-1', "$_HOLD_UP" ], @{$tp_list} ],
      MULTI_ARRAY_KEY   => 0,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  $tarif_info->{NEXT_TARIF_PLAN_SEL} = $html->form_select(
    'NEXT_TARIF_PLAN',
    {
      SELECTED          => $tarif_info->{NEXT_TARIF_PLAN},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @{$tp_list} ],
      MULTI_ARRAY_KEY   => 0,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  if ($conf{BONUS_EXT_FUNCTIONS}) {
    my @BILL_ACCOUNT_PRIORITY = ("$_PRIMARY $_BILL_ACCOUNT", "$_EXTRA $_BILL_ACCOUNT, $_PRIMARY $_BILL_ACCOUNT", "$_EXTRA $_BILL_ACCOUNT");

    $tarif_info->{BILLS_PRIORITY_SEL} = $html->form_select(
      'BILLS_PRIORITY',
      {
        SELECTED     => $tarif_info->{BILLS_PRIORITY},
        SEL_ARRAY    => \@BILL_ACCOUNT_PRIORITY,
        ARRAY_NUM_ID => 1
      }
    );

    $tarif_info->{BONUS} = $html->tpl_show(_include('bonus_tp_row', 'Bonus'), $tarif_info, { OUTPUT2RETURN => 1 });
  }

  if ($conf{EXT_BILL_ACCOUNT}) {
    my $checked = ($tarif_info->{EXT_BILL_ACCOUNT}) ? ' checked' : '';
    $tarif_info->{EXT_BILL_ACCOUNT} = "<tr><td>$_EXTRA $_BILL:</td><td><input type='checkbox' name='EXT_BILL_ACCOUNT' value='1' $checked></td></tr>\n";
  }
  else {
    $tarif_info->{EXT_BILL_ACCOUNT} = '';
  }

  $html->tpl_show(_include('dv_tp', 'Dv'), $tarif_info, { SKIP_VARS => 'IP' });

  my $list = $tariffs->list({ %LIST_PARAMS, MODULE => 'Dv' });

  # Time tariff Name Begin END Day fee Month fee Simultaneously - - -
  my $table = $html->table(
    {
      width   => '100%',
      caption => "$_TARIF_PLANS",
      border  => 1,
      title   => [ '#', $_NAME, $_HOUR_TARIF, $_TRAFIC_TARIFS, $_PAYMENT_TYPE, $_DAY_FEE, $_MONTH_FEE, $_SIMULTANEOUSLY, $_AGE, $_GROUP, '-', '-', '-' ],
      cols_align => [ 'right', 'left', 'center', 'center', 'center', 'right', 'right', 'right', 'right', 'center:noprint', 'center:noprint', 'center:noprint' ],
      ID         => 'DV_TARIF_PLANS'
    }
  );

  my ($delete, $change);
  foreach my $line (@$list) {
    if ($permissions{4}{1}) {
      $delete = $html->button($_DEL, "index=$index&del=$line->[18]", { MESSAGE => "$_DEL $line->[0]?", CLASS => 'del' });
      $change = $html->button($_CHANGE, "index=$index&TP_ID=$line->[18]", { CLASS => 'change' });
    }

    if ($FORM{TP_ID} eq $line->[18]) {
      $table->{rowcolor} = 'row_active';
    }
    else {
      undef($table->{rowcolor});
    }

    $table->addrow(
      $html->b($line->[0]),
      $html->button($line->[1], "index=$index&TP_ID=$line->[18]"),
      $bool_vals[ $line->[2] ],
      $bool_vals[ $line->[3] ],
      $Payment_Types[ $line->[4] ],
      $line->[5], $line->[6], $line->[7], $line->[8], $line->[9], $html->button($_INTERVALS, "index=" . get_function_index('form_intervals') . "&subf=73&TP_ID=$line->[18]", { CLASS => 'interval' }),
      $change, $delete
    );
  }

  print $table->show();

  $table = $html->table(
    {
      width      => '100%',
      cols_align => [ 'right', 'right' ],
      rows       => [ [ "$_TOTAL:", $html->b($tariffs->{TOTAL}) ] ]
    }
  );
  print $table->show();
}

#*******************************************************************
# dv_rating_tp
#*******************************************************************
sub dv_rating_tp {
  my ($attr) = @_;

  eval { require Bonus_rating; };
  if (!$@) {
    Bonus_rating->import();
  }
  else {
    $html->message('err', $_ERROR, "Can't load 'Bonus_rating'. Purchase this module http://abills.net.ua");
    return 0;
  }

  my $Bonus_rating = Bonus_rating->new($db, $admin, \%conf);

  if (defined($attr->{TP})) {
    if ($FORM{change}) {
      $Bonus_rating->change({%FORM});

      if (!$Bonus_rating->{errno}) {
        $html->message('info', $_INFO, "$_CHANGED");
      }
    }
  }
  elsif (defined($FORM{TP_ID})) {
    $FORM{subf} = $index;
    dv_tp();
    return 0;
  }

  if ($Bonus_rating->{errno}) {
    $html->message('err', $_ERROR, "[$Bonus_rating->{errno}] $err_strs{$Bonus_rating->{errno}} $Bonus_rating->{errstr}");
  }

  $Bonus_rating->info($FORM{TP_ID});

  my $tp_list = $tariffs->list({ MODULE => 'Dv', DOMAIN_ID => $admin->{DOMAIN_ID} });
  $Bonus_rating->{RATING_ACTION_SEL} = $html->form_select(
    'RATING_ACTION',
    {
      SELECTED          => $Bonus_rating->{RATING_ACTION},
      SEL_MULTI_ARRAY   => [ [ '', '' ], [ '-1', "$_HOLD_UP" ], @{$tp_list} ],
      MULTI_ARRAY_KEY   => 18,
      MULTI_ARRAY_VALUE => '0,1',
      NO_ID             => 1
    }
  );

  $Bonus_rating->{ACTION}           = 'change';
  $Bonus_rating->{LNG_ACTION}       = "$_CHANGE";
  $Bonus_rating->{EXT_BILL_ACCOUNT} = "checked" if ($Bonus_rating->{EXT_BILL_ACCOUNT});

  $html->tpl_show(_include('dv_rating_tp', 'Dv'), $Bonus_rating);
}

#*******************************************************************
# dv_rating_periodic
#*******************************************************************
sub dv_rating_periodic {
  my ($attr) = @_;

  my $debug = $attr->{DEBUG} || 0;
  my $debug_output = '';
  $debug_output .= "DV: Make ratings\n" if ($debug > 1);

  eval { require Bonus_rating; };
  if (!$@) {
    Bonus_rating->import();
  }
  else {
    print "Can't load 'Bonus_rating'. Purchase this module http://abills.net.ua";
    return 0;
  }

  my %LIST_PARAMS = (PAGE_ROWS => 1000000);
  $LIST_PARAMS{LOGIN} = $attr->{LOGIN} if ($attr->{LOGIN});
  $LIST_PARAMS{TP_ID} = $attr->{TP_ID} if ($attr->{TP_ID});

  my $Bonus_rating = Bonus_rating->new($db, $admin, \%conf);

  $Bonus_rating->change_users_rating({%LIST_PARAMS});

  #Change Tps
  my $list = $Bonus_rating->change_users_tps_list({%LIST_PARAMS});

  foreach my $line (@$list) {
    my $uid   = $line->[0];
    my $tp_id = $line->[1];
    $debug_output .= "UID: $uid TP: $line->[6] -> $tp_id\n" if ($debug > 0);
    $Dv->change(
      {
        UID            => $uid,
        TP_ID          => $tp_id,
        NO_CHANGE_FEES => 1,
      }
    );

  }

  $DEBUG .= $debug_output;
  return $debug_output;
}

#*******************************************************************
#
#*******************************************************************
sub dv_rating_user {

  eval { require Bonus_rating; };
  if (!$@) {
    Bonus_rating->import();
  }
  else {
    print "Can't load 'Bonus_rating'. Purchase this module http://abills.net.ua";
    return 0;
  }

  my $Bonus_rating = Bonus_rating->new($db, $admin, \%conf);
  $users = $user if (!$users);

  $Bonus_rating->users_rating_info({ UID => $LIST_PARAMS{UID} });

  if ($Bonus_rating->{TOTAL} == 0) {
    $html->message('info', $_INFO, "$_BONUS $_NOT_ACTIVE");
    return 0;
  }

  if ($FORM{UP_RATING_PRE}) {
    my $need_percents = int(($FORM{UP_RATING} - $Bonus_rating->{RATING_PER}));
    $FORM{NEED_SUM} = sprintf("%.2f", $need_percents * ($Bonus_rating->{ONE_PERCENT_SUM} * $Bonus_rating->{ONE_PERCENT_COUNT}));

    $html->tpl_show(_include('dv_user_rating_pre', 'Dv'), { %$Bonus_rating, %FORM });
    return 0;
  }
  elsif ($FORM{UP_RATING}) {
    my $need_percents = int(($FORM{UP_RATING} - $Bonus_rating->{RATING_PER}));
    my $need_sum = $need_percents * ($Bonus_rating->{ONE_PERCENT_SUM} * $Bonus_rating->{ONE_PERCENT_COUNT});

    if ($users->{CREDIT} + $users->{DEPOSIT} < $need_sum) {
      $html->message('err', $_ERROR, "$ERR_SMALL_DEPOSIT");
    }
    else {
      for (my $i = 0 ; $i < int($need_percents * $Bonus_rating->{ONE_PERCENT_COUNT}) ; $i++) {
        $fees->take($users, $Bonus_rating->{ONE_PERCENT_SUM}, { DESCRIBE => "$_RATING_UP" });
        $users->{DEPOSIT} -= $Bonus_rating->{ONE_PERCENT_SUM};
      }
      $Bonus_rating->{RATING_PER} = $FORM{UP_RATING};
      $html->message('info', $_INFO, "$_UP_RATING $FORM{UP_RATING}");

      $users->pi_change({ _rating => $Bonus_rating->{RATING_PER}, UID => $LIST_PARAMS{UID} });
    }
  }

  $Bonus_rating->{UP_RATING} = int(($users->{CREDIT} + $users->{DEPOSIT}) / ($Bonus_rating->{ONE_PERCENT_SUM} * $Bonus_rating->{ONE_PERCENT_COUNT})) + $Bonus_rating->{RATING_PER};

  if ($Bonus_rating->{UP_RATING} > 100) {
    $Bonus_rating->{UP_RATING} = 100;
  }
  elsif ($Bonus_rating->{UP_RATING} < 0) {
    $Bonus_rating->{UP_RATING} = 0;
  }

  $Bonus_rating->{ONE_PERCENT_SUM} = sprintf("%.2f", $Bonus_rating->{ONE_PERCENT_SUM} * $Bonus_rating->{ONE_PERCENT_COUNT});

  $html->tpl_show(_include('dv_user_rating', 'Dv'), $Bonus_rating);
}

#*******************************************************************
# online users
#*******************************************************************
sub dv_online {

  my $message;
  if ($FORM{ping}) {
    if ($FORM{ping} =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}$/) {
      my $res = `$PING -c 5 $FORM{ping}`;
      $html->message('info', $_INFO, "Ping  $FORM{ping} \n Result: \n" . $html->pre($res, { OUTPUT2RETURN => 1 }));
    }
    else {
      $html->message('err', $_ERROR, "$ERR_WRONG_DATA");
    }
  }
  elsif ($FORM{hangup}) {
    my ($nas_id, $nas_port_id, $acct_session_id, $user_name) = split(/ |\+/, $FORM{hangup}, 4);

    $Nas->info({ NAS_ID => $nas_id });

    if ($Nas->{errno}) {
      $html->message('err', $_NAS, "$Nas->{errstr}");
      return 0;
    }

    require "Abills/nas.pl";
    my $ret = hangup(
      $Nas,
      "$nas_port_id",
      "$user_name",
      {
        ACCT_SESSION_ID   => "$acct_session_id",
        FRAMED_IP_ADDRESS => "$FORM{FRAMED_IP_ADDRESS}",
        UID               => $FORM{UID}
      }
    );

    if ($ret == 0) {
      $message = "$_NAS ID:  $nas_id\n $_NAS IP: $Nas->{NAS_IP}\n $_PORT: $nas_port_id\n SESSION_ID: $acct_session_id\n\n  $ret";
      sleep 3;
      $admin->action_add("$FORM{UID}", "$user_name", { MODULE => 'Dv', TYPE => 15 });
    }
    elsif ($ret == 1) {
      $message = 'NAS NOT supported yet';
    }

    $html->message('info', $_INFO, "$message");
  }
  if ($FORM{zapall}) {
    $sessions->zap(0, 0, 0, { ALL => 1, %FORM });
    $html->message('info', $_INFO, "Zapped all sessions");
  }
  elsif ($FORM{zap}) {
    my ($uid, $nas_id, $nas_port_id, $acct_session_id) = split(/ /, $FORM{zap}, 4);
    $sessions->zap($nas_id, $nas_port_id, $acct_session_id, {%FORM});

    if ($sessions->{errno}) {
      $html->message('err', $_ERROR, "[$sessions->{errno}] $err_strs{$sessions->{errno}}");
      return 0;
    }

    $Nas->info({ NAS_ID => $nas_id });
    $message = "\n$_NAS ID:   $nas_id\n $_NAS IP: $Nas->{NAS_IP} \n $_PORT: $nas_port_id\n SESSION_ID: $acct_session_id\n\n";
    my ($Y, $M, $D) = split(/-/, $DATE, 3);
    $sessions->list(
      {
        UID             => $uid,
        DATE            => ">=$Y-$M-01",
        ACCT_SESSION_ID => $acct_session_id,
        NAS_PORT        => $nas_port_id,
        NAS_ID          => $Nas->{NAS_ID},
        PAGE_ROWS       => 1
      }
    );

    if ($sessions->{TOTAL} < 1) {
      $message .= $html->button('Add To log', "index=$index&tolog=$acct_session_id&nas_id=$nas_id&nas_port_id=$nas_port_id&ZAPED=1", { BUTTON => 1 }) . ' ' . $html->button($_DEL, "index=$index&del=$acct_session_id&nas_id=$nas_id&nas_port_id=$nas_port_id&ZAPED=1", { BUTTON => 1 });
    }
    else {
      $message .= "$_EXIST";
      $sessions->online_del(
        {
          NAS_ID          => $nas_id,
          NAS_PORT        => $nas_port_id,
          ACCT_SESSION_ID => $acct_session_id
        }
      );
    }

    $html->message('info', $_INFO, $message);
  }
  elsif ($FORM{tolog}) {
    require Acct;
    Acct->import();
    my $Acct = Acct->new($db, \%conf);

    if ($FORM{dellist}) {
      $sessions->online(
        {
          SESSION_IDS  => $FORM{dellist},
          ZAPED        => 1,
          FIELDS_NAMES => [
            INPUT_OCTETS,
            OUTPUT_OCTETS,
            INPUT_OCTETS2,
            OUTPUT_OCTETS2,

            ACCT_SESSION_TIME,
            ACCT_SESSION_ID,

            NAS_PORT_ID,
            NAS_IP,
            CLIENT_IP,
            CONNECT_INFO,
            CID,
            USER_NAME,
            SESSION_START
          ]
        }
      );

      my $online_list = $sessions->{nas_sorted};
      my $nas_list    = $Nas->list();
      my @results     = ();
      foreach my $nas_row (@$nas_list) {
        next if (!defined($online_list->{ $nas_row->[0] }));

        foreach my $line (@{ $online_list->{ $nas_row->[0] } }) {
          $ACCT_INFO->{INBYTE}               = $line->[0];
          $ACCT_INFO->{OUTBYTE}              = $line->[1];
          $ACCT_INFO->{INBYTE2}              = $line->[2];
          $ACCT_INFO->{OUTBYTE2}             = $line->[3];
          $ACCT_INFO->{ACCT_SESSION_TIME}    = $line->[4];
          $ACCT_INFO->{ACCT_SESSION_ID}      = $line->[5];
          $ACCT_INFO->{NAS_PORT}             = $line->[6];
          $ACCT_INFO->{NAS_IP_ADDRESS}       = $nas_row->[3];
          $ACCT_INFO->{FRAMED_IP_ADDRESS}    = $line->[8];
          $ACCT_INFO->{CONNECT_INFO}         = $line->[9];
          $ACCT_INFO->{CALLING_STATION_ID}   = $line->[10];
          $ACCT_INFO->{USER_NAME}            = $line->[11];
          $ACCT_INFO->{SESSION_START}        = $line->[12];
          $ACCT_INFO->{ACCT_TERMINATE_CAUSE} = 3;
          $ACCT_INFO->{ACCT_STATUS_TYPE}     = 'Stop';

          my $r = $Acct->accounting($ACCT_INFO, $Nas);

          if ($Acct->{errno}) {
            push @results, "$ACCT_INFO->{USER_NAME} $_ERROR";
          }
          else {
            push @results, "$ACCT_INFO->{USER_NAME} $_ADDED";
          }
        }
      }

      $table = $html->table({ width => '100%', });

      foreach my $val (@results) {
        $table->addrow($val);
      }

      $html->message('info', $_REPORTS, $table->show());
      my @del_arr = split(/, /, $FORM{dellist});
      $sessions->online_del({ SESSIONS_LIST => \@del_arr });
    }
    else {
      $Nas->info({ NAS_ID => $FORM{nas_id} });
      my $ACCT_INFO = $sessions->online_info(
        {
          NAS_ID          => $FORM{nas_id},
          NAS_PORT        => $FORM{nas_port_id},
          ACCT_SESSION_ID => $FORM{tolog}
        }
      );

      if ($ACCT_INFO->{TOTAL} < 1) {
        $html->message('err', $_ERROR, "$_NOT_EXIST");
        return 0;
      }

      $ACCT_INFO->{INBYTE}               = $ACCT_INFO->{ACCT_INPUT_OCTETS};
      $ACCT_INFO->{OUTBYTE}              = $ACCT_INFO->{ACCT_OUTPUT_OCTETS};
      $ACCT_INFO->{INBYTE2}              = $ACCT_INFO->{ACCT_EX_INPUT_OCTETS};
      $ACCT_INFO->{OUTBYTE2}             = $ACCT_INFO->{ACCT_EX_OUTPUT_OCTETS};
      $ACCT_INFO->{ACCT_STATUS_TYPE}     = 'Stop';
      $ACCT_INFO->{ACCT_TERMINATE_CAUSE} = 3;

      # Exppp VENDOR params
      my $r = $Acct->accounting($ACCT_INFO, $Nas);

      if ($Acct->{errno}) {
        $html->message('err', $_ERRNO, "$Acct->{errno} $Acct->{errstr}");
      }
      else {
        my $table = $html->table({ width => '100%' });
        foreach my $k (sort keys %$ACCT_INFO) {
          $table->addrow($k, $ACCT_INFO->{$k});
        }

        $table->addrow('-', '-');
        foreach my $k (sort keys %$Acct) {
          $table->addrow($k, $Acct->{$k});
        }

        $html->message('info', $_ADDED, $table->show());
      }

      $sessions->online_del(
        {
          NAS_ID          => $ACCT_INFO->{NAS_ID},
          NAS_PORT        => $ACCT_INFO->{NAS_PORT},
          ACCT_SESSION_ID => $ACCT_INFO->{ACCT_SESSION_ID}
        }
      );
    }
  }
  elsif ($FORM{del} || $FORM{dellist}) {
    if ($FORM{dellist}) {
      my @sessions_list = split(/, /, $FORM{dellist});
      $sessions->online_del({ SESSIONS_LIST => \@sessions_list });
      $FORM{del} = $FORM{dellist};
    }
    else {
      $sessions->online_del(
        {
          NAS_ID          => $FORM{nas_id},
          NAS_PORT        => $FORM{nas_port_id},
          ACCT_SESSION_ID => $FORM{del}
        }
      );
    }

    if (!$sessions->{errno}) {
      my $table = $html->table(
        {
          width => '100%',
          rows  => [ [ "NAS_ID", $FORM{nas_id} ], [ "NAS_PORT", $FORM{nas_port_id} ], [ "ACCT_SESSION_ID", $FORM{del} ] ]
        }
      );

      my $MODULE      = (defined($self->{MODULE})) ? $self->{MODULE} : '';
      my $action_type = ($attr->{TYPE})            ? $attr->{TYPE}   : '';
      $html->message('info', $_DELETED, $table->show());
    }
  }

  # online count
  my $list = $sessions->online_count({ %LIST_PARAMS, FIELDS => \@ACTIVE_FIELDS });
  my $nas_list = $Nas->list();

  $form_link = '';
  my $cure = '';
  if ($FORM{ZAPED}) {
    $LIST_PARAMS{ZAPED} = 1;
    $form_link = $html->button("Online", "index=$index", { BUTTON => 1, IMG => ':button_activate.png' });
    $cure = 'Zap';
    $pages_qs .= "&ZAPED=1";
  }
  else {
    $sessions->{ZAPED} = 0 if (!$sessions->{ZAPED});
    $form_link = $html->button("$_ZAPED ($sessions->{ZAPED})", "index=$index&ZAPED=1", { BUTTON => 1, IMG => ':button_del.png' });
    $cure = 'Online';
  }

  my $table2 = $html->table(
    {
      width      => '100%',
      cols_align => [ 'left', 'right', 'right', 'right' ]
    }
  );

  $table2->addtd($table2->td("Online $_TOTAL: $sessions->{ONLINE}", { bgcolor => $_COLORS[0] }), $table2->td($form_link));

  print $table2->show();

  #Field formed section
  my @FIELDS_ALL = ("$_USER", "$_FIO", "$_PORT", "IP", "$_DURATION", "$_RECV", "$_SENT", "Ex_IN", "Ex_OUT", "CID", "SESSION_ID", "$_TARIF_PLAN", "CONNECT_INFO", "$_SPEED", "$_SUM", "$_STATUS", "$_ADDRESS", "$_GROUP", "TURBO", "$_JOIN_SERVICE");

  if ($sessions->{TOTAL} > 500) {
    my $table = $html->table(
      {
        width      => '100%',
        caption    => "Online $_TOTAL",
        border     => 1,
        title      => [ "NAS ID", "NAS $_NAME", "NAS IP", "$_TYPE", "$_SESSIONS", "$_USERS", "ZAPPED", "$_ERROR", "-" ],
        cols_align => [ 'right', 'left', 'right', 'right', 'right', 'right', 'right', 'right', 'right', 'center:noprint' ],
        qs         => $pages_qs,
        ID         => 'ONLINE'
      }
    );

    foreach my $line (@$list) {
      $table->{rowcolor} = ($line->[0] == $FORM{NAS_ID}) ? 'row_active' : undef;

      $table->addrow($line->[0], $line->[1], $line->[2], $line->[3], $line->[4], $line->[5], ($line->[6] > 0) ? $html->button("$line->[6]", "index=$index&NAS_ID=$line->[0]&ZAPED=1") : 0, $line->[7], $html->button("$_SHOW", "index=$index&NAS_ID=$line->[0]", { CLASS => 'show' }));
    }
    print $table->show();

    if (!$FORM{NAS_ID} && !$FORM{ZAPED} && !$FORM{FILTER}) {
      print dv_online_search({ FIELDS_ALL => \@FIELDS_ALL });

      return 0;
    }
    else {
      $pages_qs .= "&NAS_ID=$FORM{NAS_ID}";
      $LIST_PARAMS{NAS_ID} = $FORM{NAS_ID};
    }
  }

  my @CAPTION = ();
  my @ACTIVE_FIELDS = (0, 1, 2, 3, 4, 5, 6, 7, 8);

  if ($FORM{'fields'}) {
    @ACTIVE_FIELDS = split(/, /, $FORM{'fields'});
    $FORM{'fields'} =~ s/ //g;
    $admin->{WEB_OPTIONS} =~ s/;DV_MONITOR=(.+);//g;
    $admin->change({ AID => $admin->{AID}, WEB_OPTIONS => "$admin->{WEB_OPTIONS};DV_MONITOR=$FORM{'fields'};" });
  }
  elsif ($admin->{WEB_OPTIONS} =~ /DV_MONITOR=(.+);/) {
    @ACTIVE_FIELDS = split(/,/, $1);
  }

  foreach my $field_id (@ACTIVE_FIELDS) {
    push @CAPTION, $FIELDS_ALL[$field_id];
  }

  if (defined($FORM{FILTER})) {
    $LIST_PARAMS{FILTER_FIELD} = $FORM{FILTER_FIELD};
    $LIST_PARAMS{FILTER}       = $FORM{FILTER};
  }

  $sessions->online({ %LIST_PARAMS, FIELDS => \@ACTIVE_FIELDS });
  my $dub_ports  = $sessions->{dub_ports};
  my $dub_logins = $sessions->{dub_logins};

  $table = $html->table(
    {
      width      => '100%',
      caption    => "$cure",
      border     => 1,
      title      => [ @CAPTION, '-', '-', '-', '-' ],
      cols_align => [ 'left', 'left', 'right', 'right', 'right', 'right', 'right', 'right', 'right', 'center:noprint', 'center:noprint', 'center:noprint', 'center:noprint' ],
      qs         => $pages_qs,
      ID         => 'ONLINE',
      header     => ($FORM{ZAPED}) ? "<script language=\"JavaScript\" type=\"text/javascript\">
<!-- 
function CheckAllINBOX() {
  for (var i = 0; i < document.users_list.elements.length; i++) {
    if(document.users_list.elements[i].type == 'checkbox' && document.users_list.elements[i].name == 'dellist'){
      document.users_list.elements[i].checked =         !(document.users_list.elements[i].checked);
    }
  }
}
//-->
</script>\n<a href=\"javascript:void(0)\" onClick=\"CheckAllINBOX();\">$_SELECT_ALL</a>\n" : undef
    }
  );

  my $online = $sessions->{nas_sorted};

  foreach my $nas_row (@$nas_list) {
    next if (!defined($online->{ $nas_row->[0] }));
    next if (($FORM{NAS_ID} && $FORM{NAS_ID} != $nas_row->[0]) && !$FORM{ZAPED});

    my $l     = $online->{ $nas_row->[0] };
    my $total = $#{$l} + 1;
    $table->{rowcolor} = 'row_active';
    $table->{extra} = "colspan='" . ($#CAPTION + 1) . "' class='small'";
    $table->addrow("$nas_row->[0]:"
      . $html->button($html->b($nas_row->[1]), "index=" . get_function_index('form_nas') . "&NAS_ID=$nas_row->[0]")
      . ":$nas_row->[3]:$_TOTAL: $total ("
      . $html->button("Zap $_SESSIONS", "index=$index&zapall=1&NAS_ID=$nas_row->[0]", { MESSAGE => "Do you realy want zap all sessions on NAS '$nas_row->[0]' ?" }) . ') '
      . $html->button("", "#", { IMG => ':chart_16.png', IMG_ALT => "$_GRAPH $_NAS", NEW_WINDOW => ((-f '../graphics.cgi') ? "../graphics.cgi?NAS_ID=$nas_row->[0]&DAILY=1&NAS_TYPE=$nas_row->[4]" : "index.cgi?MODULE=grapher&qindex=-1"), NEW_WINDOW_SIZE => "670:340" }));

    foreach my $line (@$l) {
      undef($table->{rowcolor});
      undef($table->{extra});
      my @rows = ();
      for (my $i = 0 ; $i <= $#ACTIVE_FIELDS ; $i++) {
        my $value = $line->[$i];

        if ( $ACTIVE_FIELDS[$i] == 5
          || $ACTIVE_FIELDS[$i] == 6
          || $ACTIVE_FIELDS[$i] == 7
          || $ACTIVE_FIELDS[$i] == 8)
        {
          $value = int2byte($line->[$i]);
        }
        elsif ($ACTIVE_FIELDS[$i] == 0) {
          my $user_info =
            "$_FIO: $line->[1]\n$_PHONE: $line->[$#ACTIVE_FIELDS+1]\n"
          . "$_TARIF_PLAN: $line->[$#ACTIVE_FIELDS+15]\n"
          . "$_DEPOSIT: $line->[$#ACTIVE_FIELDS+5]\n"
          . "$_CREDIT: $line->[$#ACTIVE_FIELDS+6]\n"
          . "$_SPEED: \n"
          . "SESSION_ID: $line->[$#ACTIVE_FIELDS+13]\n"
          . "CID: $line->[$#ACTIVE_FIELDS+14]\n"
          . "CONNECT_INFO: \n"
          . "UPDATES: $line->[$#ACTIVE_FIELDS+8]";

          if ($line->[ $#ACTIVE_FIELDS + 3 ]) {
            $value = user_ext_menu($line->[ $#ACTIVE_FIELDS + 3 ], $line->[0], { TITLE => $user_info });
          }
          else {
            if ($value =~ /(\!)\s+(.+)/) {
              $values = $html->color_mark($html->b(' !! '), $_COLORS[6]) . $2;
            }
          }

          #Dublicate logins color yelow
          if (defined($dub_logins->{ $line->[0] }) && $dub_logins->{ $line->[0] } > 1) { $table->{rowcolor} = '#FFFF00'; }
        }

        # Dub ports color green
        elsif ($nas_row->[4] ne 'ipcad' && $nas_row->[4] ne 'dhcp' && $ACTIVE_FIELDS[$i] == 2) {
          if (defined($dub_ports->{ $nas_row->[0] }{ $line->[$i] }) && $dub_ports->{ $nas_row->[0] }{ $line->[$i] } > 1) { $table->{rowcolor} = '#00FF40'; }
        }
        elsif ($ACTIVE_FIELDS[$i] == 3) {
          $value = int2ip($line->[$i]);
        }
        push @rows, $value;
      }

      if ($line->[ $#ACTIVE_FIELDS + 9 ] > 3) { $table->{rowcolor} = '#FF0000'; }
      my $zap = $html->button('Z', "index=$index&zap=" . $line->[ $#ACTIVE_FIELDS + 3 ] . '+' . $nas_row->[0] . '+' . $line->[ $#ACTIVE_FIELDS + 12 ] . '+' . $line->[ ($#ACTIVE_FIELDS + 13) ] . $pages_qs, { TITLE => 'Zap', CLASS => 'del', NO_LINK_FORMER => 1 });

      my $hangup = ($FORM{ZAPED}) ? $html->form_input('dellist', "$line->[$#ACTIVE_FIELDS + 13]", { TYPE => 'checkbox' }) : $html->button('H', "index=$index&FRAMED_IP_ADDRESS=$line->[$#ACTIVE_FIELDS+2]&hangup=$nas_row->[0]+$line->[$#ACTIVE_FIELDS + 12]+$line->[$#ACTIVE_FIELDS + 13]+$line->[$#ACTIVE_FIELDS + 11]&UID=$line->[$#ACTIVE_FIELDS+3]$pages_qs", { TITLE => 'Hangup', CLASS => 'off' });

      $table->addrow(@rows, $html->button('P', "index=$index&NAS_ID=$FORM{NAS_ID}&ping=$line->[$#ACTIVE_FIELDS+2]$pages_qs", { TITLE => 'ping', BUTTON => 1 }),
        "$zap", "$hangup", $html->button("$_GRAPH $_USER", "#", { CLASS => 'stats2', NEW_WINDOW => ((-f '../graphics.cgi') ? "../graphics.cgi?LOGIN=$line->[0]&DAILY=1&NAS_TYPE=$nas_row->[4]" : "index.cgi?MODULE=grapher&qindex=-1"), NEW_WINDOW_SIZE => "670:340" }));
    }
  }

  my $output = $table->show();

  if ($FORM{ZAPED}) {
    $output = $html->form_main(
      {
        CONTENT => $output,
        HIDDEN  => {
          index  => "$index",
          ZAPED  => 1,
          NAS_ID => $FORM{NAS_ID}
        },
        SUBMIT => {
          go    => "$_DEL",
          tolog => "$_ADD to LOG"
        },
        METHOD => 'POST',
        NAME   => 'users_list'
      }
    );
  }
  else {
    $output .= dv_online_search(
      {
        FIELDS_ALL    => \@FIELDS_ALL,
        ACTIVE_FIELDS => \@ACTIVE_FIELDS
      }
    );

    $output .=
      $html->button('Zap All', "index=$index&zapall=1", { IMG => ':tech_work.png', MESSAGE => "Do you realy want ZAP all sessions ?" }) . ' '
    . $html->button("$_GRAPH $_NAS",         "#", { IMG => ':chart.png', NEW_WINDOW => ((-f '../graphics.cgi') ? "../graphics.cgi?NAS_ID=all&DAILY=1&NAS_TYPE=$nas_row->[4]" : "index.cgi?MODULE=grapher&qindex=-1"), NEW_WINDOW_SIZE => "675:720" }) . ' '
    . $html->button("$_GRAPH $_TARIF_PLANS", "#", { IMG => ':chart.png', NEW_WINDOW => ((-f '../graphics.cgi') ? "../graphics.cgi?TP_ID=all&DAILY=1&NAS_TYPE=$nas_row->[4]"  : "index.cgi?MODULE=grapher&qindex=-1"), NEW_WINDOW_SIZE => "675:720" }) . ' '
    . $html->button("$_GRAPH $_GROUPS",      "#", { IMG => ':chart.png', NEW_WINDOW => ((-f '../graphics.cgi') ? "../graphics.cgi?GID=all&DAILY=1&NAS_TYPE=$nas_row->[4]"    : "index.cgi?MODULE=grapher&qindex=-1"), NEW_WINDOW_SIZE => "675:720" });
  }

  print $output;
}

#**********************************************************
#
#**********************************************************
sub dv_online_search {
  my ($attr) = @_;

  my $FIELDS_ALL    = $attr->{FIELDS_ALL};
  my $ACTIVE_FIELDS = $attr->{ACTIVE_FIELDS};
  my $table2        = $html->table({ width => '100%' });
  my @arr           = ();
  my $i             = 0;

  foreach my $name (@$FIELDS_ALL) {
    my $ex_info = '';
    push @arr, $html->form_input('fields', "$i", { TYPE => 'checkbox', STATE => (in_array($i, $ACTIVE_FIELDS)) ? 1 : undef }) . ' ' . $html->b($name) . " $ex_info";
    if ($#arr > 2) {
      $table2->addrow(@arr);
      @arr = ();
    }
    $i++;
  }

  if ($#arr > -1) {
    $table2->addrow(@arr);
  }

  my $FIELDS_SEL = $html->form_select(
    'FILTER_FIELD',
    {
      SELECTED     => $FORM{FILTER_FIELD},
      SEL_ARRAY    => $FIELDS_ALL,
      ARRAY_NUM_ID => 1
    }
  );

  my $table = $html->table(
    {
      width       => '100%',
      title_plain => [ " $_FILTERS: " . $html->form_input('FILTER', $FORM{FILTER}) . " $_FIELDS: $FIELDS_SEL" . " $_REFRESH (sec): " . $html->form_input('REFRESH', int($FORM{REFRESH}), { SIZE => 4 }), $html->form_input('SHOW', $_SHOW, { TYPE => 'SUBMIT' }) ],
      cols_align => [ 'center:noprint', 'center:noprint' ],
    }
  );

  return $html->form_main(
    {
      CONTENT => $table2->show() . $table->show(),
      HIDDEN  => {
        index  => "$index",
        NAS_ID => $FORM{NAS_ID}
      },
      METHOD => 'GET'
    }
  );
}

#**********************************************************
# Whow sessions from log
# dv_sessions()
#**********************************************************
sub dv_sessions {
  my ($list, $sessions, $attr) = @_;

  my %ACCT_TERMINATE_CAUSES = (
    '' => '',
    0  => 'Unknown',
    1  => 'User-Request',
    2  => 'Lost-Carrier',
    3  => 'Lost-Service',
    4  => 'Idle-Timeout',
    5  => 'Session-Timeout',
    6  => 'Admin-Reset',
    7  => 'Admin-Reboot',
    8  => 'Port-Error',
    9  => 'NAS-Error',
    10 => 'NAS-Request',
    11 => 'NAS-Reboot',
    12 => 'Port-Unneeded',
    13 => 'Port-Preempted',
    14 => 'Port-Suspended',
    15 => 'Service-Unavailable',
    16 => 'Callback',
    17 => 'User-Error',
    18 => 'Host-Request',
    19 => 'Supplicant-Restart',
    20 => 'Reauthentication-Failure',
    21 => 'Port-Reinit',
    22 => 'Port-Disabled',
    23 => 'Lost-Alive/Billd Calculation'
  );

  if (!$list) {
    if (!defined($FORM{sort})) {
      $LIST_PARAMS{SORT} = 2;
      $LIST_PARAMS{DESC} = 'DESC';
    }

    $sessions->{SEL_NAS} = $html->form_select(
      'NAS_ID',
      {
        SELECTED          => $FORM{NAS_ID},
        SEL_MULTI_ARRAY   => [ [ '', $_ALL ], @{ $Nas->list({%LIST_PARAMS}) } ],
        MULTI_ARRAY_KEY   => 0,
        MULTI_ARRAY_VALUE => 1,
      }
    );

    $sessions->{TERMINATE_CAUSE_SEL} = $html->form_select(
      'TERMINATE_CAUSE',
      {
        SELECTED => $FORM{TERMINATE_CAUSE},
        SEL_HASH => \%ACCT_TERMINATE_CAUSES
      }
    );

    $sessions->{SHOW_TERMINATE_CAUSE} = 'checked' if ($FORM{SHOW_TERMINATE_CAUSE});

    form_search({ SEARCH_FORM => $html->tpl_show(_include('dv_sessions_search', 'Dv'), { %FORM, %$sessions }, { OUTPUT2RETURN => 1 }) });
    if ($FORM{search}) {
      $sessions = Dv_Sessions->new($db, $admin, \%conf);
      $list = $sessions->list({%LIST_PARAMS, COLS_NAME => 1 });
    }
    else {
      return 0;
    }
  }

  if ($sessions->{TOTAL} < 1) {
    $html->message('info', $_INFO, "$_NO_RECORD");
    return 0;
  }

  my @caption = ("$_USER", "$_START", "$_DURATION", "$_TARIF_PLAN", (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : '') . " $_SENT", (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : '') . " $_RECV", "CID", "NAS", "IP", "$_SUM");

  if ($FORM{SHOW_TERMINATE_CAUSE}) {
    push @caption, 'TC';
  }

  if ($FORM{BILL_ID}) {
    push @caption, 'BILL_ID';
  }
 
  if (! $user->{UID}) {
  	push @caption, '-';
  }

  my $table = $html->table(
    {
      width        => '100%',
      caption      => "$_SESSIONS",
      border       => 1,
      title        => [ @caption, '-' ],
      cols_align   => [ 'left', 'right', 'right', 'RIGHT', 'right', 'right', 'right', 'right', 'right', 'right', 'center:noprint', 'center:noprint' ],
      qs           => $pages_qs,
      pages        => $sessions->{TOTAL},
      recs_on_page => $LIST_PARAMS{PAGE_ROWS},
      ID           => 'DV_SESSIONS',
      EXPORT       => "$_EXPORT XML:&xml=1",
    }
  );

  my $delete = '';
  use Billing;
  my $Billing = Billing->new($db, \%conf);

  foreach my $line (@$list) {
    if ($permissions{3}{1}) {# && $LIST_PARAMS{UID}) {
      $delete = $html->button(
        $_DEL,
        "index=". get_function_index('dv_stats') ."$pages_qs&del=$line->{uid}+$line->{acct_session_id}+$line->{nas_id}+$line->{start}+$line->{sum}+$line->{login}",
        { MESSAGE => "$_DEL $_SESSION $_SESSION_ID " . ($line->{acct_session_id}) . "?", 
        	CLASS => 'del', 
        	NO_LINK_FORMER => 1 
        }
      );
    }

    my @rows = ();
    #for (my $i = 1 ; $i <= $sessions->{SEARCH_FIELDS_COUNT} ; $i++) {
      #if ($line->{terminate_cause}) {
        push @rows, $ACCT_TERMINATE_CAUSES{ $line->{terminate_cause} } if ($FORM{SHOW_TERMINATE_CAUSE});
      #        	print "print";
      #}
      #elsif ($line->{bill_id}) {
        push @rows, $line->{bill_id} if ($FORM{BILL_ID});
      #}
    #}

    $table->addrow(
      $html->button($line->{login}, "index=11&UID=$line->{uid}"),
      $line->{start}, 
      $line->{duration}, 
      $line->{tp_id}, 
      int2byte($line->{sent}, { DIMENSION => $FORM{DIMENSION} }),
      int2byte($line->{recv}, { DIMENSION => $FORM{DIMENSION} }),
      $line->{CID}, 
      $line->{nas_id}, 
      $line->{ip},
      $line->{sum}, 
      @rows, 
      $html->button("D", "index=" . get_function_index(($user->{UID}) ? 'dv_user_stats' : 'dv_stats') . "&UID=$line->{uid}" . "&SESSION_ID=$line->{acct_session_id}", { TITLE => "$_DETAIL", CLASS => 'stats' }),
      $delete
    );
  }

  if (! $FORM{EXPORT_CONTENT} && $attr->{OUTPUT2RETURN}) {
    return $table->show();
  }

  print $table->show();
}

#**********************************************************
# dv_use_all_monthes();
#**********************************************************
sub dv_use_allmonthes {

  $FORM{allmonthes} = 1;
  dv_use();
}

#**********************************************************
# dv_use();
#**********************************************************
sub dv_use {

  my %CAPTIONS_HASH = (
    '1:DATE:right'          => $_DATE,
    '2:USERS:left'          => $_USERS,
    '3:USERS_FIO:left'      => $_FIO,
    '4:TP:left'             => $_TARIF_PLAN,
    '5:SESSIONS:right'      => $_SESSIONS,
    '6:TRAFFIC_RECV:right'  => "$_TRAFFIC $_RECV",
    '7:TRAFFIC_SENT:right'  => "$_TRAFFIC $_SENT",
    '8:TRAFFIC_SUM:right'   => $_TRAFFIC,
    '9:TRAFFIC_2_SUM:right' => $_TRAFFIC . " 2",
    '91:DURATION:right'     => $_DURATION,
    '92:SUM:right'          => $_SUM
  );

  my %ACCT_TERMINATE_CAUSES = (
    'Unknown'                      => 0,
    'User-Request'                 => 1,
    'Lost-Carrier'                 => 2,
    'Lost-Service'                 => 3,
    'Idle-Timeout'                 => 4,
    'Session-Timeout'              => 5,
    'Admin-Reset'                  => 6,
    'Admin-Reboot'                 => 7,
    'Port-Error'                   => 8,
    'NAS-Error'                    => 9,
    'NAS-Request'                  => 10,
    'NAS-Reboot'                   => 11,
    'Port-Unneeded'                => 12,
    'Port-Preempted'               => 13,
    'Port-Suspended'               => 14,
    'Service-Unavailable'          => 15,
    'Callback'                     => 16,
    'User-Error'                   => 17,
    'Host-Request'                 => 18,
    'Supplicant-Restart'           => 19,
    'Reauthentication-Failure'     => 20,
    'Port-Reinit'                  => 21,
    'Port-Disabled'                => 22,
    'Lost-Alive/Billd Calculation' => 23
  );

  my %ACCT_TERMINATE_CAUSES_REV = reverse %ACCT_TERMINATE_CAUSES;
  my $i                         = 1;
  my $list                      = $users->config_list({ PARAM => 'ifu*' });
  my %INFO_LISTS                = ();

  foreach my $line (@$list) {
    my $field_id = '';
    if ($line->[0] =~ /ifu(\S+)/) {
      $field_id = $1;
    }

    my ($position, $type, $name) = split(/:/, $line->[1]);

    $CAPTIONS_HASH{ (90 + $i) . ':' . $field_id . ':left' } = $name;

    if ($type == 2) {
      my $list = $users->info_lists_list({ LIST_TABLE => $field_id . '_list' });
      foreach my $line (@$list) {
        $INFO_LISTS{$field_id}{ $line->[0] } = $line->[1];
      }
    }
    $i++;
  }

  my %HIDDEN = ();

  $HIDDEN{COMPANY_ID} = $FORM{COMPANY_ID} if ($FORM{COMPANY_ID});
  $HIDDEN{sid} = $sid if ($FORM{sid});

  reports(
    {
      DATE      => $FORM{DATE},
      REPORT    => '',
      HIDDEN    => \%HIDDEN,
      EX_PARAMS => {
        HOURS => "$_HOURS",
        USERS => "$_USERS"
      },
      EXT_TYPE => {
        TP              => "$_TARIF_PLANS",
        GID             => "$_GROUPS",
        TERMINATE_CAUSE => 'TERMINATE_CAUSE',
        COMPANIES       => $_COMPANIES
      },
      PERIOD_FORM => 1,
      FIELDS      => {%CAPTIONS_HASH},
      XML         => 1,
      EX_INPUTS   => [
        $html->form_select(
          'DIMENSION',
          {
            SELECTED => $FORM{DIMENSION},
            SEL_HASH => {
              ''   => 'Auto',
              'Bt' => 'Bt',
              'Kb' => 'Kb',
              'Mb' => 'Mb',
              'Gb' => 'Gb'
            },
            NO_ID => 1
          }
        )
      ]
    }
  );

  if ($FORM{TP_ID}) {
    $LIST_PARAMS{TP_ID} = $FORM{TP_ID};
    $pages_qs .= "&TP_ID=$FORM{TP_ID}";
  }

  if ($FORM{COMPANY_ID}) {
    $LIST_PARAMS{COMPANY_ID} = $FORM{COMPANY_ID};
    $pages_qs .= "&COMPANY_ID=$FORM{COMPANY_ID}";
  }

  my ($tables_sessions);
  my $output = '';

  my %TP_NAMES    = ();
  my %GROUP_NAMES = ();

  my %DATA_HASH = ();
  my %CHART     = ();
  my %AVG       = (
    MONEY    => 0,
    TRAFFIC  => 0,
    DURATION => 0
  );

  my @CHART_TYPE  = ('column', 'line');
  my @CHART_TYPE2 = ('area',   'area');
  my $graph_type  = '';

  #Day reposrt
  if ($FORM{DATE}) {

    #Used Traffic
    $table_sessions = $html->table(
      {
        width      => '100%',
        caption    => "$_SESSIONS",
        title      => [ "$_DATE", "$_USERS", "$_SESSIONS", "$_TRAFFIC ", "$_TRAFFIC 2", $_DURATION, $_SUM ],
        cols_align => [ 'right', 'left', 'right', 'right', 'right', 'right', 'right' ],
        qs         => $pages_qs,
        ID         => 'DV_REPORTS_SESSIONS'
      }
    );

    if ($FORM{EX_PARAMS} && $FORM{EX_PARAMS} eq 'HOURS') {

      my $list = $sessions->reports({%LIST_PARAMS});
      foreach my $line (@$list) {
        $table_sessions->addrow($html->b($line->[0]), $line->[1], $line->[2], int2byte($line->[3], { DIMENSION => $FORM{DIMENSION} }), int2byte($line->[4], { DIMENSION => $FORM{DIMENSION} }), $line->[5], $html->b($line));

        $AVG{USERS}    = $line->[1]           if ($AVG{USERS} < $line->[1]);
        $AVG{TRAFFIC}  = $line->[3]           if ($AVG{TRAFFIC} < $line->[3]);
        $AVG{DURATION} = time2sec($line->[5]) if ($AVG{DURATION} < time2sec($line->[5]));
        $AVG{MONEY}    = $line->[6]           if ($AVG{MONEY} < $line->[6]);

        if ($line->[0] =~ /(\d+)-(\d+)-(\d+) (\d+)/) {
          $num = $4 + 1;
        }
        elsif ($line->[0] =~ /(\d+)-(\d+)/) {
          $CHART{X_LINE}[$num] = $line->[0];
          $num++;
        }

        $DATA_HASH{USERS}[$num]     = $line->[1];
        $DATA_HASH2{TRAFFIC}[$num]  = $line->[3];
        $DATA_HASH2{DURATION}[$num] = time2sec($line->[5]);
        $DATA_HASH{MONEY}[$num]     = $line->[6];

      }

      $graph_type = 'day_stats';
      $output     = $html->make_charts(
        {
          PERIOD        => $graph_type,
          DATA          => \%DATA_HASH2,
          AVG           => \%AVG,
          TYPE          => [ 'area', 'area' ],
          TRANSITION    => 1,
          OUTPUT2RETURN => 1
        }
      );

    }
    else {
      my $list = $sessions->reports({%LIST_PARAMS});
      foreach my $line (@$list) {
        $table_sessions->addrow($html->b($line->[0]), $html->button("$line->[1]", "index=15&UID=$line->[7]&DATE=$line->[0]"), $line->[2], int2byte($line->[3], { DIMENSION => $FORM{DIMENSION} }), int2byte($line->[4], { DIMENSION => $FORM{DIMENSION} }), $line->[5], $html->b($line->[6]));
      }
    }
  }
  else {

    #Used Traffic
    my @caption     = ();
    my @field_align = ();
    my %fields_hash = ();
    my @fields_arr  = ();

    if ($FORM{FIELDS}) {
      @fields_arr = split(/, /, $FORM{FIELDS});
      foreach my $line (@fields_arr) {
        $fields_hash{$line} = 1;
      }

      my $i = 0;
      foreach my $line (sort keys %CAPTIONS_HASH) {
        my ($k, $val, $align) = split(/:/, $line);

        if ($fields_hash{$val}) {
          push @caption,     $CAPTIONS_HASH{$line};
          push @field_align, $align;
          $fields_arr[$i] = $val;
          $i++;
        }
      }
    }
    else {
      @caption = ("$_DATE", "$_USERS", "$_SESSIONS", "$_TRAFFIC ", "$_TRAFFIC 2", $_DURATION, $_SUM);
      @field_align = ('right', 'right', 'right', 'right', 'right', 'right', 'right');
    }

    $graph_type = 'month_stats';

    if ($FORM{TYPE} eq 'USER') {
      $caption[0] = "$_USER";

      #$caption[1]="$_LOGINS";
    }
    if ($FORM{TYPE} eq 'COMPANIES') {
      $caption[0] = "$_COMPANIES";

      #$caption[1]="$_LOGINS";
    }
    elsif ($FORM{TYPE} eq 'TERMINATE_CAUSE') {
      $caption[0] = "$_ERROR";
      @CHART_TYPE = ('pie');
      $graph_type = 'pie';
    }
    elsif ($FORM{TYPE} eq 'TP') {
      $caption[0] = "$_TARIF_PLAN";
      @CHART_TYPE2 = ('column', 'line');
      $CHART{AXIS_CATEGORY_skip} = 0;
    }
    elsif ($FORM{TYPE} eq 'GID') {
      @CHART_TYPE2 = ('column', 'line');
      $CHART{AXIS_CATEGORY_skip} = 0;

      $caption[0] = "$_GROUPS";
      my $list = $users->groups_list();

      foreach my $line (@$list) {
        $GROUP_NAMES{ $line->[0] } = $line->[1];
      }

    }
    elsif ($FORM{TP_ID}) {
      $caption[0]     = "$_LOGINS";
      $field_align[0] = 'left';
    }

    $table_sessions = $html->table(
      {
        width      => '100%',
        caption    => "$_SESSIONS",
        title      => \@caption,
        cols_align => \@field_align,
        qs         => $pages_qs,
        ID         => 'DV_REPORTS_SESSIONS'
      }
    );

    my $num  = 0;
    my $list = $sessions->reports({%LIST_PARAMS});

    foreach my $line (@$list) {
      my @rows = ();
      if ($FORM{FIELDS}) {
        for (my $i = 0 ; $i <= $#caption ; $i++) {
          if ($fields_arr[$i] =~ /TRAFFIC/) {
            push @rows, int2byte($line->[$i], { DIMENSION => $FORM{DIMENSION} });
          }
          elsif ($fields_arr[$i] =~ /USERS/ || $fields_arr[$i] =~ /USERS_FIO/) {
            push @rows, $html->button("$line->[$i]", "index=11&UID=" . ($line->[ $#fields_arr + 1 ]));
          }
          elsif ($fields_arr[$i] =~ /^_/ && ref($INFO_LISTS{ $fields_arr[$i] }) eq 'HASH') {
            push @rows, ($INFO_LISTS{ $fields_arr[$i] }{ $line->[$i] }) ? $INFO_LISTS{ $fields_arr[$i] }{ $line->[$i] } : '';
          }
          elsif ($fields_arr[$i] =~ 'TP') {
            if (scalar keys %TP_NAMES == 0) {
              my $list = $tariffs->list({ MODULE => 'Dv' });
              foreach my $line (@$list) {
                $TP_NAMES{ $line->[0] } = $line->[1];
              }
            }

            push @rows, $button = (($FORM{TYPE} eq 'TP') ? $line->[0] : $line->[1]) . '. ' . $html->button($TP_NAMES{ (($FORM{TYPE} eq 'TP') ? $line->[0] : $line->[1]) }, "index=$index&TP_ID=" . (($FORM{TYPE} eq 'TP') ? $line->[0] : $line->[1]) . "$pages_qs");
          }
          elsif ($fields_arr[$i] =~ 'GID') {
            push @rows, $button = $line->[0] . '. ' . $html->button($GROUP_NAMES{ $line->[0] }, "index=$index&GID=$line->[0]$pages_qs");
          }
          else {
            push @rows, $line->[$i];
          }
        }
      }
      else {
        my $button = '';
        if ($FORM{TYPE} eq 'USER') {
          $button = $html->button("$line->[0]", "index=11&UID=$line->[7]");
        }
        elsif ($FORM{TYPE} eq 'TP') {
          $button = $line->[0] . '. ' . $html->button($TP_NAMES{ $line->[0] }, "index=$index&TP_ID=$line->[0]$pages_qs");
        }
        elsif ($FORM{TYPE} eq 'COMPANIES') {
          $button = $html->button("$line->[0]", "index=13&COMPANY_ID=$line->[8]");
        }
        elsif ($FORM{TYPE} eq 'GID') {
          $button = $line->[0] . '. ' . $html->button($GROUP_NAMES{ $line->[0] }, "index=$index&GID=$line->[0]$pages_qs");
        }
        elsif ($FORM{TP_ID}) {
          $button = $html->button("$line->[0]", "index=11&$type=$line->[0]&UID=$line->[7]");
        }
        elsif ($FORM{TYPE} eq 'TERMINATE_CAUSE') {
          $button = $html->button($ACCT_TERMINATE_CAUSES_REV{ $line->[0] }, "index=$index&$type=$line->[0]&TERMINATE_CAUSE=$line->[0]$pages_qs");

          $DATA_HASH{TYPE}[ $num + 1 ] = $line->[3];
          $CHART{X_TEXT}[$num] = $line->[0];

          $num++;
        }
        else {
          $button = $html->button("$line->[0]", "index=$index&$type=$line->[0]$pages_qs");
        }

        @rows = ($button, $line->[1], $line->[2], int2byte($line->[3], { DIMENSION => $FORM{DIMENSION} }), int2byte($line->[4], { DIMENSION => $FORM{DIMENSION} }), $line->[5], $html->b($line->[6]));

        if ($FORM{TYPE} ne 'TERMINATE_CAUSE') {
          $AVG{USERS}   = $line->[1] if ($AVG{USERS} < $line->[1]);
          $AVG{TRAFFIC} = $line->[3] if ($AVG{TRAFFIC} < $line->[3]);

          $AVG{DURATION} = time2sec($line->[5]) if ($AVG{DURATION} < time2sec($line->[5]));
          $AVG{MONEY}    = $line->[6]           if ($AVG{MONEY} < $line->[6]);

          if ($line->[0] =~ /(\d+)-(\d+)-(\d+)/) {
            $num = $3;
          }
          elsif ($line->[0] =~ /(\d+)-(\d+)/) {
            $CHART{X_LINE}[$num] = $line->[0];
            $num++;
          }
          else {
            $CHART{X_TEXT}[$num] = $line->[0];
            $num++;
          }

          $DATA_HASH{USERS}[$num]     = $line->[1];
          $DATA_HASH2{TRAFFIC}[$num]  = $line->[3];
          $DATA_HASH2{DURATION}[$num] = time2sec($line->[5]);
          $DATA_HASH{MONEY}[$num]     = $line->[6];
        }

      }

      $table_sessions->addrow(@rows);

    }

    if ($graph_type ne 'pie') {

      $output = $html->make_charts(
        {
          PERIOD => $graph_type,
          DATA   => \%DATA_HASH2,
          AVG    => \%AVG,

          TYPE          => \@CHART_TYPE2,
          TRANSITION    => 1,
          OUTPUT2RETURN => 1,
          %CHART
        }
      );

      #%CHART = ();
    }

  }

  $table = $html->table(
    {
      width      => '100%',
      cols_align => [ 'right', 'right', 'right', 'right', 'right', 'right' ],
      rows       => [
        [
          "$_USERS: " . $html->b($sessions->{USERS}),
          "$_SESSIONS: " . $html->b($sessions->{SESSIONS}),
          "$_TRAFFIC: " 
          . $html->b(int2byte($sessions->{TRAFFIC})) 
          . $html->br()
          . "$_TRAFFIC IN: "
          . $html->b(int2byte($sessions->{TRAFFIC_IN}))
          . $html->br()
          . "$_TRAFFIC OUT: "
          . $html->b(int2byte($sessions->{TRAFFIC_OUT}))
          ,

          "$_TRAFFIC 2: " . $html->b(int2byte($sessions->{TRAFFIC_2})) . $html->br() . "$_TRAFFIC 2 IN: " . $html->b(int2byte($sessions->{TRAFFIC_2_IN})) . $html->br() . "$_TRAFFIC 2 OUT: " . $html->b(int2byte($sessions->{TRAFFIC_2_OUT})),

          "$_DURATION: " . $html->b($sessions->{DURATION}),
          "$_SUM: " . $html->b($sessions->{SUM})
        ]
      ],
      rowcolor => 'even'
    }
  );

  print $table_sessions->show() . $table->show();

  $table = $html->table({ rows => [ [$output] ] });
  print $table->show();

  if ($graph_type ne '') {
    $html->make_charts(
      {
        PERIOD     => $graph_type,
        DATA       => \%DATA_HASH,
        AVG        => \%AVG,
        TYPE       => \@CHART_TYPE,
        TRANSITION => 1,
        %CHART
      }
    );

  }

}

#**********************************************************
# dv_error
#**********************************************************
sub dv_error {
  my ($attr)    = @_;
  my $PAGE_ROWS = 25;
  my $login     = '';

  my %log_levels_rev = reverse %log_levels;
  my @ACTIONS = ('', 'AUTH', 'ACCT', 'HANGUP', 'CALCULATION', 'CMD', 'LOST_ALIVE');

  if ($attr->{USER_INFO}) {
    my $user = $attr->{USER_INFO};
    $login = $user->{LOGIN};
    $LIST_PARAMS{LOGIN_EXPR} = $user->{LOGIN};
  }
  elsif ($FORM{LOGIN}) {
    $login = $FORM{LOGIN};
    $LIST_PARAMS{LOGIN_EXPR} = $FORM{LOGIN};
    $pages_qs .= "&LOGIN=$FORM{LOGIN}";
  }
  elsif ($FORM{UID}) {
    dv_users();
    return 0;
  }

  #Sql Part
  if ($conf{ERROR2DB}) {
    my %nas_ids = (
      '' => '',
      0  => 'UNKNOWN',
    );

    my $list = $Nas->list();
    foreach my $line (@$list) {
      $nas_ids{ $line->[0] } = $line->[1];
    }

    $Dv->{LOG_TYPE_SEL} = $html->form_select(
      'LOG_TYPE',
      {
        SELECTED => $FORM{LOG_TYPE},
        SEL_HASH => { '' => '', %log_levels_rev },
        NO_ID    => 1
      }
    );

    $Dv->{NAS_ID_SEL} = $html->form_select(
      'NAS_ID',
      {
        SELECTED => $FORM{NAS_ID},
        SEL_HASH => \%nas_ids,
        NO_ID    => 1
      }
    );

    $Dv->{ACTIONS_SEL} = $html->form_select(
      'ACTION',
      {
        SELECTED  => $FORM{ACTION},
        SEL_ARRAY => \@ACTIONS,
      }
    );

    form_search({ SEARCH_FORM => $html->tpl_show(_include('dv_errors_search', 'Dv'), { %FORM, %$Dv }, { OUTPUT2RETURN => 1 }) });

    if (!$FORM{sort}) {
      $LIST_PARAMS{SORT} = 1;
      $LIST_PARAMS{DESC} = DESC;
    }

    if ($FORM{search}) {
      $LIST_PARAMS{INTERVAL} = "$FORM{FROM_DATE}/$FORM{TO_DATE}";
    }

    $list = $Log->log_list({%LIST_PARAMS});
    my $table = $html->table(
      {
        caption    => $_TOTAL,
        width      => '100%',
        cols_align => [ 'right', 'right' ],
      }
    );

    my $total = 0;
    foreach my $line (@{ $Log->{list} }) {
      $table->addrow($log_levels_rev{ $line->[0] }, $line->[1]);
      $total += $line->[1];
    }

    $table->addrow($_TOTAL, $total);

    print $table->show();

    $table = $html->table(
      {
        caption => "$_ERROR",
        width   => '100%',
        title   => [ $_DATE, "$_TYPE", "$_ACTION", "$_USER", "$_TEXT", "NAS" ],
        pages   => $total,
        qs      => $pages_qs,
        ID      => 'DV_ERRORS'
      }
    );

    foreach my $line (@$list) {
      $table->addrow($line->[0], $log_levels_rev{ $line->[1] }, $line->[2], $html->button($line->[3], "index=11&LOGIN=$line->[3]"), ($line->[1] < 5) ? $html->color_mark($line->[4], "$_COLORS[6]") : $line->[4], $nas_ids{ $line->[5] });
    }

    print $table->show();
  }

  #File part
  if (!-f $conf{LOGFILE}) {
    $html->message('info', $_INFO, "'$conf{LOGFILE}' $_NOT_EXIST");
    return 0;
  }

  if (defined($FORM{LOG_TYPE})) {
    $pages_qs .= "&LOG_TYPE=$FORM{LOG_TYPE}";
  }

  my ($list, $types, $totals) = show_log(
    "$login",
    "$conf{LOGFILE}",
    {
      DATE      => $FORM{DATE},
      LOG_TYPE  => $log_levels_rev{ $FORM{LOG_TYPE} },
      PG        => $PG,
      PAGE_ROWS => 25                                    #$PAGE_ROWS
    }
  );

  my $table = $html->table(
    {
      caption => "System $_ERROR",
      width   => '100%',
      pages   => $totals,
      qs      => $pages_qs,
      ID      => 'DV_ERRORS'
    }
  );

  foreach my $line (@$list) {
    if ($line =~ m/LOG_WARNING/i) {
      $line = $html->color_mark($line, $_COLORS[6]);
    }

    $table->addrow($line);
  }
  print $table->show();

  $table = $html->table(
    {
      width      => '100%',
      cols_align => [ 'right', 'right' ]
    }
  );

  $table->addrow($html->button("$_TOTAL", "index=$index&$pages_qs"), $totals);
  while (my ($k, $v) = each %$types) {
    $table->addrow($html->button($k, "index=$index&LOG_TYPE=$k$pages_qs"), $v);
  }

  $table->addrow($_SIZE, int2byte((-s $conf{LOGFILE}))) if ($login eq '');

  print $table->show();

}

#**********************************************************
# stats
#**********************************************************
sub dv_stats {
  my ($attr) = @_;

  if (defined($attr->{USER_INFO})) {
    my $user = $attr->{USER_INFO};

    $UID = $user->{UID};
    $LIST_PARAMS{UID} = $UID;
    if (!defined($FORM{sort})) {
      $LIST_PARAMS{SORT} = 2;
      $LIST_PARAMS{DESC} = DESC;
    }

    if (defined($FORM{OP_SID}) and $FORM{OP_SID} eq $COOKIES{OP_SID}) {
      $html->message('err', $_ERROR, "$_EXIST $FORM{OP_SID} eq $COOKIES{OP_SID}");
    }
    elsif ($FORM{bm}) {
      use Bills;
      my $Bill = Bills->new($db);
      $Bill->action('add', "$FORM{BILL_ID}", $FORM{sum});
      if ($bill->{errno}) {
        $html->message('err', $_ERROR, "[$bill->{errno}] $err_strs{$bill->{errno}}");
      }
      else {
        $html->message('info', $_INFO, "$_ADDED: SUM $FORM{sum}, BILL_ID: $FORM{BILL_ID}");
      }
    }
    elsif ($FORM{SESSION_ID}) {
      $pages_qs .= "&SESSION_ID=$FORM{SESSION_ID}";
      dv_session_detail({ USER_INFO => $attr->{USER_INFO} });
      return 0;
    }
  }
  elsif ($FORM{UID}) {
  	$LIST_PARAMS{UID} = $FORM{UID};
  }


  if ($FORM{del} && $FORM{is_js_confirmed}) {
    if (!defined($permissions{3}{1})) {
      $html->message('err', $_ERROR, 'ACCESS DENY');
      return 0;
    }

    my ($UID, $session_id, $nas_id, $session_start_date, $session_start_time, $sum, $login) = split(/ /, $FORM{del}, 7);
    $sessions->del($UID, $session_id, $nas_id, "$session_start_date $session_start_time");
    if (!$sessions->{errno}) {
      my $table = $html->table(
        {
          width => '100%',
          rows  => [ [ "$_LOGIN", $login ], [ 'SESSION_ID', $session_id ], [ 'NAS_ID', $nas_id ], [ 'SESSION_START', "$session_start_date $session_start_time" ], [ $_SUM, $sum ] ]
        }
      );

      $html->message('info', $_DELETED, $table->show());
      form_back_money('log', $sum, { UID => $UID });    #
      return 0;
    }
  }

  if ($sessions->{errno}) {
    $html->message('err', $_ERROR, "[$sessions->{errno}] $err_strs{$sessions->{errno}}");
  }

  $Dv->info($FORM{UID});

  #Join Service
  if ($users->{COMPANY_ID}) {
    if ($Dv->{JOIN_SERVICE}) {
      my @uids = ();
      my $list = $Dv->list(
          {
            JOIN_SERVICE => ($Dv->{JOIN_SERVICE}==1) ? $Dv->{UID} : $Dv->{JOIN_SERVICE},
            COMPANY_ID   => $attr->{USER_INFO}->{COMPANY_ID},
            PAGE_ROWS    => 10000,
            COLS_NAME    => 1
          }
        );

      foreach my $line (@$list) {
      	if ($Dv->{JOIN_SERVICE} == 1) {
          $Dv->{JOIN_SERVICES_USERS} .= $html->button("$line->{id}", "&index=$index&UID=$line->{uid}", { BUTTON => 1 }) . ' ';
        }

        push @uids, $line->{uid};
      }

      $LIST_PARAMS{UIDS} = ($Dv->{JOIN_SERVICE} > 1) ? $Dv->{JOIN_SERVICE} : $FORM{UID};
      $LIST_PARAMS{UIDS} .= ',' . join(', ', @uids) if ($#uids > -1);

      if ($Dv->{JOIN_SERVICE} > 1) {
        $Dv->{JOIN_SERVICES_USERS} .= $html->button("$_MAIN", "index=$index&UID=$Dv->{JOIN_SERVICE}", { BUTTON => 1 }) . ' ';
      }

      my $table = $html->table(
      {
        width => '100%',
        rows  => [ [ "$_JOIN_SERVICE:", $Dv->{JOIN_SERVICES_USERS} ] ]
      });
      $sessions->{JOIN_SERVICE_STATS} .= $table->show();
    }
  }

  if ($FORM{rows}) {
    $LIST_PARAMS{PAGE_ROWS} = $FORM{rows};
    $conf{list_max_recs}    = $FORM{rows};
    $pages_qs .= "&rows=$conf{list_max_recs}";
  }

  if (!$LIST_PARAMS{UID} && $FORM{LOGIN}) {
    my $users = Users->new($db, $admin, \%conf);
    my $list = $users->list({ LOGIN => $FORM{LOGIN}, COLS_NAME => 1 });
    if ($users->{TOTAL} == 1) {
      $LIST_PARAMS{UID}      = $list->[0]->{uid};
      $FORM{UID}             = $LIST_PARAMS{UID};
      $UID                   = $LIST_PARAMS{UID};
      $LIST_PARAMS{ACTIVATE} = $list->[0]->{activate};
    }
    else {
      $html->message('err', $_ERROR, "'$FORM{LOGIN}' $_NOT_EXIST");
      return 0;
    }

    $pages_qs .= "&UID=$LIST_PARAMS{UID}";
  }

  my $list  = $sessions->periods_totals({%LIST_PARAMS});
  my $table = $html->table(
    {
      caption     => "$_PERIOD",
      width       => '100%',
      title_plain => [ "$_PERIOD", "$_DURATION", "$_SEND", "$_RECV", "$_SUM" ],
      cols_align  => [ 'left', 'right', 'right', 'right', 'right' ],
      rowcolor    => 'odd',
      ID          => 'DV_STATS_PERIOD'
    }
  );

  for (my $i = 0 ; $i < 5 ; $i++) {
    $table->addrow($html->button("$PERIODS[$i]", "index=$index&PERIOD=$i$pages_qs"), "$sessions->{'duration_'. $i}", int2byte($sessions->{ 'sent_' . $i }), int2byte($sessions->{ 'recv_' . $i }), int2byte($sessions->{ 'sum_' . $i }));
  }

  $sessions->{PERIOD_STATS} = $table->show();

  $table = $html->table(
    {
      width    => '100%',
      rowcolor => 'row_active',
      rows     => [
        [
          "$_FROM: ",
          $html->date_fld2('FROM_DATE', { MONTHES => \@MONTHES, FORM_NAME => 'stats', WEEK_DAYS => \@WEEKDAYS }),
          "$_TO: ",
          $html->date_fld2('TO_DATE', { MONTHES => \@MONTHES, FORM_NAME => 'stats', WEEK_DAYS => \@WEEKDAYS }),
          $html->form_select(
            'DIMENSION',
            {
              SELECTED => $FORM{DIMENSION},
              SEL_HASH => {
                ''   => 'Auto',
                'Kb' => 'Kb',
                'Mb' => 'Mb',
                'Gb' => 'Gb'
              },
              NO_ID => 1
            }
          ),
          "$_ROWS: ",
          $html->form_input('rows', int($conf{list_max_recs}), { SIZE => 4 }),
          $html->form_input('show', $_SHOW,                    { TYPE => 'submit' })
        ]
      ],
      ID => 'STATS_PERIODS_SEARCH'
    }
  );

  $sessions->{PERIOD_STATS} .= $html->form_main(
    {
      CONTENT => $table->show({ OUTPUT2RETURN => 1 }),
      HIDDEN  => {
        sid   => "$sid",
        index => "$index",
        UID   => "$UID",
      },
      NAME => 'stats'
    }
  );

  if (defined($FORM{show})) {
    $pages_qs .= "&show=1&FROM_DATE=$FORM{FROM_DATE}&TO_DATE=$FORM{TO_DATE}";
    $LIST_PARAMS{INTERVAL} = "$FORM{FROM_DATE}/$FORM{TO_DATE}";
  }
  elsif (defined($FORM{PERIOD})) {
    $LIST_PARAMS{PERIOD} = $FORM{PERIOD};
    $pages_qs .= "&PERIOD=$FORM{PERIOD}";
  }
  elsif ($FORM{DATE}) {
    $LIST_PARAMS{DATE} = $FORM{DATE};
    $pages_qs .= "&DATE=$FORM{DATE}";
  }

  $tariffs->ti_list({ TP_ID => $Dv->{TP_NUM} });
  if ($tariffs->{TOTAL} > 0) {
    $tariffs->tt_list({ TI_ID => $tariffs->{list}->[0]->[0] });
    foreach my $line (@{ $tariffs->{list} }) {
      $TRAFFIC_NAMES{ $line->[0] } = $line->[6];
    }
  }

  #Show rest of prepaid traffic
  if (
    $sessions->prepaid_rest(
      {
        UID  => ($Dv->{JOIN_SERVICE} > 1) ? $Dv->{JOIN_SERVICE} : $LIST_PARAMS{UID},
        UIDS => $LIST_PARAMS{UIDS}
      }
    )
  )
  {

    #Prepaid: period, traffic_type
    my $list  = $sessions->{INFO_LIST};
    my $table = $html->table(
      {
        caption     => "$_PREPAID",
        width       => '100%',
        title_plain => [ "$_TRAFF $_TYPE", "$_BEGIN", "$_END", "$_START", "$_TOTAL (MB)", "$_REST (MB)", "$_OVERQUOTA (MB)" ],
        cols_align  => [ 'left', 'right', 'right', 'right', 'right', 'right', 'right' ],
        rowcolor    => 'odd',
        ID          => 'PREAPID_TRAFIC'
      }
    );

    foreach my $line (@$list) {
    	my $traffic_rest = ($conf{DV_INTERVAL_PREPAID}) ? $sessions->{REST}->{ $line->{interval_id} }->{ $line->{traffic_class} }  :  $sessions->{REST}->{ $line->{traffic_class} };

      $table->addrow(
        $line->{traffic_class} . ':' . (($TRAFFIC_NAMES{ $line->{traffic_class} }) ? $TRAFFIC_NAMES{ $line->{traffic_class} } : ''). 
        ($conf{DV_INTERVAL_PREPAID} ? "/ $line->{interval_id}" : '') ,
        $line->{interval_begin}, 
        $line->{interval_end}, 
        $line->{activate}, 
        $line->{prepaid},
        ($line->{prepaid} > 0 && $traffic_rest > 0) ? $traffic_rest      : 0,
        ($line->{prepaid} > 0 && $traffic_rest < 0) ? abs($traffic_rest) : 0
      );
    }

    $sessions->{PREPAID_INFO} = $table->show();
  }

  $pages_qs .= "&DIMENSION=$FORM{DIMENSION}" if ($FORM{DIMENSION});

  if (!defined($FORM{sort})) {
    $LIST_PARAMS{SORT} = 2;
    $LIST_PARAMS{DESC} = DESC;
  }

  $sessions->{TOTALS_AVG} = dv_stats_calculation($sessions);
  #Session List
  $list = $sessions->list({%LIST_PARAMS, COLS_NAME => 1 });

  if ($sessions->{TOTAL} < 1) {
    $html->message('info', $_INFO, "$_NO_RECORD");
  }

  $table = $html->table(
    {
      caption     => "$_SUM",
      width       => '100%',
      rowcolor    => 'odd',
      title_plain => [
        "$_SESSIONS",
        "$_DURATION",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_SENT",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_RECV",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_SUM",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC 2") . " $_SENT",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC 2") . " $_RECV",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC 2") . " $_SUM",
        "$_SUM"
      ],
      cols_align => [ 'right', 'right', 'right', 'right', 'right', 'right', 'right', 'right', 'right' ],
      rows       => [
        [
          $sessions->{TOTAL},
          $sessions->{DURATION},
          int2byte($sessions->{TRAFFIC_IN},                              { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC_OUT},                             { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC_OUT} + $sessions->{TRAFFIC_IN},   { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_IN},                             { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_OUT},                            { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_OUT} + $sessions->{TRAFFIC2_IN}, { DIMENSION => $FORM{DIMENSION} }),
          $sessions->{SUM}
        ]
      ],
      ID => 'TOTALS_FULL'
    }
  );

  $sessions->{TOTALS_FULL} = $table->show();
  if (-f '../graphics.cgi' || -f 'graphics.cgi') {
    $sessions->{DAILY_GRAPH}  = $html->img("/graphics.cgi?LOGIN=$users->{LOGIN}&DAILY=1&SHOW_GRAPH=1", "$_DAILY $_STATS");
    $sessions->{WEEKLY_GRAPH} = $html->img("/graphics.cgi?LOGIN=$users->{LOGIN}&WEEKLY=1&SHOW_GRAPH=1", "$_WEEKLY $_STATS");
    #$sessions->{MONTHLY_GRAPH} = $html->button('Wheekly Graph', '#', { IMG => '/graphics.cgi?UID=9&WEEKLY=1&SHOW_GRAPH=1' });
  }

  if ($sessions->{TOTAL} > 0) {
    $sessions->{SESSIONS} = dv_sessions($list, $sessions, { OUTPUT2RETURN => 1 });
  }

  $html->tpl_show(_include('dv_stats', 'Dv'), $sessions);
}

#*******************************************************************
# WHERE period
# base_state($where, $period);
#*******************************************************************
sub dv_stats_calculation {
  my ($sessions) = @_;

  $sessions->calculation({%LIST_PARAMS});
  my $table = $html->table(
    {
      width       => '640',
      rowcolor    => 'odd',
      title_plain => [ "-", "$_MIN", "$_MAX", "$_AVG", "$_TOTAL" ],
      cols_align  => [ 'left', 'right', 'right', 'right', 'right' ],
      rows        => [
        [ $_DURATION,         $sessions->{min_dur},            $sessions->{max_dur},            $sessions->{avg_dur},            $sessions->{total_dur} ],
        [ "$_TRAFFIC $_RECV", int2byte($sessions->{min_recv}), int2byte($sessions->{max_recv}), int2byte($sessions->{avg_recv}), int2byte($sessions->{total_recv}) ],
        [ "$_TRAFFIC $_SENT", int2byte($sessions->{min_sent}), int2byte($sessions->{max_sent}), int2byte($sessions->{avg_sent}), int2byte($sessions->{total_sent}) ],
        [ "$_TRAFFIC $_SUM",  int2byte($sessions->{min_sum}),  int2byte($sessions->{max_sum}),  int2byte($sessions->{avg_sum}),  int2byte($sessions->{total_sum}) ]
      ],
      ID => 'DV_TRAFFIC_CALCULATIONS'
    }
  );

  return $table->show();
}

#**********************************************************
# form_stats
#**********************************************************
sub dv_user_stats {
  if (defined($FORM{SESSION_ID})) {
    $pages_qs .= "&SESSION_ID=$FORM{SESSION_ID}";
    dv_session_detail({ LOGIN => $LIST_PARAMS{LOGIN} });
    return 0;
  }

  if ($sessions->{errno}) {
    $html->message('err', $_ERROR, "[$sessions->{errno}] $err_strs{$sessions->{errno}}");
  }

  #Join Service
  if ($user->{COMPANY_ID}) {
    if ($FORM{COMPANY_ID}) {
      $users = Users->new($db, $admin, \%conf);
      dv_use();
      return 0;
    }

    use Customers;
    my $customer = Customers->new($db, $admin, \%conf);
    my $company  = $customer->company();
    my $ulist    = $company->admins_list(
      {
        COMPANY_ID => $user->{COMPANY_ID},
        UID        => $UID
      }
    );

    if ($company->{TOTAL} > 0 && $ulist->[0]->[0] > 0) {
      $Dv->{JOIN_SERVICES_USERS} = $html->button("$_COMPANY", "&sid=$sid&index=$index&COMPANY_ID=$user->{COMPANY_ID}", { BUTTON => 1 }) . ' ';
    }

    $Dv->info($UID);

    if ($Dv->{JOIN_SERVICE}) {
      my $list = $Dv->list(
        {
          JOIN_SERVICE => ($Dv->{JOIN_SERVICE}==1) ? $UID : $Dv->{JOIN_SERVICE}, 
          COMPANY_ID   => $attr->{USER_INFO}->{COMPANY_ID},
          PAGE_ROWS    => 1000,
          COLS_NAME    => 1
        }
      );

      if ($Dv->{JOIN_SERVICE} == 1) {
        $Dv->{JOIN_SERVICES_USERS} .= (!$FORM{JOIN_STATS}) ? $html->b("$_ALL $_USERS") . ' :: '
                 : $html->button("$_ALL", "&sid=$sid&index=$index&JOIN_STATS=" . $line->{uid}, { BUTTON => 1 }) . ' ';
      }
      #elsif ($Dv->{JOIN_SERVICE} > 1) {
      #  $Dv->{JOIN_SERVICES_USERS} .= $html->button("$_MAIN", "index=$index&UID=$Dv->{JOIN_SERVICE}", { BUTTON => 1 });
      #}

      foreach my $line (@$list) {
        if ($FORM{JOIN_STATS} && $FORM{JOIN_STATS} == $line->{uid}) {
          $Dv->{JOIN_SERVICES_USERS} .= $html->b($line->{id}) . ' ';
          $UID = $FORM{JOIN_STATS};
        }
        elsif($Dv->{JOIN_SERVICE} == 1) {
          $Dv->{JOIN_SERVICES_USERS} .= $html->button("$line->{id}", "&sid=$sid&index=$index&JOIN_STATS=" . $line->{uid}, { BUTTON => 1 }) . ' ';
        }

        push @uids, $line->{uid};
      }

      $LIST_PARAMS{UIDS}  = ($Dv->{JOIN_SERVICE} > 1) ? $Dv->{JOIN_SERVICE} : $UID;
      $LIST_PARAMS{UIDS} .= ',' . join(', ', @uids) if ($#uids > -1 && !$FORM{JOIN_STATS});
    }

    my $table = $html->table(
      {
        width => '100%',
        rows  => [ [ "$_JOIN_SERVICE: ", $Dv->{JOIN_SERVICES_USERS} ] ]
      }
    );
    $sessions->{JOIN_SERVICE_STATS} .= $table->show();
  }

  if ($FORM{rows}) {
    $LIST_PARAMS{PAGE_ROWS} = $FORM{rows};
    $LIST_PARAMS{PG}        = $FORM{pg};
    $conf{list_max_recs}    = $FORM{rows};
    $pages_qs .= "&rows=$conf{list_max_recs}";
  }

  #online sessions
  my $list = $sessions->online(
    {
      USER_NAME => $LIST_PARAMS{LOGIN},
      FIELDS    => [ 0, 3, 9, 4, 5, 6 ]
    }
  );

  if ($sessions->{TOTAL} > 0) {
    my $table = $html->table(
      {
        caption     => "Online",
        width       => '100%',
        title_plain => [ "$_LOGIN", "IP", "CID", "$_DURATION", "$_RECV", "$_SEND" ],
        cols_align  => [ 'left', 'right', 'right', 'right', 'right', 'right' ],
        rowcolor    => 'odd',
        ID          => 'ONLINE'
      }
    );

    foreach my $line (@$list) {
      $table->addrow($line->[0], int2ip($line->[1]), $line->[2], $line->[3], int2byte($line->[4]), int2byte($line->[5]));
    }
    $sessions->{ONLINE} = $table->show();
  }

  #PEriods totals
  $list = $sessions->periods_totals({%LIST_PARAMS});
  my $table = $html->table(
    {
      caption     => "$_PERIOD",
      width       => '100%',
      title_plain => [ "$_PERIOD", "$_DURATION", "$_SEND", "$_RECV", "$_SUM" ],
      cols_align  => [ 'left', 'right', 'right', 'right', 'right' ],
      rowcolor    => 'odd',
      ID          => 'DV_STATS_PERIOD'
    }
  );

  for (my $i = 0 ; $i < 5 ; $i++) {
    $table->addrow($html->button("$PERIODS[$i]", "index=$index&PERIOD=$i$pages_qs"), "$sessions->{'duration_'. $i}", int2byte($sessions->{ 'sent_' . $i }), int2byte($sessions->{ 'recv_' . $i }), int2byte($sessions->{ 'sum_' . $i }));
  }
  $sessions->{PERIOD_STATS} .= $table->show();

  $table = $html->table(
    {
      width    => '100%',
      rowcolor => 'row_active',
      rows     => [
        [
          "$_FROM: ",
          $html->date_fld2('FROM_DATE', { MONTHES => \@MONTHES, FORM_NAME => 'stats', WEEK_DAYS => \@WEEKDAYS }),
          "$_TO: ",
          $html->date_fld2('TO_DATE', { MONTHES => \@MONTHES, FORM_NAME => 'stats', WEEK_DAYS => \@WEEKDAYS }),
          $html->form_select(
            'DIMENSION',
            {
              SELECTED => $FORM{DIMENSION},
              SEL_HASH => {
                ''   => 'Auto',
                'Kb' => 'Kb',
                'Mb' => 'Mb',
                'Gb' => 'Gb'
              },
              NO_ID => 1
            }
          ),
          "$_ROWS: ",
          $html->form_input('rows', int($conf{list_max_recs}), { SIZE => 4,        OUTPUT2RETURN => 1 }),
          $html->form_input('show', $_SHOW,                    { TYPE => 'submit', OUTPUT2RETURN => 1 })
        ]
      ],
      ID => 'STATS_PERIODS_SEARCH',
    }
  );

  $sessions->{PERIOD_STATS} .= $html->form_main(
    {
      CONTENT => $table->show({ OUTPUT2RETURN => 1 }),
      HIDDEN  => {
        sid   => "$sid",
        index => "$index",
        UID   => "$UID",
        UIDS  => "$FORM{UIDS}",
      },
      NAME => 'stats',
    }
  );

  $Dv->info($user->{UID});
  $tariffs->ti_list({ TP_ID => $Dv->{TP_NUM} });
  if ($tariffs->{TOTAL} > 0) {
    $tariffs->tt_list({ TI_ID => $tariffs->{list}->[0]->[0] });
    foreach my $line (@{ $tariffs->{list} }) {
      $TRAFFIC_NAMES{ $line->[0] } = $line->[6];
    }
  }

  #dv_stats_calculation($sessions);

  if (defined($FORM{show})) {
    $pages_qs .= "&show=1&FROM_DATE=$FORM{FROM_DATE}&TO_DATE=$FORM{TO_DATE}";
    $LIST_PARAMS{INTERVAL} = "$FORM{FROM_DATE}/$FORM{TO_DATE}";
  }
  elsif (defined($FORM{PERIOD})) {
    $LIST_PARAMS{PERIOD} = int($FORM{PERIOD});
    $pages_qs .= "&PERIOD=$FORM{PERIOD}";
  }

  #Show rest of prepaid traffic
  if (
    $sessions->prepaid_rest(
      {
        UID  => ($Dv->{JOIN_SERVICE} > 1) ? $Dv->{JOIN_SERVICE} : $LIST_PARAMS{UID},
        UIDS => $LIST_PARAMS{UIDS}
      }
    )
  )
  {

    my $list  = $sessions->{INFO_LIST};
    my $table = $html->table(
      {
        caption     => "$_PREPAID",
        width       => '100%',
        title_plain => [ "$_TRAFF $_TYPE", "$_BEGIN", "$_END", "$_START", "$_TOTAL (MB)", "$_REST (MB)", "$_OVERQUOTA (MB)" ],
        cols_align  => [ 'left', 'right', 'right', 'right', 'right', 'right', 'right' ],
        rowcolor    => 'odd',
        ID          => 'DV_STATS_PREPAID'
      }
    );

    foreach my $line (@$list) {
    	my $traffic_rest = ($conf{DV_INTERVAL_PREPAID}) ? $sessions->{REST}->{ $line->{interval_id} }->{ $line->{traffic_class} }  :  $sessions->{REST}->{ $line->{traffic_class} };

      $table->addrow(
        $line->{traffic_class} . ':' . (($TRAFFIC_NAMES{ $line->{traffic_class} }) ? $TRAFFIC_NAMES{ $line->{traffic_class} } : ''). 
        ($conf{DV_INTERVAL_PREPAID} ? "/ $line->{interval_id}" : '') ,
        $line->{interval_begin}, 
        $line->{interval_end}, 
        $line->{activate}, 
        $line->{prepaid},
        ($line->{prepaid} > 0 && $traffic_rest > 0) ? $traffic_rest      : 0,
        ($line->{prepaid} > 0 && $traffic_rest < 0) ? abs($traffic_rest) : 0
      );
    }

    $sessions->{PREPAID_INFO} = $table->show();
  }

  $pages_qs .= "&DIMENSION=$FORM{DIMENSION}" if ($FORM{DIMENSION});

  #Session List
  if (!$FORM{sort}) {
    $LIST_PARAMS{SORT} = 2;
    $LIST_PARAMS{DESC} = 'DESC';
  }

  $list  = $sessions->list({%LIST_PARAMS, COLS_NAME => 1 });
  $table = $html->table(
    {
      caption     => "$_SUM",
      width       => '100%',
      rowcolor    => 'odd',
      title_plain => [
        "$_SESSIONS",
        "$_DURATION",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_SENT",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_RECV",
        (($TRAFFIC_NAMES{0}) ? $TRAFFIC_NAMES{0} : "$_TRAFFIC") . " $_SUM",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC") . " $_SENT",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC") . " $_RECV",
        (($TRAFFIC_NAMES{1}) ? $TRAFFIC_NAMES{1} : "$_TRAFFIC") . " $_SUM",
        "$_SUM"
      ],

      cols_align => [ 'right', 'right', 'right', 'right' ],
      rows       => [
        [
          $sessions->{TOTAL},
          $sessions->{DURATION},
          int2byte($sessions->{TRAFFIC_IN},                              { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC_OUT},                             { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC_OUT} + $sessions->{TRAFFIC_IN},   { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_IN},                             { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_OUT},                            { DIMENSION => $FORM{DIMENSION} }),
          int2byte($sessions->{TRAFFIC2_OUT} + $sessions->{TRAFFIC2_IN}, { DIMENSION => $FORM{DIMENSION} }),
          $sessions->{SUM}
        ]
      ]
    }
  );

  $sessions->{TOTALS_FULL} = $table->show();

  if (-f '../graphics.cgi' || -f 'graphics.cgi') {
    $sessions->{DAILY_GRAPH}  = $html->img('/graphics.cgi?LOGIN=' . $LIST_PARAMS{LOGIN} . '&DAILY=1&SHOW_GRAPH=1', "$_DAILY $_STATS" );
    $sessions->{WEEKLY_GRAPH} = $html->img('/graphics.cgi?LOGIN=' . $LIST_PARAMS{LOGIN} . '&WEEKLY=1&SHOW_GRAPH=1', "$_WEEKLY $_STATS");

    #$sessions->{MONTHLY_GRAPH} = $html->button('Wheekly Graph', '#', { IMG => '/graphics.cgi?UID=9&WEEKLY=1&SHOW_GRAPH=1' });
  }

  $sessions->{SESSIONS} = dv_sessions($list, $sessions, { OUTPUT2RETURN => 1 }) if ($sessions->{TOTAL} > 0);

  $html->tpl_show(_include('dv_stats', 'Dv'), $sessions);
}

#**********************************************************
# dv_session_detail
#**********************************************************
sub dv_session_detail {
  my ($attr) = @_;
  my $user;

  if (defined($attr->{USER_INFO})) {
    $user = $attr->{USER_INFO};
    $LIST_PARAMS{LOGIN} = $user->{LOGIN};

    if ($FORM{RECALC}) {
      $sessions->session_detail({%FORM});

      use Billing;
      my $Billing = Billing->new($db, $CONF);

      my ($UID, $SUM, $BILL_ID, $TARIF_PLAN, $TIME_TARIF, $TRAF_TARIF) = $Billing->session_sum(
        $sessions->{LOGIN},
        $sessions->{START_UNIXTIME},
        $sessions->{DURATION},
        {
          OUTBYTE  => $sessions->{SENT},
          INBYTE   => $sessions->{RECV},
          OUTBYTE2 => $sessions->{SENT2},
          INBYTE2  => $sessions->{RECV2}
        },
        {
          disable_rt_billing => 1,
          TP_NUM             => $sessions->{TP_ID}
        }
      );

      my $change = '';

      if ($sessions->{SUM} != $SUM) {
        $change = "$_CHANGE  " . $html->button($_YES, "index=$index&RECALC=1&SESSION_ID=$FORM{SESSION_ID}&UID=$FORM{UID}&change=1", { BUTTON => 1 }) . ' ?';

        if ($FORM{change}) {
          use Bills;
          my $Bill = Bills->new($db);
          $Bill->action('add',  "$sessions->{BILL_ID}", $sessions->{SUM}) if ($sessions->{SUM});
          $Bill->action('take', "$sessions->{BILL_ID}", $SUM)             if ($SUM > 0);

          $sessions->query($db, "UPDATE dv_log SET sum='$SUM' WHERE acct_session_id='$sessions->{SESSION_ID}';", 'do');

          if ($bill->{errno}) {
            $html->message('err', $_ERROR, "[$bill->{errno}] $err_strs{$bill->{errno}}");
          }
          else {
            $html->message('info', $_INFO, "$_ADDED: SUM $FORM{sum}, BILL_ID: $FORM{BILL_ID}");
          }
          $change = "$_CHANGED";
        }
      }

      $html->message('info', "$_RECALCULATE", "$_TARIF_PLAN: $TARIF_PLAN, $_SUM: $sessions->{SUM} -> $SUM  $change");
    }

  }
  elsif (defined($LIST_PARAMS{LOGIN})) {

  }
  elsif ($FORM{UID}) {
    dv_user();
    return 0;
  }

  my %ACCT_TERMINATE_CAUSES = (
    'Unknown'                      => 0,
    'User-Request'                 => 1,
    'Lost-Carrier'                 => 2,
    'Lost-Service'                 => 3,
    'Idle-Timeout'                 => 4,
    'Session-Timeout'              => 5,
    'Admin-Reset'                  => 6,
    'Admin-Reboot'                 => 7,
    'Port-Error'                   => 8,
    'NAS-Error'                    => 9,
    'NAS-Request'                  => 10,
    'NAS-Reboot'                   => 11,
    'Port-Unneeded'                => 12,
    'Port-Preempted'               => 13,
    'Port-Suspended'               => 14,
    'Service-Unavailable'          => 15,
    'Callback'                     => 16,
    'User-Error'                   => 17,
    'Host-Request'                 => 18,
    'Supplicant-Restart'           => 19,
    'Reauthentication-Failure'     => 20,
    'Port-Reinit'                  => 21,
    'Port-Disabled'                => 22,
    'Lost-Alive/Billd Calculation' => 23
  );

  my %ACCT_TERMINATE_CAUSES_VALUE = reverse %ACCT_TERMINATE_CAUSES;

  $sessions->session_detail({%FORM});

  $sessions->{ACCT_TERMINATE_CAUSE} = "$sessions->{ACCT_TERMINATE_CAUSE} : " . $ACCT_TERMINATE_CAUSES_VALUE{ $sessions->{ACCT_TERMINATE_CAUSE} };

  $sessions->{_SENT}  = int2byte($sessions->{SENT});
  $sessions->{_RECV}  = int2byte($sessions->{RECV});
  $sessions->{_RECV2} = int2byte($sessions->{SENT2});
  $sessions->{_SENT2} = int2byte($sessions->{RECV2});
  $sessions->{RECALC} = $html->button($_RECALCULATE, "index=$index&RECALC=1&SESSION_ID=$FORM{SESSION_ID}&UID=$FORM{UID}", { BUTTON => 1 });

  $Dv->info($FORM{UID});
  $tariffs->ti_list({ TP_ID => $Dv->{TP_NUM} });
  if ($tariffs->{TOTAL} > 0) {
    $tariffs->tt_list({ TI_ID => $tariffs->{list}->[0]->[0] });
    foreach my $line (@{ $tariffs->{list} }) {
      $TRAFFIC_NAMES{ $line->[0] } = $line->[6];
    }
  }

  $html->tpl_show(
    _include('dv_session_detail', 'Dv'),
    {
      %$sessions,
      TRAFFIC_NAMES_0 => $TRAFFIC_NAMES{0},
      TRAFFIC_NAMES_1 => $TRAFFIC_NAMES{1}
    }
  );

  my %ORDERS = (
    hours    => $_HOURS,
    days     => $_DAYS,
    sessions => $_SESSIONS
  );

  print $html->form_main(
    {
      CONTENT => $html->form_select(
        'PERIOD',
        {
          SELECTED => $FORM{PERIOD},
          SEL_HASH => \%ORDERS,
          NO_ID    => 1
        }
      )
      . "SESSION_ID:"
      .

      $html->form_select(
        'SESSION_ID',
        {
          SELECTED    => "$FORM{SESSION_ID}",
          SEL_OPTIONS => {
            $FORM{SESSION_ID} => "$FORM{SESSION_ID}",
            '0'               => "$_ALL"
          },
          NO_ID => 1
        }
      )

      ,
      HIDDEN => {
        index => "$index",
        UID   => "$UID"
      },
      SUBMIT => { SHOW => "$_SHOW" }
    }
  );

  $pages_qs .= "&PERIOD=$FORM{PERIOD}" if (defined($FORM{PERIOD}));

  #Log intervals
  my $list = $sessions->list_log_intervals({ ACCT_SESSION_ID => $FORM{SESSION_ID} });
  if ($sessions->{TOTAL} > 0) {
    my $table = $html->table(
      {
        width      => '100%',
        caption    => "$_INTERVALS",
        border     => 1,
        title      => [ "$_INTERVAL", "$_TRAFFIC", "$_SENT", "$_RECV", "$_DURATION", "$_SUM" ],
        cols_align => [ 'right', 'right', 'right', 'right', 'right', 'right', 'right' ],
        qs         => $pages_qs,
        ID         => 'DV_SESSION_DETAIL'
      }
    );

    foreach my $line (@$list) {
      $table->addrow($line->[0], $line->[1], int2byte($line->[2]), int2byte($line->[3]), $line->[4], $line->[5]);
    }

    print $table->show();
  }

  #Log detail list
  if (!$FORM{sort}) {
    $LIST_PARAMS{SORT} = 1;
    $LIST_PARAMS{DESC} = 'DESC';
  }

  $list = $sessions->detail_list({ %LIST_PARAMS, %FORM });
  my $table = $html->table(
    {
      width      => '100%',
      border     => 1,
      title      => [ "LAST_UPDATE", "$_SESSION_ID", "NAS ID", "$_ SENT", "$_RECV", "$_SENT 2", "$_RECV 2", "$_SUM" ],
      cols_align => [ 'right', 'right', 'right', 'right', 'right', 'right', 'right', 'right' ],
      pages      => $sessions->{TOTAL},
      qs         => $pages_qs,
      ID         => 'DETAIL_LIST'
    }
  );

  foreach my $line (@$list) {
    $table->addrow($line->[0], $html->button($line->[1], "index=$index&UID=$UID&SESSION_ID=$line->[1]"), $line->[2], int2byte($line->[3]), int2byte($line->[4]), int2byte($line->[5]), int2byte($line->[6]), $line->[7]);
  }

  print $table->show();

  $table = $html->table(
    {
      width      => '100%',
      cols_align => [ 'right', 'right' ],
      rows       => [ [ "$_TOTAL:", $html->b($sessions->{TOTAL}) ] ]
    }
  );
  print $table->show();
}

#**********************************************************
# dv_user_info
#**********************************************************
sub dv_user_chg_tp {
  my ($attr) = @_;

  my $Shedule = Shedule->new($db, $admin, \%conf);
  my $period = $FORM{period} || 0;

  if (!$conf{DV_USER_CHG_TP}) {
    $html->message('err', "$_CHANGE $_TARIF_PLAN", "$_NOT_ALLOW", { ID => 140 });
    return 0;
  }

  if ($LIST_PARAMS{UID}) {
    $Dv = $Dv->info($LIST_PARAMS{UID});
    if ($Dv->{TOTAL} < 1) {
      $html->message('info', $_INFO, "$_NOT_ACTIVE", { ID => 22 });
      return 0;
    }
  }
  else {
    $html->message('err', $_ERROR, "$_USER_NOT_EXIST", { ID => 19 });
    return 0;
  }

  if ($conf{FEES_PRIORITY} =~ /bonus/ && $user->{EXT_BILL_DEPOSIT}) {
    $user->{DEPOSIT} += $user->{EXT_BILL_DEPOSIT};
  }
  my %CHANGE_PARAMS = ();

  #Get TP groups
  $tariffs->tp_group_info($Dv->{TP_GID});
  if (!$tariffs->{USER_CHG_TP}) {
    $html->message('err', "$_CHANGE $_TARIF_PLAN", "$_NOT_ALLOW", { ID => 140 });
    return 0;
  }

  #Get next abon day
  if (
       $Dv->{MONTH_ABON} > 0
    && !$Dv->{STATUS}
    && !$user->{DISABLE}
    && ( $user->{DEPOSIT} + $user->{CREDIT} > 0
      || $Dv->{POSTPAID_ABON}
      || $Dv->{PAYMENT_TYPE} == 1)
  )
  {

    if ($user->{ACTIVATE} ne '0000-00-00') {
      my ($Y, $M, $D) = split(/-/, $user->{ACTIVATE}, 3);
      $M--;
      $Dv->{ABON_DATE} = strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, $M, ($Y - 1900), 0, 0, 0) + 31 * 86400 + (($conf{START_PERIOD_DAY}) ? $conf{START_PERIOD_DAY} * 86400 : 0))));
    }
    else {
      my ($Y, $M, $D) = split(/-/, $DATE, 3);

      if ($conf{START_PERIOD_DAY} && $conf{START_PERIOD_DAY} > $D) {
        $D = $conf{START_PERIOD_DAY};
      }
      else {
        $M++;
        $D = '01';
      }

      if ($M == 13) {
        $M = 1;
        $Y++;
      }

      $Dv->{ABON_DATE} = sprintf("%d-%02d-%02d", $Y, $M, $D);
    }
  }

  if ($FORM{set}) {
    if (!$FORM{TP_ID} || $FORM{TP_ID} < 1) {
      $html->message('err', "$_ERROR", "$ERR_WRONG_DATA: $_TARIF_PLAN", { ID => 141 });
    }
    elsif ($conf{DV_USER_CHG_TP_NPERIOD}) {
      my ($CUR_Y, $CUR_M, $CUR_D) = split(/-/, $DATE);

      # Get next month
      my ($Y, $M, $D);
      if ($user->{ACTIVATE} eq '0000-00-00') {

        # Get next month
        ($Y, $M, $D) = split(/-/, $DATE, 3);
      }
      else {
        ($Y, $M, $D) = split(/-/, $user->{ACTIVATE}, 3);
      }

      # Renew expired accounts
      if ($user->{EXPIRE} ne '0000-00-00' && $Dv->{TP_AGE} > 0) {
        ($Y, $M, $D) = split(/-/, $user->{EXPIRE});
        my $seltime = POSIX::mktime(0, 0, 0, $D, ($M - 1), ($Y - 1900));

        # REnew expire tarif
        if ($seltime < time()) {
          my $tp_age = $Dv->{TP_INFO}->{AGE};
          my ($EXPIRE_Y, $EXPIRE_M, $EXPIRE_D) = split(/-/, strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $CUR_D, ($CUR_M), ($CUR_Y - 1900), 0, 0, 0) + $tp_age * 86400))));
          $CHANGE_PARAMS{EXPIRE} = "$EXPIRE_Y-$EXPIRE_M-$EXPIRE_D";
          ($Y, $M, $D) = split(/-/, $DATE, 3);
          $Dv->{TP_INFO} = $tariffs->info($FORM{TP_ID});
          goto CHG_TP;
        }
        else {
          ($Y, $M, $D) = split(/-/, strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, ($M), ($Y - 1900), 0, 0, 0) + $tp_age * 86400))));
        }
      }

      if ($Dv->{STATUS} == 5) {

      }

      # For daily fees or moth distribution next day fees
      elsif (!$conf{DV_USER_CHG_TP_NEXT_MONTH} && ($Dv->{MONTH_ABON} == 0 || $Dv->{ABON_DISTRIBUTION})) {
        ($Y, $M, $D) = split(/-/, strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, ($M - 1), ($Y - 1900), 0, 0, 0) + 86400))));
      }
      else {
        if ($user->{ACTIVATE} ne '0000-00-00') {
          ($Y, $M, $D) = split(/-/, strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, ($M - 1), ($Y - 1900), 0, 0, 0) + 30 * 86400))));
        }
        else {
          if ($conf{START_PERIOD_DAY} && $conf{START_PERIOD_DAY} > $D) {
            $D = $conf{START_PERIOD_DAY};
          }
          else {
            $M++;
            if ($M == 13) {
              $M = 1;
              $Y++;
            }
            $D = '01';
          }
        }
      }

      CHG_TP:
      $M = sprintf("%02d", $M);
      $D = sprintf("%02d", $D);
      my $seltime = POSIX::mktime(0, 0, 0, $D, ($M - 1), ($Y - 1900));

      if ($seltime > time()) {
        $Shedule->add(
          {
            UID      => $LIST_PARAMS{UID},
            TYPE     => 'tp',
            ACTION   => $FORM{TP_ID},
            D        => $D,
            M        => $M,
            Y        => $Y,
            MODULE   => 'Dv',
            COMMENTS => "$_FROM: $Dv->{TP_ID}:$Dv->{TP_NAME}"
          }
        );
      }
      else {
        $FORM{UID} = $LIST_PARAMS{UID};
        $FORM{STATUS} = 0 if ($Dv->{STATUS} == 5);
        $Dv->change({%FORM});

        $user->change(
          $LIST_PARAMS{UID},
          {
            ACTIVATE => ($user->{ACTIVATE} ne '0000-00-00') ? "$DATE" : undef,
            UID => $LIST_PARAMS{UID},
            %CHANGE_PARAMS
          }
        );

        if ($user->{errno}) {
          $html->message('err', $_ERROR, "[$user->{errno}] $err_strs{$user->{errno}}", { ID => 19 });
        }
        else {
          $html->message('info', $_CHANGED, "$_CHANGED");
          $Dv->info($user->{UID});
          dv_get_month_fee($Dv) if (!$FORM{DV_NO_ABON});
        }
      }
    }
    elsif ($period == 1 && $conf{DV_USER_CHG_TP_SHEDULE}) {
      my ($year, $month, $day) = split(/-/, $FORM{DATE}, 3);
      my $seltime = POSIX::mktime(0, 0, 0, $day, ($month - 1), ($year - 1900));

      if ($seltime <= time()) {
        $html->message('info', $_INFO, "$ERR_WRONG_DATA");
        return 0;
      }

      $Shedule->add(
        {
          UID      => $LIST_PARAMS{UID},
          TYPE     => 'tp',
          ACTION   => $FORM{TP_ID},
          D        => sprintf("%02d", $day),
          M        => sprintf("%02d", $month),
          Y        => $year,
          MODULE   => 'Dv',
          COMMENTS => "$_FROM: $Dv->{TP_ID}:$Dv->{TP_NAME}"
        }
      );

      if ($Shedule->{errno}) {
        $html->message('err', $_ERROR, "[$Shedule->{errno}] $err_strs{$Shedule->{errno}}");
      }
      else {
        $html->message('info', $_CHANGED, "$_CHANGED");
        $Dv->info($user->{UID});
      }
    }

    #Imidiatly change TP
    else {
      if ($user->{CREDIT} + $user->{DEPOSIT} < 0) {
        $html->message('err', "$_ERROR", "$ERR_SMALL_DEPOSIT - $_DEPOSIT: $user->{DEPOSIT} $_CREDIT: $user->{CREDIT}", { ID => 15 });
        return 0;
      }

      $FORM{UID} = $LIST_PARAMS{UID};

      $Dv->{ABON_DATE} = undef;
      if ($Dv->{MONTH_ABON} > 0 && !$Dv->{STATUS} && !$users->{DISABLE}) {
        if ($user->{ACTIVATE} ne '0000-00-00') {
          my ($Y, $M, $D) = split(/-/, $user->{ACTIVATE}, 3);
          $M--;
          $Dv->{ABON_DATE} = strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, $M, ($Y - 1900), 0, 0, 0) + 31 * 86400 + (($conf{START_PERIOD_DAY}) ? $conf{START_PERIOD_DAY} * 86400 : 0))));
        }
        else {
          my ($Y, $M, $D) = split(/-/, $DATE, 3);
          $M++;
          if ($M == 13) {
            $M = 1;
            $Y++;
          }

          if ($conf{START_PERIOD_DAY}) {
            $D = sprintf("%02d", $conf{START_PERIOD_DAY});
          }
          else {
            $D = '01';
          }
          $Dv->{ABON_DATE} = sprintf("%d-%02d-%02d", $Y, $M, $D);
        }
      }

      if ($Dv->{ABON_DATE}) {
        ($year, $month, $day) = split(/-/, $Dv->{ABON_DATE}, 3);
        my $seltime = POSIX::mktime(0, 0, 0, $day, ($month - 1), ($year - 1900));

        if ($seltime <= time()) {
          $html->message('info', $_INFO, "$ERR_WRONG_DATA ($year, $month, $day)/" . $seltime . "-" . time());
          return 0;
        }
        elsif ($FORM{date_D} > ($month != 2 ? (($month % 2) ^ ($month > 7)) + 30 : (!($year % 400) || !($year % 4) && ($year % 25) ? 29 : 28))) {
          $html->message('info', $_INFO, "$ERR_WRONG_DATA ($year-$month-$day)");
          return 0;
        }

        $Shedule->add(
          {
            UID      => $LIST_PARAMS{UID},
            TYPE     => 'tp',
            ACTION   => $FORM{TP_ID},
            D        => $day,
            M        => $month,
            Y        => $year,
            MODULE   => 'Dv',
            COMMENTS => "$_FROM: $Dv->{TP_ID}:$Dv->{TP_NAME}"
          }
        );

        if ($Shedule->{errno}) {
          $html->message('err', $_ERROR, "[$Shedule->{errno}] $err_strs{$Shedule->{errno}}");
        }
        else {
          $html->message('info', $_CHANGED, "$_CHANGED");
        }
      }
      else {
        $Dv->change({%FORM});

        if ($Dv->{errno}) {
          $html->message('err', $_ERROR, "[$Dv->{errno}] $err_strs{$Dv->{errno}}");
        }
        else {

          #Take fees
          if (!$Dv->{STATUS}) {
            dv_get_month_fee($Dv) if (!$FORM{DV_NO_ABON});
            $user->change(
              $user->{UID},
              {
                ACTIVATE => "$DATE",
                UID      => $user->{UID}
              }
            );
          }

          $html->message('info', $_CHANGED, "$_CHANGED");
          $Dv->info($Dv->{UID});
        }
      }

      $Dv->info($Dv->{UID});
    }
  }
  elsif ($FORM{del}) {
    $Shedule->del(
      {
        UID => $LIST_PARAMS{UID},
        ID  => $FORM{SHEDULE_ID}
      }
    );

    $html->message('info', $_DELETED, "$_DELETED [$FORM{SHEDULE_ID}]");
  }

  $Shedule->info(
    {
      UID      => $user->{UID},
      TYPE     => 'tp',
      DESCRIBE => "$message\n$_FROM: '$FORM{date_y}-$FORM{date_m}-$FORM{date_d}'",
      MODULE   => 'Dv'
    }
  );

  if ($Shedule->{TOTAL} > 0) {
    $tariffs->info(0, { ID => $Shedule->{ACTION} });

    $table = $html->table(
      {
        width      => '100%',
        caption    => "$_SHEDULE",
        cols_align => [ 'left', 'left' ],
        rows       => [ [ "$_TARIF_PLAN:", "$Shedule->{ACTION} : $tariffs->{NAME}" ], [ "$_DATE:", "$Shedule->{Y}-$Shedule->{M}-$Shedule->{D}" ], [ "$_ADDED:", "$Shedule->{DATE}" ], [ "ID:", "$Shedule->{SHEDULE_ID}" ] ]
      }
    );
    $tariffs->{TARIF_PLAN_SEL} = $table->show({ OUTPUT2RETURN => 1 }) . $html->form_input('SHEDULE_ID', "$Shedule->{SHEDULE_ID}", { TYPE => 'HIDDEN', OUTPUT2RETURN => 1 });
    $tariffs->{TARIF_PLAN_TABLE} = $tariffs->{TARIF_PLAN_SEL};
    if (!$Shedule->{ADMIN_ACTION}) {
      $tariffs->{ACTION}     = 'del';
      $tariffs->{LNG_ACTION} = $_DEL;
      $tariffs->{ACTION}     = $html->form_input('del', $_DEL, { TYPE => 'submit', OUTPUT2RETURN => 1 });
    }
  }
  else {
    $tariffs->{TARIF_PLAN_SEL} = $html->form_select(
      'TP_ID',
      {
        SELECTED        => $Dv->{TP_ID},
        SEL_MULTI_ARRAY => $tariffs->list(
          {
            TP_GID       => $Dv->{TP_GID},
            CHANGE_PRICE => '<=' . ($user->{DEPOSIT} + $user->{CREDIT}),
            MODULE       => 'Dv',
            PRIORITY     => $Dv->{TP_PRIORITY}
          }
        ),
        MULTI_ARRAY_KEY   => 0,
        MULTI_ARRAY_VALUE => 1,
      }
    );

    $table = $html->table(
      {
        width      => '100%',
        caption    => "$_TRAFIF_PLANS",
        cols_align => [ 'left', 'left' ],
      }
    );

    my $tp_list = $tariffs->list(
      {
        TP_GID       => $Dv->{TP_GID},
        CHANGE_PRICE => '<=' . ($user->{DEPOSIT} + $user->{CREDIT}),
        MODULE       => 'Dv',
        PRIORITY     => $Dv->{TP_PRIORITY},
        COMMENTS     => '*',
        COLS_NAME    => 1
      }
    );

    my @skip_tp_changes = ();
    if ($conf{DV_SKIP_CHG_TPS}) {
      @skip_tp_changes = split(/,\s?/, $conf{DV_SKIP_CHG_TPS});
    }    
    
    foreach my $tp (@$tp_list) {
      next if (in_array($tp->{id}, \@skip_tp_changes));
      next if ($tp->{id} == $Dv->{TP_ID} && $user->{EXPIRE} eq '0000-00-00');
      $table->{rowcolor} = ($table->{rowcolor} eq $_COLORS[1]) ? $_COLORS[2] : $_COLORS[1];
      my $radio_but = '';
      
      if ($tp->{day_fee} + $tp->{month_fee} < $user->{DEPOSIT} + $user->{CREDIT} || $tp->{abon_distribution}) {
        $radio_but = $html->form_input('TP_ID', "$tp->{id}", { TYPE => 'radio', OUTPUT2RETURN => 1 });
      }
      else {
        $radio_but = "$ERR_SMALL_DEPOSIT";
      }

      $table->addrow($tp->{id}, $html->b($tp->{name}) . $html->br() . convert($tp->{comments}, { text2html => 1 }), $radio_but);
    }
    $tariffs->{TARIF_PLAN_TABLE} = $table->show({ OUTPUT2RETURN => 1 });

    if ($tariffs->{TOTAL} == 0) {
      $html->message('info', $_INFO, "$ERR_SMALL_DEPOSIT", { ID => 142 });
      return 0;
    }

    $tariffs->{PARAMS} .= form_period($period, { ABON_DATE => $Dv->{ABON_DATE}, TP => $tariffs }) if ($conf{DV_USER_CHG_TP_SHEDULE} && !$conf{DV_USER_CHG_TP_NPERIOD});
    $tariffs->{ACTION} = $html->form_input('set', $_CHANGE, { TYPE => 'submit', OUTPUT2RETURN => 1 });
  }

  $tariffs->{UID}     = $attr->{USER_INFO}->{UID};
  $tariffs->{m}       = $m;
  $tariffs->{TP_ID}   = $Dv->{TP_ID};
  $tariffs->{TP_NAME} = "$Dv->{TP_ID}:$Dv->{TP_NAME}";

  $html->tpl_show(templates('form_client_chg_tp'), $tariffs);
}

#**********************************************************
# dv_user_info
#**********************************************************
sub cisco_isg_cmd {
  my ($user_ip, $command, $attr) = @_;

  my $debug = $conf{ISG_DEBUG} || 0;

  if ($debug > 0) {
    print "Content-Type: text/html\n\n";
    print "Command: $command" . $html->br();
  }

  #Get user NAS server from ip pools
  if (!$Nas->{NAS_ID}) {
    my $list = $Nas->nas_ip_pools_list();
    foreach my $line (@$list) {
      if ($line->[3] <= ip2int($user_ip) && ip2int($user_ip) <= $line->[4]) {
        $Nas->info({ NAS_ID => $line->[0] });
        next;
      }
    }
  }

  if (!$Nas->{NAS_ID}) {
    $html->message('err', $_ERROR, "$ERR_UNKNOWN_IP", { ID => 13 });
    return 0;
  }

  #Get Active session info
  my %RAD_PAIRS = ();
  my $type;
  my $r = new Radius(
    Host   => "$Nas->{NAS_MNG_IP_PORT}",
    Secret => "$Nas->{NAS_MNG_PASSWORD}"
  ) or return "Can't connect '$Nas->{NAS_MNG_IP_PORT}' $!";

  $conf{'dictionary'} = $base_dir . '/Abills/dictionary' if (!$conf{'dictionary'});
  $r->load_dictionary($conf{'dictionary'});

  $r->clear_attributes();
  $r->add_attributes({ Name => 'User-Name',          Value => "$attr->{USER_NAME}" });
  $r->add_attributes({ Name => 'Cisco-Account-Info', Value => "S$user_ip" });

  if ($command eq 'account-status-query') {
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:command=account-status-query" });
    $r->send_packet(43) and $type = $r->recv_packet;

    if (!defined $type) {
      $html->message('err', $_ERROR, "No responce from  CoA server '$Nas->{NAS_MNG_IP_PORT}' $! / " . $r->get_error(), { ID => 106 });
      return 0;
    }

    for my $a ($r->get_attributes) {
      if ($a->{'Value'} =~ /\$MA(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }
      elsif ($a->{'Value'} =~ /^S(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }
      elsif ($a->{'Value'} =~ /^N1TURBO_SPEED(\d+);(\d+)/) {
        $Dv->{TURBO_MODE_RUN} = $2;
      }
      elsif ($a->{'Value'} =~ /^N1(TP_[0-9\_]+);(\d+)/) {
        $Dv->{CURE_SERVICE}         = $1;
        $Dv->{ISG_SESSION_DURATION} = $2;
      }
      $RAD_PAIRS{ $a->{'Name'} } = $a->{'Value'};
      if ($debug > 0) {
        print "$a->{'Name'} -> $a->{'Value'}" . $html->br();
      }
    }

    # name=Cisco-Account-Info value=N1TP_100;3541;test;8657;8149;1781505;2915555
    # name=User-Name value=test
    # name=Cisco-Command-Code value=1
    # name=Cisco-Account-Info value=S85.132.11.5
    # name=Cisco-AVPair value=sg-version=1.0
    # name=Cisco-NAS-Port value=0/0/1/40
    # name=NAS-Port value=0
    # name=NAS-Port-Id value=0/0/1/40
    # name=Framed-IP-Address value=85.132.11.5 Content-Type: text/html

    # If ISG return error push error to log
    if ($RAD_PAIRS{'Error-Cause'}) {
      my $message = "NAS: $Nas->{NAS_ID}, $RAD_PAIRS{'Error-Cause'} / $RAD_PAIRS{'Reply-Message'}";
      $html->message('err', $_ERROR, $message, { ID => 100 });
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_WARNING'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "$message",
          DB        => 1
        }
      );

      return 0;
    }
    else {
      if (!$Dv->{ISG_CID_CUR}) {
        $html->message('err', $_ERROR, "$_NOT_EXIST ID: '$user_ip' ", { ID => 11 });
      }
      elsif ($Dv->{ISG_CID_CUR} =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) {
        $DHCP_INFO = dv_dhcp_get_mac($Dv->{ISG_CID_CUR});
        $Dv->{ISG_CID_CUR} = $DHCP_INFO->{MAC} || '';
        if ($Dv->{ISG_CID_CUR} eq '') {
          $html->message('err', $_ERROR, "IP: '$user_ip', MAC $_NOT_EXIST. DHCP $_ERROR ", { ID => 12 });
          return 0;
        }
      }
    }
  }
  elsif ($command eq 'deactivate-service') {

    # Deactivate cur service
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:subscriber:command=deactivate-service" });
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:service-name=$attr->{CURE_SERVICE}" });
    $r->send_packet(43) and $type = $r->recv_packet;

    if (!defined $type) {
      $html->message('err', $_ERROR, "No responce from  CoA server '$Nas->{NAS_MNG_IP_PORT}' $! / " . $r->get_error(), { ID => 106 });
      return 0;
    }
  }
  elsif ($command eq 'activate-service') {
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:command=activate-service" });
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:service-name=$attr->{SERVICE_NAME}" });
    $r->send_packet(43) and $type = $r->recv_packet;

    if (!defined $type) {
      $html->message('err', $_ERROR, "No responce from  CoA server '$Nas->{NAS_MNG_IP_PORT}' $! / " . $r->get_error(), { ID => 106 });
      return 0;
    }

    for my $a ($r->get_attributes) {

      #MAC as ID
      if ($val =~ /\$MA(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }

      #IP user ID
      elsif ($val =~ /S(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }
      $RAD_PAIRS{ $a->{'Name'} } = $a->{'Value'};
    }

    if ($RAD_PAIRS{'Error-Cause'}) {
      $html->message('err', $_ERROR, "$RAD_PAIRS{'Error-Cause'} / $RAD_PAIRS{'Reply-Message'}", { ID => 101 });
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_WARNING'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Service Enable IP: $user_ip '$service_name' Error: $RAD_PAIRS{'Error-Cause'} / $RAD_PAIRS{'Reply-Message'}",
          DB        => 1
        }
      );
    }
    else {
      $html->message('info', $_INFO, "$_SERVICE $_ENABLE");
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_INFO'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Service Enable '$service_name' IP: $user_ip",
          DB        => 1
        }
      );
      return 0;
    }
  }
  elsif ($command eq 'account-logon') {
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:command=account-logon" });
    $r->send_packet(43) and $type = $r->recv_packet;

    if (!defined $type) {
      $html->message('err', $_ERROR, "No responce from  CoA server '$Nas->{NAS_MNG_IP_PORT}' $! / " . $r->get_error(), { ID => 106 });
      return 0;
    }

    for my $a ($r->get_attributes) {

      #MAC as ID
      if ($val =~ /\$MA(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }

      #IP user ID
      elsif ($val =~ /S(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }
      $RAD_PAIRS{ $a->{'Name'} } = $a->{'Value'};
    }

    if ($RAD_PAIRS{'Error-Cause'}) {
      $html->message('err', $_ERROR, "$_LOGON $_ERROR [$RAD_PAIRS{'Error-Cause'}] $RAD_PAIRS{'Reply-Message'}", { ID => 101 });
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_WARNING'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Logon Error: $RAD_PAIRS{'Error-Cause'} / $RAD_PAIRS{'Reply-Message'}",
          DB        => 1
        }
      );
    }
    else {
      $html->message('info', $_INFO, "$_LOGON");
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_INFO'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Logon",
          DB        => 1
        }
      );

      return 0;
    }
  }
  elsif ($command eq 'account-logoff') {
    $r->add_attributes({ Name => 'Cisco-AVPair', Value => "subscriber:command=account-logon" });
    $r->send_packet(43) and $type = $r->recv_packet;

    if (!defined $type) {
      $html->message('err', $_ERROR, "No responce from  CoA server '$Nas->{NAS_MNG_IP_PORT}' $! / " . $r->get_error(), { ID => 106 });
      return 0;
    }

    for my $a ($r->get_attributes) {

      #MAC as ID
      if ($val =~ /\$MA(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }

      #IP user ID
      elsif ($val =~ /S(\S+)/) {
        $Dv->{ISG_CID_CUR} = $1;
      }
      $RAD_PAIRS{ $a->{'Name'} } = $a->{'Value'};
    }

    if ($RAD_PAIRS{'Error-Cause'}) {
      $html->message('err', $_ERROR, "$_LOGON $_ERROR [$RAD_PAIRS{'Error-Cause'}] $RAD_PAIRS{'Reply-Message'}", { ID => 101 });
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_WARNING'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Logon Error: $RAD_PAIRS{'Error-Cause'} / $RAD_PAIRS{'Reply-Message'}",
          DB        => 1
        }
      );
    }
    else {
      $html->message('info', $_INFO, "$_LOGON");
      $Log->log_add(
        {
          LOG_TYPE  => $log_levels{'LOG_INFO'},
          ACTION    => 'AUTH',
          USER_NAME => $attr->{USER_NAME} || '-',
          MESSAGE   => "Logon",
          DB        => 1
        }
      );

      return 0;
    }
  }

  #old way
  #=comments
  #
  #  	#get  PBHK identifier (IP or MAC) from NAS and account info
  #    #my $isg_cmd = "/bin/echo \"User-Name=\\\"$user->{LOGIN}\\\",cisco-avpair=\\\"subscriber:command=account-status-query\\\",Cisco-Account-Info=\\\"S$user->{REMOTE_ADDR}\\\"\" | #/usr/local/bin/radclient -x $Nas->{NAS_MNG_IP_PORT} coa $Nas->{NAS_MNG_PASSWORD}";
  #    #my $result = `$isg_cmd`;
  #
  #
  #
  #redirect service:
  #        Cisco-Account-Info=N1SERVICE_406_L4R;12;;0;0;0;0,
  #        Cisco-Account-Info=N1PBHK_SERVICE;12;;0;0;0;0,
  #        Cisco-Command-Code=0,
  #        Cisco-Account-Info=S79.124.108.107,
  #        Cisco-AVPair=sg-version=1.0,
  #        NAS-Port-Id=33555320,
  #        NAS-Port-Id=nas-port:0.0.0.0:0/0/2/888,
  #        Framed-IP-Address=79.124.108.107,
  #
  #Sending CoA-Request of id 218 to 77.87.152.66 port 1700
  #        User-Name = "test"
  #        Cisco-AVPair = "subscriber:command=account-status-query"
  #        Cisco-Account-Info = "S79.124.98.3"
  #rad_recv: CoA-ACK packet from host 77.87.152.66:1700, id=218, length=211
  #        Cisco-Account-Info = "N1SERVICE_406_L4R;224;;0;0;0;0"
  #        Cisco-Account-Info = "N1PBHK_SERVICE;224;;0;0;0;0"
  #        Cisco-Account-Info = "$MA0018.f3f8.f85a"
  #        Cisco-Account-Info = "S79.124.98.3"
  #        Cisco-Command-Code = "\0040"
  #        Cisco-AVPair = "sg-version=1.0"
  #        NAS-Port = 0
  #        NAS-Port-Id = "nas-port:0.0.0.0:0/0/2/1416"
  #        Framed-IP-Address = 79.124.98.3
  #pROFILRE
  #
  #        Cisco-Account-Info = "N1PBHK_SERVICE;399;chao;0;0;0;0"
  #        Cisco-Account-Info = "N1TP_214;399;chao;0;46;0;2867"
  #        User-Name = "chao"
  #        Cisco-Command-Code = "\0041"
  #        Cisco-Account-Info = "S79.124.99.40"
  #        Cisco-Account-Info = "ATP_214"
  #        Cisco-Account-Info = "NSERVICE_406_BOD1M"
  #        Cisco-Account-Info = "NBasic_Internet_Service"
  #        Cisco-Account-Info = "N1PBHK_SERVICE;399;chao;0;0;0;0"
  #        Idle-Timeout = 1800
  #        User-Name = "chao"
  #        Cisco-AVPair = "accounting-list=BH_ACCNT_LIST1"
  #        Cisco-AVPair = "sg-version=1.0"
  #        NAS-Port = 33555320
  #        NAS-Port-Id = "nas-port:0.0.0.0:0/0/2/888"
  #        Framed-IP-Address = 79.124.99.40
  #
  #
  #	my @arr = split(/\n/, $result);
  #  	my %RAD_PAIRS = ();
  #  	foreach my $line (@arr) {
  #        my($key, $val)=split(/ = /, $line);
  #
  #        $val =~ s/\"//g;
  #        $key =~ s/\t//g;
  #        $key =~ s/ //g;
  #
  #      	$RAD_PAIRS{$key}=$val;
  #        #Mac as ID
  #        if ($val =~ /\$MA(\S+)/) {
  #      	  $Dv->{ISG_CID_CUR}=$1;
  #      	 }
  #  	    #IP user ID
  #  	    elsif ($val =~ /^S(\S+)/) {
  #  	    	$Dv->{ISG_CID_CUR}=$1;
  #  	     }
  #        elsif ($val =~ /^N1TURBO_SPEED(\d+);(\d+)/) {
  #          $Dv->{TURBO_MODE_RUN}=$2;
  #         }
  #  	    elsif ($val =~ /^N1(TP_\d+);(\d+)/) {
  #  	      $Dv->{CURE_SERVICE}=$1;
  #  	      $Dv->{ISG_SESSION_DURATION}=$2;
  #  	     }
  #  	 }
  #=cut
  return 1;
}

#**********************************************************
# dv_turbo_mode
#**********************************************************
sub dv_turbo_mode_report {
  dv_turbo_mode({ REPORT => 1 })

}

#**********************************************************
# dv_turbo_mode
#**********************************************************
sub dv_turbo_mode {
  my ($attr) = @_;

  require "Turbo.pm";
  Turbo->import();
  my $Turbo    = Turbo->new($db, $admin, \%conf);
  my $sessions = Turbo->new($db, $admin, \%conf);

  if ($FORM{del} && defined($FORM{is_js_confirmed})) {
    $Turbo->del({ ID => $FORM{del} });
    if (!$Turbo->{errno}) {
      $html->message('info', $_INFO, "Torbo $_DELETED");
    }
  }

  if (!defined($FORM{sort})) {
    $LIST_PARAMS{SORT} = 4;
    $LIST_PARAMS{DESC} = 'DESC';
  }

  $LIST_PARAMS{ACTIVE} = 1 if (!$attr->{REPORT});

  my $list = $Turbo->list({%LIST_PARAMS});

  if ($Turbo->{TOTAL} < 1) {
    $html->message('info', $_INFO, "$_NO_RECORD");
    return 0;
  }

  my @caption = ("$_USER", "$_TARIF_PLAN", "$_REMAIN $_TIME", "$_START", "$_DURATION", "$_SPEED");

  if ($sessions->{SEARCH_FIELDS_COUNT}) {
    push @caption, 'TC';
  }

  my $table = $html->table(
    {
      width        => '100%',
      caption      => "TURBO $_SESSIONS",
      border       => 1,
      title        => [ @caption, "-" ],
      cols_align   => [ 'left', 'right', 'right', 'RIGHT', 'right', 'right', 'right', 'right', 'right', 'right', 'center:noprint', 'center:noprint' ],
      qs           => $pages_qs,
      pages        => $Turbo->{TOTAL},
      recs_on_page => $LIST_PARAMS{PAGE_ROWS},
      ID           => 'DV_TURBO_SESSIONS'
    }
  );

  my $delete = '';
  use Billing;
  my $Billing = Billing->new($db, \%conf);

  foreach my $line (@$list) {
    if ($permissions{3}{1}) {
      $delete = $html->button($_DEL, "index=" . $index . "$pages_qs&del=$line->[8]", { MESSAGE => "$_DEL $_SESSION $line->[8] ", CLASS => 'del' });
    }

    $table->addrow($html->button("$line->[0]", "index=11&UID=$line->[7]"), $line->[1], $line->[2], $line->[3], $line->[4], $line->[5], $delete);
  }

  print $table->show();
}

#**********************************************************
# dv_user_info
#**********************************************************
sub dv_user_info {
  my $DHCP_INFO = undef;

  if ($conf{DV_ISG}) {
    #Check deposit and disable STATUS
    my $list = $Dv->list(
      {
        LOGIN         => $user->{LOGIN},
        TP_CREDIT     => '>0',
        PAYMENTS_TYPE => 0,
        COLS_NAME     => 1
      }
    );

    if ($Dv->{TOTAL} < 1) {

    }
    elsif (($list->[0]->{credit} > 0 && ($list->[0]->{deposit} + $list->[0]->{credit} < 0))
      || ($list->[0]->{credit} == 0 && $list->[0]->{deposit} + $list->[0]->{credit}) < 0)
    {
      form_neg_deposit($user);
      return 0;
    }
    elsif ($list->[0]->{dv_status} && $list->[0]->{dv_status} == 1) {
      $html->message('err', $_ERROR, "$_SERVICES '$list->[0]->{tp_name}' $_DISABLE", { ID => 15 });
      return 0;
    }

    if (!cisco_isg_cmd($user->{REMOTE_ADDR}, "account-status-query", { USER_NAME => $user->{LOGIN} })) {
      return 0;
    }

    if ($Dv->{ISG_CID_CUR}) {
      #change speed (active turbo mode)
      if ($FORM{SPEED}) {
        if ($Dv->{CURE_SERVICE} =~ /TP/ || !$Dv->{TURBO_MODE_RUN}) {
          my $service_name = 'TURBO_SPEED' . $FORM{SPEED};

          #Deactive cure service (TP Service)
          if ($Dv->{CURE_SERVICE} =~ /TP/) {
            if (!cisco_isg_cmd($user->{REMOTE_ADDR}, "deactivate-service", { USER_NAME => $user->{LOGIN}, CURE_SERVICE => $Dv->{CURE_SERVICE} })) {

            }
          }

          #Activate service
          if (!cisco_isg_cmd($user->{REMOTE_ADDR}, "deactivate-service", { USER_NAME => $user->{LOGIN}, SERVICE_NAME => $service_name })) {
            return 0;
          }
        }
        elsif ($Dv->{TURBO_MODE_RUN}) {
          $html->message('info', $_INFO, "TURBO $_MODE $_ENABLE");
        }
      }
    }
  }

  # Users autoregistrations
  elsif ($conf{DV_IP_DISCOVERY}) {
    $DHCP_INFO = dv_dhcp_get_mac($user->{REMOTE_ADDR}, { CHECK_STATIC => 1 });
    if (!$DHCP_INFO->{MAC}) {
      $html->message('err', $_ERROR, "DHCP $_ERROR \n MAC: $_NOT_EXIST \n IP: '$user->{REMOTE_ADDR}'", { ID => 112 });
      return 0;
    }
    elsif ($DHCP_INFO->{STATIC}) {
      if ($DHCP_INFO->{IP} ne "$user->{REMOTE_ADDR}") {
        $html->message('err', $_ERROR, "$ERR_IP_ADDRESS_CONFLICT \n MAC: $_NOT_EXIST \n IP: '$user->{REMOTE_ADDR}' ", { ID => 114 });
      }
    }
    else {
      $html->tpl_show(_include('dv_guest_mode', 'Dv'), { %$Dv, %$DHCP_INFO });
    }
  }

  if ($FORM{activate}) {
    $Dv->change(
      {
        UID    => $LIST_PARAMS{UID},
        STATUS => 0,
        CID    => ($Dv->{ISG_CID_CUR}) ? $Dv->{ISG_CID_CUR} : undef
      }
    );

    if (!$Dv->{errno}) {
      $Dv->{ACCOUNT_ACTIVATE}=$user->{ACTIVATE};	
      $html->message('info', $_INFO, "$_ACTIVATE CID: $Dv->{ISG_CID_CUR}") if ($Dv->{ISG_CID_CUR});
      dv_get_month_fee($Dv) if (!$Dv->{STATUS});
    }
    else {
      $html->message('err', $_ACTIVATE, "$_ERROR CID: $Dv->{ISG_CID_CUR}", { ID => 102 });
    }

    #Log on
    if (!cisco_isg_cmd($user->{REMOTE_ADDR}, "account-logon", { USER_NAME => $user->{LOGIN} })) {
      return 0;
    }
  }
  elsif ($FORM{logon}) {
    #Logon
    if (!cisco_isg_cmd($user->{REMOTE_ADDR}, "account-logon", { USER_NAME => $user->{LOGIN} })) {
      return 0;
    }
  }
  elsif ($FORM{discovery}) {
    if (dv_dhcp_get_mac_add($user->{REMOTE_ADDR}, $DHCP_INFO)) {
      $html->message('info', $_INFO, "$_ACTIVATE \n\n IP: $Dv->{NEW_IP} \n CID: $DHCP_INFO->{MAC}");
    }
  }
  elsif ($FORM{hangup}) {
    require "Abills/nas.pl";
    my $ret = hangup(
      $Nas, "0",
      "$user->{LOGIN}",
      {
        ACCT_SESSION_ID   => '',
        FRAMED_IP_ADDRESS => $user->{REMOTE_ADDR},
        UID               => $user->{UID},
        USER_INFO         => $user->{LOGIN}
      }
    );
  }

  $Dv->info($LIST_PARAMS{UID});
  $user->{DV_STATUS} = $Dv->{STATUS};

  if ($Dv->{TOTAL} < 1) {
    $html->message('info', $_INFO, "$_NOT_ACTIVE");
    return 0;
  }

  # Get next payment period
  if (
       $Dv->{MONTH_ABON} > 0
    && !$Dv->{STATUS}
    && !$user->{DISABLE}
    && ( $user->{DEPOSIT} + $user->{CREDIT} > 0
      || $Dv->{POSTPAID_ABON}
      || $Dv->{PAYMENT_TYPE} == 1)
  ){

    if ($user->{ACTIVATE} ne '0000-00-00') {
      my ($Y, $M, $D) = split(/-/, $user->{ACTIVATE}, 3);
      $M--;
      $Dv->{ABON_DATE} = strftime("%Y-%m-%d", localtime((mktime(0, 0, 0, $D, $M, ($Y - 1900), 0, 0, 0) + 31 * 86400)));
    }
    else {
      my ($Y, $M, $D) = split(/-/, $DATE, 3);
      $M++;
      if ($M == 13) {
        $M = 1;
        $Y++;
      }

      if ($conf{START_PERIOD_DAY}) {
        $D = $conf{START_PERIOD_DAY};
      }
      else {
        $D = '01';
      }

      $Dv->{ABON_DATE} = sprintf("%d-%02d-%02d", $Y, $M, $D);
    }

    my ($from_year, $from_month, $from_day) = split(/-/, $DATE,            3);
    my ($to_year,   $to_month,   $to_day)   = split(/-/, $Dv->{ABON_DATE}, 3);

    if ($Dv->{ABON_DISTRIBUTION} && $Dv->{MONTH_ABON} > 0) {
      my $days_to_fees = int(($user->{DEPOSIT} + $user->{CREDIT}) / ($Dv->{MONTH_ABON} / 30));

      $Dv->{NEXT_FEES_WARNING} = "$_SERVICE_ENDED";
      $Dv->{NEXT_FEES_WARNING} =~ s/\%DAYS\%/$days_to_fees/g;
      if ($days_to_fees < 5) {
        $Dv->{NEXT_FEES_WARNING} = $html->color_mark($Dv->{NEXT_FEES_WARNING}, "red");
      }
    }
    else {
      my $from_seltime = POSIX::mktime(0, 0, 0, $from_day, ($from_month - 1), ($from_year - 1900));
      my $to_seltime   = POSIX::mktime(0, 0, 0, $to_day,   ($to_month - 1),   ($to_year - 1900));

      my $days_to_fees = int(($to_seltime - $from_seltime) / 86400);

      $Dv->{NEXT_FEES_WARNING} = "$_NEXT_FEES_THROUGHT";
      $Dv->{NEXT_FEES_WARNING} =~ s/\%DAYS\%/$days_to_fees/g;
      if ($days_to_fees < 5) {
        $Dv->{NEXT_FEES_WARNING} = $html->color_mark($Dv->{NEXT_FEES_WARNING}, "red");
      }
    }
  }

  if ($Dv->{STATUS} == 2) {
    $Dv->{STATUS} = $html->color_mark($service_status[ $Dv->{STATUS} ], $service_status_colors[ $Dv->{STATUS} ]) . ' ';
    $Dv->{STATUS} .= ($user->{DISABLE} > 0) ? $html->b("($_ACCOUNT $_DISABLE)") : $html->button($_ACTIVATE, "&index=$index&sid=$sid&activate=1", { ex_params => ' ID="ACTIVATE"', BUTTON => 1 });
  }
  elsif ($Dv->{STATUS} == 5) {
    $Dv->{STATUS} = $html->color_mark($service_status[ $Dv->{STATUS} ], $service_status_colors[ $Dv->{STATUS} ]) . ' ';

    if ($Dv->{MONTH_ABON} <= $user->{DEPOSIT}) {
      $Dv->{STATUS} .= ($user->{DISABLE} > 0) ? $html->b("($_ACCOUNT $_DISABLE)") : $html->button($_ACTIVATE, "&index=$index&sid=$sid&activate=1", { ex_params => ' ID="ACTIVATE"', BUTTON => 1 });
    }
    else {
      form_neg_deposit($user);
    }
  }
  else {
    $Dv->{STATUS} = $html->color_mark($service_status[ $Dv->{STATUS} ], $service_status_colors[ $Dv->{STATUS} ]);
  }

  while (my ($k, $v) = each %functions) {
    if ($v eq 'dv_user_info') {
      $index = $k;
      last;
    }
  }

  $user->{SERVICE_STATUS} = $Dv->{STATUS};
  if ($conf{DV_USER_CHG_TP}) {
    $Dv->{TP_CHANGE} = $html->button("$_CHANGE", 'index=' . get_function_index('dv_user_chg_tp') . '&sid=' . $sid, { CLASS => 'change rightAlignText' });
  }

  #Activate Cisco ISG Account
  if ($conf{DV_ISG}) {
    if ($user->{DISABLE}) {
      $html->message('err', $_ERROR, "$_USER  $_DISABLE", { ID => 16 });
    }
    elsif ($Dv->{CID} ne $Dv->{ISG_CID_CUR} || $Dv->{CID} eq '') {
      $html->message('info', $_INFO, "$_NOT_ACTIVE \n\n CID: $Dv->{ISG_CID_CUR} \n IP: $user->{REMOTE_ADDR} ");
      $html->form_main(
        {
          CONTENT => '',
          HIDDEN  => {
            index => "$index",
            CID   => "$Dv->{ISG_CID_CUR}",
            sid   => $sid
          },
          SUBMIT => { activate => "$_ACTIVATE" }
        }
      );

      $Dv->{CID} = $Dv->{ISG_CID_CUR};
      $Dv->{IP}  = $user->{REMOTE_ADDR};
      $Dv->{CID} .= ' ' . $html->color_mark($_NOT_ACTIVE, $_COLORS[6]);
    }

    #Self hangup
    elsif ($Dv->{CID} eq $Dv->{ISG_CID_CUR}) {
      $table = $html->table(
        {
          width    => '600',
          rowcolor => 'row_active',
          rows     => [
            [
              ($Dv->{ISG_SESSION_DURATION}) ? "$_SESSIONS $_DURATION: " . sec2time($Dv->{ISG_SESSION_DURATION}, { str => 1 }) : '',
              ($Dv->{CURE_SERVICE} !~ /TP/ && !$Dv->{TURBO_MODE_RUN}) ? $html->form_input('logon', "$_LOGON ", { TYPE => 'submit', OUTPUT2RETURN => 1 }) : '',

              #$html->form_input('hangup', $_HANGUP, { TYPE => 'submit', OUTPUT2RETURN => 1 })
            ]
          ],
        }
      );

      print $html->form_main(
        {
          CONTENT => $table->show({ OUTPUT2RETURN => 1 }),
          HIDDEN  => {
            index => "$index",
            CID   => "$Dv->{ISG_CID_CUR}",
            sid   => $sid
          },
        }
      );
    }
  }

  #Turbo mode Enable function
  if ($conf{DV_TURBO_MODE} && !$Dv->{TURBO_MODE}) {
    my (@turbo_mods) = split(/;/, $conf{DV_TURBO_MODE});
    my @turbo_mods_full = ();

    my $i = 1;
    my ($speed, $time, $price, $name);
    foreach my $line (@turbo_mods) {
      ($speed, $time, $price, $name, $bonus) = split(/:/, $line, 5);
      
      if ($bonus && ! $Dv->{FREE_TURBO_MODE} ) {
      	next;
      }
      
      push @turbo_mods_full, sprintf("$name\n $_SPEED: $speed\n $_TIME: %s\n $_PRICE: %.2f %s", sec2time($time, { format => 1 }), $price, (($bonus) ? "($_BONUS)" : ''));
      if ($FORM{SPEED} && $FORM{SPEED} == $i) {
        $FORM{MODE_ID} = $i - 1;
        $FORM{SPEED}   = $speed;
        $FORM{TIME}    = $time;
        last;
      }
      $i++;
    }

    require "Turbo.pm";
    Turbo->import();
    my $Turbo = Turbo->new($db, $admin, \%conf);
    my $list = $Turbo->list(
      {
        UID    => $LIST_PARAMS{UID},
        ACTIVE => 1,
      }
    );

    if ($Turbo->{TOTAL} > 0 || $Dv->{TURBO_MODE_RUN}) {
      my $last = $list->[0]->[2] || $Dv->{TURBO_MODE_RUN};
      $html->message('info', $_INFO, $html->b("$turbo_mods_full[$list->[0]->[1]]") . "\n$_REMAIN $_TIME: $last sec.");
    }
    elsif ($FORM{change} && $FORM{SPEED}) {
      if ($user->{DEPOSIT} + $user->{CREDIT} > $price) {
        $Turbo->add(
          {
            UID        => $LIST_PARAMS{UID},
            MODE_ID    => $FORM{MODE_ID},
            SPEED      => int($FORM{SPEED}),
            SPEED_TYPE => 0,
            TIME       => $FORM{TIME},
          }
        );

        if ($price > 0) {
          $fees->take($user, $price, { DESCRIBE => "Turbo mode: $Turbo->{INSERT_ID}" });
        }

        if ($bonus) {
        	 if ($Dv->{FREE_TURBO_MODE} < 1) {
        	 	 $html->message('err', "$_ERROR", "$_BONUS Turbo $_EXPIRED");
        	 	 return 0;
        	 }
        	 else {
        	   $Dv->change({ 
        	 	   UID             => $user->{UID},
        	 	   FREE_TURBO_MODE => ($Dv->{FREE_TURBO_MODE}-1)
        	   });
        	 }
         }

        if ($conf{DV_TURBO_CMD}) {
          $conf{DV_TURBO_CMD} = tpl_parse($conf{DV_TURBO_CMD}, { %$user, IP => $ENV{REMOTE_ADDR} });
          my $result = `$conf{DV_TURBO_CMD}`;
        }

        $html->message('info', $_INFO, $html->b("$turbo_mods_full[$FORM{MODE_ID}]") . "\n$_REMAIN $_TIME: $FORM{TIME} sec.");
      }
      else {
        $html->message('err', "$_ERROR:Turbo", "$ERR_SMALL_DEPOSIT");
      }
    }
    else {
      $Dv->{SPEED_SEL} = $html->form_select(
        'SPEED',
        {
          SELECTED     => $FORM{SPEED},
          SEL_ARRAY    => [ '', @turbo_mods_full ],
          ARRAY_NUM_ID => 1
        }
      );

      $html->tpl_show(_include('dv_user_speed', 'Dv'), $Dv);
    }
  }

  $html->tpl_show(_include('dv_user_info', 'Dv'), $Dv);
  
  
  if($conf{DV_ALERT_REDIRECT_FILTER} eq $Dv->{FILTER_ID}) {
    $Dv->change({ UID => $user->{UID},
    	            FILTER_ID => ''
    	         });
  }

  
  if ($conf{DV_USER_SERVICE_HOLDUP}) {
    #$_HOLD_UP
    dv_holdup_service($Dv);
  }
}

#**********************************************************
#
#**********************************************************
sub dv_holdup_service {
  my ($attr) = @_;
  my ($hold_up_min_period, $hold_up_max_period, $hold_up_period, $holdup_fees, $hold_fees_deposit, $active_fees) = split(/:/, $conf{DV_USER_SERVICE_HOLDUP});

  my $Shedule = Shedule->new($db, $admin, \%conf);

  if ($FORM{del}) {
    $Shedule->del(
      {
        UID => $user->{UID},
        IDS => $FORM{del},
      }
    );

    $html->message('info', $_HOLD_UP, "$_DELETED");
  }

  my $list = $Shedule->list(
    {
      UID    => $user->{UID},
      MODULE => 'Dv',
      TYPE   => 'status'
    }
  );

  my %Shedule_val = ();
  my $del_ids     = '';
  foreach $line (@$list) {
    $Shedule_val{ $line->[7] } = "$line->[3]-$line->[2]-$line->[1]";
    $del_ids .= "$line->[14],";
  }

  chop($del_ids);

  if ($Shedule->{TOTAL} > 0) {
    $html->message('info', $_INFO, "$_HOLD_UP $Shedule_val{3} -> $Shedule_val{0} " . (($Shedule->{TOTAL} > 1) ? $html->br() . $html->button("$_DEL", "index=$index&del=$del_ids&sid=$sid", { BUTTON => 1, MESSAGE => "$_DEL $_HOLD_UP?" }) : ''));

    return 0;
  }

  if ($FORM{add}) {
    my ($from_year, $from_month, $from_day) = split(/-/, $FORM{FROM_DATE}, 3);
    my ($to_year,   $to_month,   $to_day)   = split(/-/, $FORM{TO_DATE},   3);

    my $from_seltime = POSIX::mktime(0, 0, 0, $from_day, ($from_month - 1), ($from_year - 1900));
    my $to_seltime   = POSIX::mktime(0, 0, 0, $to_day,   ($to_month - 1),   ($to_year - 1900));

    my $block_days = ($to_seltime - $from_seltime) / 86400;

    if ($block_days < $hold_up_min_period) {
      $html->message('err', "$ERR_WRONG_DATA", "$_MIN $_HOLD_UP   $hold_up_min_period $_DAYS");
    }
    elsif ($block_days > $hold_up_max_period) {
      $html->message('err', "$ERR_WRONG_DATA", "$_MAX $_HOLD_UP   $hold_up_max_period $_DAYS");
    }
    elsif ($from_seltime <= time()) {
      $html->message('info', $_INFO, "$ERR_WRONG_DATA ($_FROM: $FORM{FROM_DATE}");
    }
    elsif ($to_seltime <= time()) {
      $html->message('info', $_INFO, "$ERR_WRONG_DATA ($_TO: $FORM{TO_DATE}");
    }
    else {
      $Shedule->add(
        {
          UID    => $user->{UID},
          TYPE   => "status",
          ACTION => "3",
          D      => $from_day,
          M      => $from_month,
          Y      => $from_year,
          MODULE => 'Dv'
        }
      );

      $Shedule->add(
        {
          UID    => $user->{UID},
          TYPE   => "status",
          ACTION => "0",
          D      => $to_day,
          M      => $to_month,
          Y      => $to_year,
          MODULE => 'Dv'
        }
      );

      if (!$Shedule->{errno}) {
        $html->message('info', $_INFO, "$_HOLD_UP \n $_DATE: $FORM{FROM_DATE} -> $FORM{TO_DATE} \n  $_DAYS: " . sprintf("%d", $block_days));
        return 0;
      }
    }
  }

  if ($hold_up_period) {
    my $list = $admin->action_list(
      {
        UID       => $user->{UID},
        TYPE      => 14,
        FROM_DATE => (strftime "%Y-%m-%d", localtime(time - 86400 * $hold_up_period)),
        TO_DATE   => "$DATE",
      }
    );
    if ($admin->{TOTAL} > 0) {
      return 0;
    }
  }

  if (($user->{DV_STATUS} && $user->{DV_STATUS} != 3) || $user->{DISABLE}) {
    return 0;
  }

  $Dv->{DATE_FROM} = $html->date_fld2(
    'FROM_DATE',
    {
      FORM_NAME => 'holdup',
      WEEK_DAYS => \@WEEKDAYS,
      MONTHES   => \@MONTHES,
      NEXT_DAY  => 1
    }
  );

  $Dv->{DATE_TO} = $html->date_fld2(
    'TO_DATE',
    {
      FORM_NAME => 'holdup',
      WEEK_DAYS => \@WEEKDAYS,
      MONTHES   => \@MONTHES,
    }
  );

  $html->tpl_show(_include('dv_hold_up', 'Dv'), $Dv);
}

#**********************************************************
# dv_periodic_logrotate
#**********************************************************
sub dv_periodic_logrotate {
  my ($attr) = @_;
  my $debug = $attr->{DEBUG} || 0;

  return '' if ($attr->{SKIP_ROTATE});

  # Clean s_detail table
  my ($y, $m, $d) = split(/-/, $ADMIN_REPORT{DATE}, 3);
  $conf{DV_LOG_CLEAN_PERIOD} = 180 if (!$conf{DV_LOG_CLEAN_PERIOD});

  if ($d == 1 && $conf{DV_LOG_CLEAN_PERIOD}) {
    $DEBUG .= "Make log rotate\n" if ($debug > 0);

    $sessions->log_rotate(
      {
        TYPES  => [ 'SESSION_DETAILS', 'SESSION_INTERVALS' ],
        PERIOD => $conf{DV_LOG_CLEAN_PERIOD}
      }
    );
  }
  else {
    $sessions->log_rotate({ DAILY => 1 });
  }
}

#**********************************************************
# daily_fees
#**********************************************************
sub dv_daily_fees {
  my ($attr) = @_;

  my $debug        = $attr->{DEBUG} || 0;
  my $debug_output = '';
  my $DOMAIN_ID    = $attr->{DOMAIN_ID} || 0;

  if ($attr->{USERS_WARNINGS_TEST}) {
    return $debug_output;
  }

  $debug_output .= "DV: Daily periodic fees\n" if ($debug > 1);

  $LIST_PARAMS{TP_ID} = $attr->{TP_ID} if ($attr->{TP_ID});
  $LIST_PARAMS{DOMAIN_ID} = $DOMAIN_ID;

  my %USERS_LIST_PARAMS = ();
  $USERS_LIST_PARAMS{LOGIN} = $attr->{LOGIN} if ($attr->{LOGIN});
  $USERS_LIST_PARAMS{DOMAIN_ID} = $DOMAIN_ID;

  #$USERS_LIST_PARAMS{ACTIVE_DAY_FEE} = 1;

  $tariffs->{debug} = 1 if ($debug > 6);

  my $list = $tariffs->list({%LIST_PARAMS});
  $ADMIN_REPORT{DATE} = $DATE if (!$ADMIN_REPORT{DATE});

  foreach my $line (@$list) {
    if ($line->[5] > 0) {
      my $TP_ID          = $line->[0];
      my $TP_NAME        = $line->[1];
      my $active_day_fee = $line->[20];
      my $fine           = $line->[21];
      my %TP_INFO        = ();
      $TP_INFO{POSTPAID_DAILY} = $line->[12];
      $TP_INFO{REDUCTION}      = $line->[11];
      $TP_INFO{FEES_METHOD}    = $line->[23];
      $debug_output .= "TP ID: $TP_ID DF: $line->[5] MF: $line->[6] POSTPAID: $TP_INFO{POSTPAID_DAILY} REDUCTION: $TP_INFO{REDUCTION} EXT_BILL: $line->[13] CREDIT: $line->[14]\n" if ($debug > 1);

      #Get active yesterdays logins
      my %active_logins = ();
      if ($active_day_fee > 0) {
        my $report_list = $sessions->reports(
          {
            INTERVAL => "$attr->{YESTERDAY}/$attr->{YESTERDAY}",
            TP_ID    => $TP_ID,
          }
        );

        foreach my $l (@$report_list) {
          $active_logins{ $l->[0] } = $l->[6];
        }
      }

      $Dv->{debug} = 1 if ($debug > 6);
      my $ulist = $Dv->list(
        {
          ACTIVATE     => "<=$ADMIN_REPORT{DATE}",
          EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
          JOIN_SERVICE => "<2",
          STATUS       => "0;5",
          LOGIN_STATUS => 0,
          TP_ID        => $TP_ID,
          SORT         => 1,
          PAGE_ROWS    => 1000000,
          TP_CREDIT    => '>=0',
          DELETED      => 0,
          COLS_NAME    => 1,
          %USERS_LIST_PARAMS
        }
      );

      foreach my $u (@$ulist) {
        #Check bill id and deposit
        my %user = (
          LOGIN     => $u->{id},
          UID       => $u->{uid},
          #Check ext deposit
          BILL_ID   => ($line->[14] > 0) ? $u->{ext_bill_id} : $u->{bill_id},
          REDUCTION => $u->{reduction},
          ACTIVATE  => $u->{activate},
          DEPOSIT   => $u->{deposit},
          CREDIT    => ($u->{credit} > 0) ? $u->{credit} : ($CONF->{user_credit_change}) ? 0 : $line->[15],
          DV_STATUS => $u->{dv_status},
        );

        if (defined($user{BILL_ID}) && $user{BILL_ID} > 0 && defined($user{DEPOSIT})) {
          #If deposit is above-zero or TARIF PALIN is POST PAID or PERIODIC PAYMENTS is POSTPAID
          #Active day fees
          if ( (($user{DEPOSIT} + $user{CREDIT} > 0 || $line->[4] == 1 || $TP_INFO{POSTPAID_DAILY} == 1) && $active_day_fee == 0)
            || ($active_day_fee == 1 && $active_logins{ $user{LOGIN} }))
          {
            my $sum = $line->[5];

            # IF TP have PARIODIC PAYMENTS USER reduction
            if ($TP_INFO{REDUCTION} == 1 && $user{REDUCTION} > 0) {
              if ($user{REDUCTION} >= 100) {
                $debug_output .= "UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION} next\n" if ($debug > 3);
                next;
              }
              $sum = $sum * (100 - $user{REDUCTION}) / 100;
            }

            my %PARAMS = (
              DESCRIBE => "Internet: $_DAY_FEE_SHORT $TP_NAME ($TP_ID)",
              DATE     => "$ADMIN_REPORT{DATE} $TIME",
              METHOD   => ($TP_INFO{FEES_METHOD}) ? $TP_INFO{FEES_METHOD} : 1
            );

            if ($debug > 4) {
              $debug_output .= " UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n";
            }
            else {
              $fees->take(\%user, $sum, {%PARAMS});
              if ($fees->{errno}) {
                print "Dv Error: [ $user{UID} ] $user{LOGIN} SUM: $sum [$fees->{errno}] $fees->{errstr} ";
                if ($fees->{errno} == 14) {
                  print "[ $user{UID} ] $user{LOGIN} - Don't have money account";
                }
                print "\n";
              }
              elsif ($debug > 0) {
                $debug_output .= " $user{LOGIN}  UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n" if ($debug > 0);
              }
            }
          }

          # If status too small deposit get fine from user
          elsif ($fine > 0) {
            if ($conf{DV_FINE_LIMIT} && $user{DEPOSIT} + $user{CREDIT} < $conf{DV_FINE_LIMIT}) {
              next;
            }

            %FEES_PARAMS = (
              DESCRIBE => "$_FINE",
              METHOD   => 2,
              DATE     => $ADMIN_REPORT{DATE}
            );
            $EXT_INFO = "FINE";
            $fees->take(\%user, $fine, {%FEES_PARAMS});
            $debug_output .= " $user{LOGIN}  UID: $user{UID} SUM: $fine REDUCTION: $user{REDUCTION} FINE\n" if ($debug > 0);
          }
        }
        else {
          print "[ $user{UID} ] $user{LOGIN} - Don't have money account\n";
        }

      }
    }
  }

  #Daily bonus PAYMENTS
  #Make traffic recalculation for expration
  $list = $tariffs->list({%LIST_PARAMS});
  $debug_output .= "Bonus payments\n";
  use Billing;
  my $Billing = Billing->new($db, $CONF);

  foreach my $tp_line (@$list) {
    my $ti_list = $tariffs->ti_list({ TP_ID => $tp_line->[18] });
    next if ($tariffs->{TOTAL} != 1);

    $debug_output .= "TP_ID: $tp_line->[0]\n" if ($debug > 6);
    foreach my $ti (@$ti_list) {

      my $tt_list = $tariffs->tt_list({ TI_ID => $ti->[0] });
      next if ($tariffs->{TOTAL} < 1);

      my %expr_hash     = ();
      my $traffic_class = 0;

      foreach my $tt (@$tt_list) {
        my $expression = $tt->[8];
        next if ($expression !~ /BONUS_TRAFFIC_/);

        $expression =~ s/BONUS_TRAFFIC/TRAFFIC/g;

        $debug_output .= "TP: $tp_line->[0] TI: $ti->[0] TT: $tt->[0]\n";
        $debug_output .= "  Expr: $expression\n" if ($debug > 3);
        $traffic_class = $tt->[0];

        $expr_hash{$traffic_class} = $expression;

        #last;

        if (!defined($expr_hash{$traffic_class})) {
          next;
        }

        #Get users for bonus payments
        #Ipn users for daily payments
        $ulist = $Dv->list(
          {
            ACTIVATE     => "<=$ADMIN_REPORT{DATE}",
            EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
            STATUS       => 0,
            LOGIN_STATUS => 0,
            TP_ID        => $tp_line->[0],
            SORT         => 1,
            PAGE_ROWS    => 1000000,
            TP_CREDIT    => '>=0',
            COMPANY_ID   => '>=0',
            COLS_NAME    => 1,
            %USERS_LIST_PARAMS
          }
        );

        my $extfield_count = $Dv->{SEARCH_FIELDS_COUNT};
        foreach my $u (@$ulist) {
          %user = (
            LOGIN      => $u->{id},
            UID        => $u->{uid},
            BILL_ID    => ($tp_line->[14] > 0) ? $u->{bill_id} : $u->{ext_bill_id},
            REDUCTION  => $u->{reduction},
            ACTIVATE   => $u->{activate},
            DEPOSIT    => $u->{deposit},
            CREDIT     => ($u->{credit} > 0) ? $u->{credit} : $tp_line->[15],
            COMPANY_ID => $u->{company_id}
          );

          $Billing->{PERIOD_TRAFFIC} = undef;

          my $RESULT = $Billing->expression(
            $user{UID},
            \%expr_hash,
            {
              START_PERIOD  => $attr->{YESTERDAY},
              STOP_PERIOD   => $attr->{DATE},
              debug         => 0,
              IPN           => 1,
              TRAFFIC_CLASS => $traffic_class
            }
          );

          my $message = '';
          my $sum     = 0;

          my %FEES_PARAMS = (
            DATE   => $ADMIN_REPORT{DATE},
            METHOD => 0
          );

          if ($RESULT->{'TRAFFIC_IN'}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED $_TRAFFIC: " . $RESULT->{'TRAFFIC_IN'} . "SUM: $RESULT->{PRICE_IN}";
            $sum = $RESULT->{'TRAFFIC_IN'} * $RESULT->{PRICE_IN};    #(($RESULT->{PRICE_IN}) ? $RESULT->{PRICE_IN} : 0);
          }

          if ($RESULT->{'TRAFFIC_OUT'}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED $_TRAFFIC: " . $RESULT->{'TRAFFIC_OUT'} . "SUM: $RESULT->{PRICE_OUT}";
            $sum = $RESULT->{'TRAFFIC_OUT'} * $RESULT->{PRICE_OUT};
          }
          elsif ($RESULT->{'TRAFFIC_SUM'}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED $_TRAFFIC: " . $RESULT->{'TRAFFIC_SUM'} . " SUM: $RESULT->{PRICE}";
            $sum = $RESULT->{'TRAFFIC_SUM'} * $RESULT->{PRICE};
          }

          if ($sum > 0 && $debug < 5) {
            $payments->add(
              \%user,
              {
                SUM      => $sum,
                METHOD   => 4,
                DESCRIBE => "$_TRAFFIC_CLASS: $traffic_class $_BONUS",
              }
            );
          }

          $debug_output .= " Login: $u->{id} ($u->{uid})  TP_ID: $u->{tp_id} Payments: $sum REDUCTION: $u->{reduction} $u->{deposit} $u->{credit} - $user{ACTIVATE}\n" if ($debug > 0);
        }
      }
    }
  }

  $DEBUG .= $debug_output;
  return $debug_output;
}

#**********************************************************
# holdup_fees
#
#
#**********************************************************
sub dv_holdup_fees {
  my ($attr) = @_;

  my $debug = $attr->{DEBUG} || 0;
  my $debug_output = '';
  $debug_output .= "DV: Holdup abon\n" if ($debug > 1);
  return $debug_output if (!$conf{DV_USER_SERVICE_HOLDUP});
  my ($hold_up_min_period, $hold_up_max_period, $hold_up_period, $holdup_fees, $hold_fees_deposit) = split(/:/, $conf{DV_USER_SERVICE_HOLDUP});
  return $debug_output if (!$holdup_fees || $holdup_fees == 0);

  my %USERS_LIST_PARAMS = ();
  $USERS_LIST_PARAMS{LOGIN}    = $attr->{LOGIN} if ($attr->{LOGIN});
  $USERS_LIST_PARAMS{EXT_BILL} = 1              if ($conf{BONUS_EXT_FUNCTIONS});
  $USERS_LIST_PARAMS{TP_ID}    = $attr->{TP_ID} if ($attr->{TP_ID});

  my $ulist = $Dv->list(
    {
      ACTIVATE     => "<=$ADMIN_REPORT{DATE}",
      EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
      STATUS       => "3",
      LOGIN_STATUS => 0,
      SORT         => 1,
      PAGE_ROWS    => 1000000,
      TP_CREDIT    => '>=0',
      COLS_NAME    => 1,
      %USERS_LIST_PARAMS
    }
  );

  my $extfield_count = $Dv->{SEARCH_FIELDS_COUNT};
  my $ext_deposit_op = 0;

  foreach my $u (@$ulist) {
    my %user = (
      LOGIN        => $u->{id},
      UID          => $u->{uid},
      BILL_ID      => ($ext_deposit_op > 0) ? $u->{ext_bill_id} : $u->{bill_id},
      MAIN_BILL_ID => ($ext_deposit_op > 0) ? $u->{bill_id} : 0,
      REDUCTION    => $u->{reduction},
      ACTIVATE     => $u->{activate},
      DEPOSIT      => $u->{deposit},
      CREDIT       => ($u->{credit} > 0) ? $u->{credit} : 0,
      COMPANY_ID   => $u->{company_id},
      DV_STATUS    => $u->{dv_status},
      EXT_DEPOSIT  => ($u->{ext_deposit}) ? $u->{ext_deposit} : 0,
    );

    $debug_output .= " Login: $user{LOGIN} ($user{UID}) TP_ID: ($u->{tp_id} Fees: $line->[6] REDUCTION: $user{REDUCTION} DEPOSIT: $u->{deposit} CREDIT $user{CREDIT} ACTIVE: $user{ACTIVATE} TP: $u->{tp_num}\n" if ($debug > 3);

    if (($user{BILL_ID} && $user{BILL_ID} > 0) && defined($user{DEPOSIT})) {
      if ($debug > 4) {
        $debug_output .= " UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n";
      }
      else {
        my %FEES_PARAMS = (
          DATE     => $ADMIN_REPORT{DATE},
          METHOD   => 1,
          DESCRIBE => "$_HOLD_UP"
        );
        $fees->take(\%user, $holdup_fees, {%FEES_PARAMS});
        $debug_output .= " $user{LOGIN}  UID: $user{UID} SUM: $holdup_fees REDUCTION: $user{REDUCTION}\n" if ($debug > 0);
      }
    }
    else {
      my $ext = ($ext_deposit_op > 0) ? 'Ext bill' : '';
      print "UID: $user{UID} LOGIN: $user{LOGIN} Don't have $ext money account\n";
    }
  }

  $DEBUG .= $debug_output;
  return $debug_output;
}

#**********************************************************
# Change tp in next period
#**********************************************************
sub dv_monthly_next_tp {
  my ($attr) = @_;

  my $debug         = $attr->{DEBUG} || 0;
  my $debug_output  = '';
  my $list          = $tariffs->list({ NEXT_TARIF_PLAN => '>0' });
  my ($y, $m, $d)   = split(/-/, $ADMIN_REPORT{DATE}, 3);
  my $days_in_month = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($y % 400) || !($y % 4) && ($y % 25) ? 29 : 28));
  my $date_unixtime = mktime(0, 0, 0, $d, ($m - 1), $y - 1900, 0, 0, 0);

  my %CHANGED_TPS = ();

  foreach my $line (@$list) {
    my %TP_INFO = (
      TP_ID      => $line->[0],
      NEXT_TP_ID => $line->[22]
    );

    $Dv->{debug} = 1 if ($debug > 6);
    my $ulist = $Dv->list(
      {
        ACTIVATE     => "<=$ADMIN_REPORT{DATE}",
        EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
        STATUS       => "0",
        LOGIN_STATUS => 0,
        TP_ID        => $TP_INFO{TP_ID},
        SORT         => 1,
        PAGE_ROWS    => 1000000,
        DELETED      => 0,
        COLS_NAME    => 1,
        %USERS_LIST_PARAMS
      }
    );

    my $extfield_count = $Dv->{SEARCH_FIELDS_COUNT};
    foreach my $u (@$ulist) {
      my %user = (
        LOGIN      => $u->{id},
        UID        => $u->{uid},
        REDUCTION  => $u->{reduction},
        ACTIVATE   => $u->{activate},
        DEPOSIT    => $u->{deposit},
        CREDIT     => ($u->{credit} > 0) ? $u->{credit} : ($CONF->{user_credit_change}) ? 0 : $line->[15],
        COMPANY_ID => $u->{company_id},
        DV_STATUS  => $u->{dv_status},
        EXT_DEPOSIT => ($u->{ext_deposit}) ? $u->{ext_deposit} : 0,
      );

      if (!$CHANGED_TPS{ $user{UID} } && ($d == $START_PERIOD_DAY || $user{ACTIVATE} ne '0000-00-00')) {
        if ($user{ACTIVATE} ne '0000-00-00') {
          ($activate_y, $activate_m, $activate_d) = split(/-/, $user{ACTIVATE}, 3);
          $active_unixtime = mktime(0, 0, 0, $activate_d, $activate_m - 1, $activate_y - 1900, 0, 0, 0);

          if ($date_unixtime - $active_unixtime < 30 * 86400) {
            next;
          }
        }

        $debug_output .= " Login: $user{LOGIN} ($user{UID}) ACTIVATE $user{ACTIVATE} TP_ID: $TP_INFO{TP_ID} -> $TP_INFO{NEXT_TP_ID}\n";
        $CHANGED_TPS{ $user{UID} } = 1;
        $Dv->change(
          {
            UID    => $user{UID},
            STATUS => 0,
            TP_ID  => $TP_INFO{NEXT_TP_ID}
          }
        );
      }
    }
  }

  return $debug_output;
}

#**********************************************************
# monthly_fees
# Extended parameters
# TP_ID - Make periodic only for  TP_ID
# LOGIN - Make periodic only for user. You can use wildcard (*)
#**********************************************************
sub dv_monthly_fees {
  my ($attr) = @_;

  my $debug = $attr->{DEBUG} || 0;
  my $debug_output = '';
  $debug_output .= "DV: Monthly periodic payments\n" if ($debug > 1);

  use Users;

  $LIST_PARAMS{TP_ID} = $attr->{TP_ID} if ($attr->{TP_ID});
  my %USERS_LIST_PARAMS = ();
  $USERS_LIST_PARAMS{LOGIN} = $attr->{LOGIN} if ($attr->{LOGIN});
  $USERS_LIST_PARAMS{EXT_BILL} = 1 if ($conf{BONUS_EXT_FUNCTIONS});

  $START_PERIOD_DAY = ($conf{START_PERIOD_DAY}) ? $conf{START_PERIOD_DAY} : 1;
  $ADMIN_REPORT{DATE} = $DATE if (!$ADMIN_REPORT{DATE});

  #Change TP to next TP
  $debug_output .= dv_monthly_next_tp($attr);
  $DEBUG .= $debug_output;

  my $users = Users->new($db, $admin, \%conf);
  my $list = $tariffs->list({%LIST_PARAMS});

  my ($y, $m, $d)      = split(/-/, $ADMIN_REPORT{DATE}, 3);
  my $days_in_month    = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($y % 400) || !($y % 4) && ($y % 25) ? 29 : 28));
  my $cure_month_begin = "$y-$m-01";
  my $cure_month_end   = "$y-$m-$days_in_month";
  $m--;
  my $date_unixtime = mktime(0, 0, 0, $d, $m, $y - 1900, 0, 0, 0);

  #Get Preview month begin end days
  if ($m == 0) {
    $m = 12;
    $y--;
  }

  $m = sprintf("%02d", $m);
  my $days_in_pre_month = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($y % 400) || !($y % 4) && ($y % 25) ? 29 : 28));

  my $pre_month_begin = "$y-$m-01";
  my $pre_month_end   = "$y-$m-$days_in_pre_month";

  foreach my $line (@$list) {
    my %TP_INFO             = ();
    my $TP_ID               = $line->[0];
    my $TP_NAME             = $line->[1];
    my $min_use_sum         = $line->[16];
    my $abon_distrib        = $line->[17];
    my $postpaid            = $line->[4];
    my $month_fee           = $line->[6];
    my $activate_date       = "<=$ADMIN_REPORT{DATE}";
    my $tp_ext_deposit_op   = $line->[14];
    my $small_deposit_block = $line->[19];
    my $fine                = $line->[21];

    $TP_INFO{POSTPAID_MONTHLY} = $line->[13];
    $TP_INFO{REDUCTION}        = $line->[11];
    $TP_INFO{FEES_METHOD}      = $line->[23];

    my %used_traffic = ();

    #Monthfee & min use
    if ($month_fee > 0 || $min_use_sum > 0) {
      $debug_output .= "TP ID: $line->[0] MF: $line->[6] POSTPAID: $TP_INFO{POSTPAID_MONTHLY} REDUCTION: $TP_INFO{REDUCTION} EXT_BILL_ID: $tp_ext_deposit_op CREDIT: $line->[15] MIN_USE: $min_use_sum ABON_DISTR: $abon_distrib\n" if ($debug > 1);

      #get used  traffic for min use functions
      my %processed_users = ();
      if ($min_use_sum > 0 && $START_PERIOD_DAY && $conf{DV_MIN_USER_FULLPERIOD}) {
        my $interval = "$pre_month_begin/$pre_month_end";
        if ($conf{DV_MIN_USER_FULLPERIOD}) {
          $activate_date = strftime "%Y-%m-%d", localtime($date_unixtime - 86400 * 30);
          $interval      = "$activate_date/$ADMIN_REPORT{DATE}";
          $activate_date = "=$activate_date";
        }

        my $report_list = $sessions->reports(
          {
            INTERVAL => $interval,
            TP_ID    => $TP_ID,
          }
        );

        foreach my $l (@$report_list) {
          $used_traffic{ $l->[7] } = $l->[6];
        }
      }
      if ($abon_distrib) {
        $month_fee = $month_fee / $days_in_month;
      }

      $Dv->{debug} = 1 if ($debug > 5);
      my $ulist = $Dv->list(
        {
          ACTIVATE     => "$activate_date",
          EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
          STATUS       => "0;5",
          JOIN_SERVICE => "<2",
          LOGIN_STATUS => 0,
          TP_ID        => $TP_ID,
          SORT         => 1,
          PAGE_ROWS    => 1000000,
          TP_CREDIT    => '>=0',
          DELETED      => 0,
          COLS_NAME    => 1,
          %USERS_LIST_PARAMS
        }
      );

      my $extfield_count = $Dv->{SEARCH_FIELDS_COUNT};
      foreach my $u (@$ulist) {
        my $EXT_INFO       = '';
        my $ext_deposit_op = $tp_ext_deposit_op;
        my %user           = (
          LOGIN        => $u->{id},
          UID          => $u->{uid},
          BILL_ID      => ($ext_deposit_op > 0) ? $u->{ext_billd_id} : $u->{bill_id},
          MAIN_BILL_ID => ($ext_deposit_op > 0) ? $u->{bill_id} : 0,
          REDUCTION    => $u->{reduction},
          ACTIVATE     => $u->{activate},
          DEPOSIT      => $u->{deposit},
          CREDIT       => ($u->{credit} > 0) ? $u->{credit} : ($CONF->{user_credit_change}) ? 0 : $line->[15],
          COMPANY_ID   => $u->{company_id},
          DV_STATUS    => $u->{dv_status},
          EXT_DEPOSIT  => ($u->{ext_deposit}) ? $u->{ext_deposit} : 0,
        );

        $debug_output .= " Login: $user{LOGIN} ($user{UID}) TP_ID: $u->{tp_id} Fees: $line->[6] REDUCTION: $user{REDUCTION} DEPOSIT: $user{DEPOSIT} CREDIT $user{CREDIT} ACTIVE: $user{ACTIVATE} TP: $u->{tp_id}\n" if ($debug > 3);

        if (!$user{BILL_ID} && $user{MAIN_BILL_ID}) {
          $user{BILL_ID}      = $user{MAIN_BILL_ID};
          $user{MAIN_BILL_ID} = 0;
          $ext_deposit_op     = 0;
        }

        if (($user{BILL_ID} && $user{BILL_ID} > 0) && defined($user{DEPOSIT})) {
          my %FEES_PARAMS = (
            DATE   => $ADMIN_REPORT{DATE},
            METHOD => ($TP_INFO{FEES_METHOD}) ? $TP_INFO{FEES_METHOD} : 1
          );
          my $sum = 0;

          #***************************************************************
          #Min use Makes only 1 of month
          if ($min_use_sum > 0 && $d != $START_PERIOD_DAY && !$conf{DV_MIN_USER_FULLPERIOD}) {

            #Check activation date
            my $min_use = $min_use_sum;

            if ($user{REDUCTION} > 0) {
              $min_use = $min_use * (100 - $user{REDUCTION}) / 100;
            }

            #Min use Alignment
            if (!$conf{DV_MIN_USER_FULLPERIOD} && $user{ACTIVATE} ne '0000-00-00') {
              my ($activated_y, $activated_m, $activated_d) = split(/-/, $user{ACTIVATE}, 3);
              my $days_in_month = ($activated_m != 2 ? (($activated_m % 2) ^ ($activated_m > 7)) + 30 : (!($activated_y % 400) || !($activated_y % 4) && ($activated_y % 25) ? 29 : 28));
              $min_use = sprintf("%.5f", $min_use / $days_in_month * ($days_in_month - $activated_d + $START_PERIOD_DAY));
            }

            my $used = ($used_traffic{ $user{UID} }) ? $used_traffic{ $user{UID} } : 0;
            $FEES_PARAMS{DESCRIBE} = "$_MIN_USE";

            #summary for all company users with same tarif plan
            if ($user{COMPANY_ID} > 0 && $processed_users{ $user{COMPANY_ID} }) {
              next;
            }

            if ($user{COMPANY_ID} > 0) {
              my $company_users = $Dv->list(
                {
                  TP_ID      => $TP_ID,
                  COMPANY_ID => $user{COMPANY_ID}
                }
              );
              my @UIDS = ();
              foreach my $c_user (@$company_users) {
                push @UIDS, $c_user->[0];
                $used += $used_traffic{ $user{UID} } if ($used_traffic{ $user{UID} });
                $processed_users{ $user{COMPANY_ID} }++;
              }

              $min_use = $min_use * $processed_users{ $user{COMPANY_ID} };
              $FEES_PARAMS{DESCRIBE} .= "$_COMPANY $_LOGINS: " . join(', ', @UIDS);
            }

            #Get Fees sum for min_user
            if ($conf{MIN_USE_FEES_CONSIDE}) {
              $fees->list(
                {
                  UID     => $user{UID},
                  DATE    => ($user{ACTIVATE} ne '0000-00-00') ? ">=$user{ACTIVATE}" : $DATE,
                  METHODS => "$conf{MIN_USE_FEES_CONSIDE}"
                }
              );
              $used += $fees->{SUM} if ($fees->{SUM});
            }

            $debug_output .= "  USED: $used\n" if ($debug > 3);

            #Make payments
            next if ($used >= $min_use);

            $sum = $min_use - $used;

            if ($TP_INFO{REDUCTION} == 1 && $user{REDUCTION} > 0) {
              if ($user{REDUCTION} >= 100) {
                $debug_output .= "UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION} next\n" if ($debug > 3);
                next;
              }
              $sum = $sum * (100 - $user{REDUCTION}) / 100;
            }

            if ($postpaid == 1 || $user{DEPOSIT} + $user{CREDIT} > 0 || $TP_INFO{POSTPAID_MONTHLY} == 1) {
              if ($d == $START_PERIOD_DAY) {
                if ($debug > 4) {
                  $debug_output .= " UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n";
                }
                else {
                  $fees->take(\%user, $sum, {%FEES_PARAMS});

                  $debug_output .= " $user{LOGIN} UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n" if ($debug > 0);
                  if ($user{ACTIVATE} ne '0000-00-00') {
                    $users->change(
                      $user{UID},
                      {
                        UID      => $user{UID},
                        ACTIVATE => '0000-00-00'
                      }
                    );
                  }
                }
              }
            }
          }

          #***************************************************************
          #Month Fee
          if ($month_fee > 0) {

            #Make sum
            $sum = $month_fee;
            if ($TP_INFO{REDUCTION} == 1 && $user{REDUCTION} > 0) {
              $sum = $sum * (100 - $user{REDUCTION}) / 100;
            }

            my ($activate_y, $activate_m, $activate_d);
            my $active_unixtime = 0;
            if ($user{ACTIVATE} ne '0000-00-00') {
              ($activate_y, $activate_m, $activate_d) = split(/-/, $user{ACTIVATE}, 3);
              $active_unixtime = mktime(0, 0, 0, $activate_d, $activate_m - 1, $activate_y - 1900, 0, 0, 0);
            }

            #Get 2 time fees from main account and ext account and from main
            if ($conf{BONUS_EXT_FUNCTIONS} && $ext_deposit_op > 0) {

              # Small deposit
              if ($small_deposit_block && $user{EXT_DEPOSIT} + $user{DEPOSIT} + $user{CREDIT} < $sum) {
                if (($user{ACTIVATE} eq '0000-00-00' and $d == $START_PERIOD_DAY) || $abon_distrib || ($user{ACTIVATE} ne '0000-00-00' && $date_unixtime - $active_unixtime < 30 * 86400)) {
                  goto SMALL_DEPOSIT_LABEL;
                }
              }
              elsif ($sum > $user{EXT_DEPOSIT} && $user{EXT_DEPOSIT} > 0) {

                # Take some sum from ext deposit other from main
                if ((($user{ACTIVATE} eq '0000-00-00' and $d == $START_PERIOD_DAY) || $abon_distrib) || $user{ACTIVATE} ne '0000-00-00') {
                  if ($date_unixtime - $active_unixtime < 30 * 86400) {
                  }
                  else {
                    my $ext_deposit_sum = $user{EXT_DEPOSIT};

                    $FEES_PARAMS{DESCRIBE} = "Internet: $_MONTH_FEE_SHORT $TP_NAME ($TP_ID)";

                    #"$_MONTH_FEE ($TP_ID)";
                    $fees->take(\%user, $ext_deposit_sum, {%FEES_PARAMS});
                    $sum = $sum - $user{EXT_DEPOSIT};
                    $user{BILL_ID} = $user{MAIN_BILL_ID};
                  }

                  #and after take rest from main DEPOSIT
                  #
                }
              }
              elsif ($user{EXT_DEPOSIT} <= 0) {
                $user{BILL_ID} = $user{MAIN_BILL_ID};
              }
              else {
                $user{DEPOSIT} = $user{EXT_DEPOSIT};
              }
            }

            #If deposit is above-zero or TARIF PALIN is POST PAID or PERIODIC PAYMENTS is POSTPAID
            if ($postpaid == 1 || $user{DEPOSIT} + $user{CREDIT} > 0 || $TP_INFO{POSTPAID_MONTHLY} == 1) {

              #***************************************************************
              #Unblock Small deposit status
              if ($small_deposit_block && $month_fee < $user{DEPOSIT}) {
                $Dv->change(
                  {
                    UID    => $user{UID},
                    STATUS => 0
                  }
                );
              }

              #take fees in first day of month
              $FEES_PARAMS{DESCRIBE} = "Internet: $_MONTH_FEE_SHORT $TP_NAME ($TP_ID)";

              #"$_MONTH_FEE ($TP_ID)";
              $FEES_PARAMS{DESCRIBE} .= " - $_ABON_DISTRIBUTION" if ($abon_distrib);
              if ($user{DV_STATUS} == 5 && $fine > 0) {
                if ($conf{DV_FINE_LIMIT} && $user{DEPOSIT} + $user{CREDIT} < $conf{DV_FINE_LIMIT}) {
                  next;
                }
                $FEES_PARAMS{DESCRIBE} = "$_FINE";
                $FEES_PARAMS{METHOD}   = 2;
                $sum                   = $fine;
                $EXT_INFO              = "FINE";
              }

              # If activation set to monthly fees taken throught 30 days
              elsif ($user{ACTIVATE} ne '0000-00-00') {

                #Block small deposit
                if ($small_deposit_block && $sum > $user{DEPOSIT} + $user{CREDIT} && $date_unixtime - $active_unixtime > 30 * 86400) {
                  SMALL_DEPOSIT_LABEL:

                  if ($small_deposit_block == -1) {
                    $Dv->change(
                      {
                        UID    => $user{UID},
                        STATUS => 5
                      }
                    );
                  }
                  else {
                    $Dv->change(
                      {
                        UID   => $user{UID},
                        TP_ID => $small_deposit_block
                      }
                    );
                  }

                  #Change activation to cure date
                  # !!! We need change activation only if payments add
                  #                 $users->change($user{UID}, {
                  #        	                      UID      => $user{UID},
                  #        	                      ACTIVATE => $ADMIN_REPORT{DATE} });

                  $debug_output .= " SMALL_DEPOSIT_BLOCK." if ($debug > 3);
                  next;
                }

                if ($date_unixtime - $active_unixtime > 30 * 86400) {
                  if ($debug > 4) {
                    $debug_output .= " $user{LOGIN} UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n";
                  }
                  else {
                    $FEES_PARAMS{DESCRIBE} .= " ($ADMIN_REPORT{DATE}-" . (strftime "%Y-%m-%d", localtime($date_unixtime + 86400 * 30)) . ')' if (!$abon_distrib);

                    $fees->take(\%user, $sum, {%FEES_PARAMS});
                    $debug_output .= " $user{LOGIN} UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION} CHANGE ACTIVATE\n" if ($debug > 0);
                    if ($fees->{errno}) {
                      print "Dv Error: [ $user{UID} ] $user{LOGIN} SUM: $sum [$fees->{errno}] $fees->{errstr} ";
                      if ($fees->{errno} == 14) {
                        print "UID: $user{UID} LOGIN: $user{LOGIN} - Don't have money account";
                      }
                      print "\n";
                    }
                    else {
                      $users->change(
                        $user{UID},
                        {
                          UID      => $user{UID},
                          ACTIVATE => $ADMIN_REPORT{DATE}
                        }
                      );
                    }
                    next;
                  }
                }
                elsif ($abon_distrib) {
                  $EXT_INFO .= "CHANGE ACTIVATE\n" if ($debug > 0);
                }
                else {
                  next;
                }
              }
              elsif (($user{ACTIVATE} eq '0000-00-00' and $d == $START_PERIOD_DAY) || $abon_distrib) {

                #Block small deposit
                if ($small_deposit_block && $sum > $user{DEPOSIT} + $user{CREDIT}) {
                  if ($small_deposit_block == -1) {
                    $Dv->change(
                      {
                        UID    => $user{UID},
                        STATUS => 5
                      }
                    );
                  }
                  else {
                    $Dv->change(
                      {
                        UID   => $user{UID},
                        TP_ID => $small_deposit_block
                      }
                    );
                  }
                  $debug_output .= " SMALL_DEPOSIT_BLOCK." if ($debug > 3);
                  next;
                }
              }
              else {
                next;
              }

              # get fees
              if ($debug > 4) {
                $debug_output .= " UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION}\n";
              }
              else {
                $FEES_PARAMS{DESCRIBE} .= " ($cure_month_begin-$cure_month_end)" if (!$abon_distrib);

                $fees->take(\%user, $sum, {%FEES_PARAMS});
                $debug_output .= " $user{LOGIN}  UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION} $EXT_INFO\n" if ($debug > 0);
              }
            }
            else {

              # Get Fine
              if ($fine > 0) {
                if ($conf{DV_FINE_LIMIT} && $user{DEPOSIT} + $user{CREDIT} < $conf{DV_FINE_LIMIT}) {
                  next;
                }
                %FEES_PARAMS = (
                  DESCRIBE => "$_FINE",
                  METHOD   => 1,
                  DATE     => $ADMIN_REPORT{DATE}
                );
                $sum      = $fine;
                $EXT_INFO = "FINE";
                $fees->take(\%user, $sum, {%FEES_PARAMS});
                $debug_output .= " $user{LOGIN}  UID: $user{UID} SUM: $sum REDUCTION: $user{REDUCTION} FINE\n" if ($debug > 0);
              }

              #Block small deposit
              if ($user{DV_STATUS} == 0 && $small_deposit_block && $date_unixtime - $active_unixtime > 30 * 86400) {
                if ($small_deposit_block == -1) {
                  $Dv->change(
                    {
                      UID    => $user{UID},
                      STATUS => 5
                    }
                  );
                }
                else {
                  $Dv->change(
                    {
                      UID   => $user{UID},
                      TP_ID => $small_deposit_block
                    }
                  );
                }
                $debug_output .= " SMALL_DEPOSIT_BLOCK" if ($debug > 3);
                next;
              }
            }
          }
        }
        else {
          my $ext = ($ext_deposit_op > 0) ? 'Ext bill' : '';
          print "UID: $user{UID} LOGIN: $user{LOGIN} Don't have $ext money account\n";
        }
      }
    }
  }

  #=====================================

  #Make traffic recalculation for expration
  if ($d == 1) {
    $list = $tariffs->list({%LIST_PARAMS});
    $debug_output .= "Total month price\n";
    use Billing;
    my $Billing = Billing->new($db, $CONF);

    foreach my $tp_line (@$list) {
      my $ti_list = $tariffs->ti_list({ TP_ID => $tp_line->[18] });
      next if ($tariffs->{TOTAL} != 1);

      foreach my $ti (@$ti_list) {

        my $tt_list = $tariffs->tt_list({ TI_ID => $ti->[0] });
        next if ($tariffs->{TOTAL} != 1);

        my %expr_hash = ();
        foreach my $tt (@$tt_list) {
          my $expression = $tt->[8];
          next if ($expression !~ /MONTH_TRAFFIC_/);

          $expression =~ s/MONTH_TRAFFIC/TRAFFIC/g;

          $debug_output .= "TP: $tp_line->[0] TI: $ti->[0] TT: $tt->[0]\n";
          $debug_output .= "  Expr: $expression\n" if ($debug > 3);

          $expr_hash{ $tt->[0] } = $expression;
        }

        next if (!defined($expr_hash{0}));

        $ulist = $Dv->list(
          {
            ACTIVATE     => "<=$ADMIN_REPORT{DATE}",
            EXPIRE       => "0000-00-00,>$ADMIN_REPORT{DATE}",
            STATUS       => 0,
            LOGIN_STATUS => 0,
            TP_ID        => $tp_line->[0],
            SORT         => 1,
            PAGE_ROWS    => 1000000,
            TP_CREDIT    => '>=0',
            COMPANY_ID   => '>=0',
            COLS_NAME    => 1,
            %USERS_LIST_PARAMS
          }
        );

        my $extfield_count = $Dv->{SEARCH_FIELDS_COUNT};
        foreach my $u (@$ulist) {

          %user = (
            LOGIN      => $u->{id},
            UID        => $u->{uid},
            BILL_ID    => ($tp_line->[14] > 0) ? $u->{ext_bill_id} : $u->{bill_id},
            REDUCTION  => $u->{reduction},
            ACTIVATE   => $u->{activate},
            DEPOSIT    => $u->{deposit},
            CREDIT     => ($u->{credit} > 0) ? $u->{credit} : $tp_line->[15],
            COMPANY_ID => $u->{company_id}
          );

          $debug_output .= " Login: $u->{id} ($u->{uid}) TP_ID: $u->{tp_id} Fees: - REDUCTION: $u->{reduction} $u->{deposit} $u->{credit} - $user{ACTIVATE}\n" if ($debug > 3);

          #Summary for company users
          #         my @UIDS  = ();
          #         if ($$processed_users{$user{COMPANY_ID}}) {
          #         	 next;
          #          }
          #
          #         if ($user{COMPANY_ID}) {
          #           my $company_users = $ulist = $Dv->list({ TP_ID      => $tp_line->[0],
          #                                                    COMPANY_ID => $user{COMPANY_ID}
          #         	                                        });
          #           $$processed_users{$user{COMPANY_ID}}=1;
          #
          #           foreach my $c_user ( @$company_users ) {
          #         	    push @UIDS, $c_user->[7];
          #            }
          #
          #           print "$user{LOGIN} hello $user{COMPANY_ID} // ";
          #           print @UIDS ,"\n";
          #          }

          $Billing->{PERIOD_TRAFFIC} = undef;
          my $RESULT = $Billing->expression(
            $user{UID},
            \%expr_hash,
            {
              START_PERIOD => $user{ACTIVATE},
              debug        => 0,

              #UIDS         => ($#UIDS > -1) ? join(',', @UIDS) : '',
              #ACCOUNTS_SUMMARY => $#UIDS+1
            }
          );

          my $message = '';
          my $sum     = 0;

          my %FEES_PARAMS = (
            DATE   => $ADMIN_REPORT{DATE},
            METHOD => 0
          );

          if ($RESULT->{TRAFFIC_IN}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED \n $_TRAFFIC: $RESULT->{TRAFFIC_IN} \n SUM: $RESULT->{PRICE_IN}";
            $sum = $RESULT->{TRAFFIC_IN} * $RESULT->{PRICE_IN};
          }

          if ($RESULT->{TRAFFIC_OUT}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED $_TRAFFIC: $RESULT->{TRAFFIC_OUT} SUM: $RESULT->{PRICE_OUT}";
            $sum = $RESULT->{TRAFFIC_OUT} * $RESULT->{PRICE_OUT};
          }
          elsif ($RESULT->{TRAFFIC_SUM}) {
            $FEES_PARAMS{DESCRIBE} = "$_USED $_TRAFFIC: $RESULT->{TRAFFIC_SUM} SUM: $RESULT->{PRICE}";
            $sum = $RESULT->{TRAFFIC_SUM} * $RESULT->{PRICE};
          }

          $fees->take(\%user, $sum, {%FEES_PARAMS});
        }

      }
    }

  }

  $DEBUG .= $debug_output;
  return $debug_output;
}

#**********************************************************
# user_warnings
#
#**********************************************************
sub dv_users_warning_messages {
  my ($attr) = @_;

  $ADMIN_REPORT{USERS_WARNINGS} = sprintf("%-14s| %4s|%-20s| %9s| %8s|\n", $_LOGIN, 'TP', $_TARIF_PLAN, $_DEPOSIT, $_CREDIT) . "---------------------------------------------------------------\n";
  if ($ADMIN_REPORT{NO_USERS_WARNINGS}) {
    return 0;
  }


  my $debug = $attr->{DEBUG} || 0;
  my $debug_output = '';
  $debug_output .= "DV: Daily warning messages\n" if ($debug > 1);

  my %LIST_PARAMS     = (USERS_WARNINGS => 1);
  $LIST_PARAMS{ALERT_PERIOD}=$conf{DV_ALERT_REDIRECT} if ($conf{DV_ALERT_REDIRECT});
  $LIST_PARAMS{LOGIN} = $attr->{LOGIN} if ($attr->{LOGIN});
  $Dv->{debug}=1 if($debug > 5);
  my $dv_list         = $Dv->list({ %LIST_PARAMS, 
  	                                COLS_NAME  => 1,
  	                                COLS_UPPER => 1 });


  if ($Dv->{TOTAL} < 1) {
  	$DEBUG .= $debug_output;
    return $debug_output;
  }

  my @allert_redirect_days = split(/,\s?/, $conf{DV_ALERT_REDIRECT} || '');
  
  foreach my $u (@$dv_list) {
  	my $type='email';
    my $email = ((!defined($u->{EMAIL})) || $u->{EMAIL} eq '') ? (($conf{USERS_MAIL_DOMAIN}) ? "$u->{LOGIN}\@$conf{USERS_MAIL_DOMAIN}" : '') : "$u->{EMAIL}";
    if ($email eq '') { next; }

    if($conf{DV_ALERT_REDIRECT_FILTER} && in_array($u->{to_next_period}, \@allert_redirect_days)) {
    	$type='redirect';
    	$Dv->change({ UID       => $u->{uid},
    		            FILTER_ID => $conf{DV_ALERT_REDIRECT_FILTER}
    		          });
    }

    my $info = sprintf("%-14s| %4d|%-20s| %9.4f| %8.2f| %6s|\n", $u->{login}, 
       $u->{tp_num}, 
       $u->{tp_name}, 
       $u->{deposit}, 
       $u->{credit},
       $type);

    $ADMIN_REPORT{USERS_WARNINGS} .= $info;
    $debug_output .= $info if ($debug > 3);

    if ($debug < 5) {
      my $message = $html->tpl_show(_include('dv_users_warning_messages', 'Dv'), $u, { OUTPUT2RETURN => 1 });
      sendmail("$conf{ADMIN_MAIL}", "$email", "$_BILL_INFO", "$message", "$conf{MAIL_CHARSET}", "2 (High)");
    }
  }

  $ADMIN_REPORT{USERS_WARNINGS} .= "---------------------------------------------------------------
$_TOTAL: $Dv->{TOTAL}\n";

  if ($debug > 5) {
    $debug_output .= $ADMIN_REPORT{USERS_WARNINGS};
  }

  $DEBUG .= $debug_output;
  return $debug_output;  
}

#**********************************************************
# form_traf_tarifs()
#**********************************************************
sub dv_traf_tarifs {
  my ($attr) = @_;
  my $tarif_plan;

  if (defined($FORM{tt})) {
    $tarif_plan = $attr->{TP};
    $tarif_plan->tt_defaults();
    $tarif_plan->{TI_ID} = $FORM{tt};

    if ($FORM{add}) {
      $tarif_plan->tt_add({%FORM});
      if (!$tarif_plan->{errno}) {
        $html->message('info', $_INFO, "$_ADDED");
      }
    }
    elsif ($FORM{change}) {
      $FORM{TI_ID} = $FORM{tt};
      $tarif_plan->tt_change({%FORM});

      if (!$tarif_plan->{errno}) {
        $html->message('info', $_INFO, "$_CHANGED");
      }
    }
    elsif (defined($FORM{chg})) {
      $tarif_plan->tt_info({ TI_ID => $FORM{tt}, TT_ID => $FORM{chg} });
      if (!$tarif_plan->{errno}) {
        $html->message('info', $_INFO, "$_CHANGING");
      }
      $tarif_plan->{ACTION}     = 'change';
      $tarif_plan->{LNG_ACTION} = $_CHANGE;
    }
    elsif (defined($FORM{del}) && defined($FORM{is_js_confirmed})) {
      $tarif_plan->tt_del({ TI_ID => $FORM{tt}, TT_ID => $FORM{del} });
      if (!$tarif_plan->{errno}) {
        $html->message('info', $_INFO, "$_DELETED");
      }
    }

    if ($tarif_plan->{errno}) {
      my $messages = "($tarif_plan->{errstr})" if ($tarif_plan->{errstr});
      $html->message('err', $_ERROR, "[$tarif_plan->{errno}] $err_strs{$tarif_plan->{errno}} $messages");
    }
    my $list = $tarif_plan->tt_list({ TI_ID => $FORM{tt}, form => 1 });
    $tarif_plan->{TT_ID} = $tarif_plan->{TOTAL} if (!defined($FORM{chg}));
  }
  elsif ($attr->{TP}) {
    $tarif_plan = $attr->{TP};
    $tarif_plan->tt_defaults();

    if ($FORM{change}) {

      $tarif_plan->tt_change(
        {
          TT_DESCRIBE_0  => $FORM{TT_DESCRIBE_0},
          TT_PRICE_IN_0  => $FORM{TT_PRICE_IN_0},
          TT_PRICE_OUT_0 => $FORM{TT_PRICE_OUT_0},
          TT_NET_ID_0    => $FORM{TT_NETS_0},
          TT_PREPAID_0   => $FORM{TT_PREPAID_0},
          TT_SPEED_0     => $FORM{TT_SPEED_0},

          TT_DESCRIBE_1  => $FORM{'TT_DESCRIBE_1'},
          TT_PRICE_IN_1  => $FORM{TT_PRICE_IN_1},
          TT_PRICE_OUT_1 => $FORM{TT_PRICE_OUT_1},
          TT_NETS_1      => $FORM{TT_NETS_1},
          TT_PREPAID_1   => $FORM{TT_PREPAID_1},
          TT_SPEED_1     => $FORM{TT_SPEED_1},

          TT_DESCRIBE_2 => $FORM{TT_DESCRIBE_2},
          TT_NETS_2     => $FORM{TT_NETS_2},
          TT_SPEED_2    => $FORM{TT_SPEED_2},

          EX_FILE_PATH => "$conf{DV_EXPPP_NETFILES}"
        }
      );

      if ($tarif_plan->{errno}) {
        my $messages = "($tarif_plan->{errstr})" if ($tarif_plan->{errstr});
        $html->message('err', $_ERROR, "[$tarif_plan->{errno}] $err_strs{$tarif_plan->{errno}} $messages");
      }
      else {
        $html->message('info', $_INFO, "$_INTERVALS");
      }
    }

    my $list = $tarif_plan->tt_list($FORM{ti});
  }
}

#***********************************************************
# dv_Sheduler
#***********************************************************
sub dv_sheduler {
  my ($type, $action, $uid, $attr) = @_;

  my $user = $Dv->info($uid);
  if ($type eq 'tp') {
    $Dv->change(
      {
        UID   => $uid,
        TP_ID => $action
      }
    );

    if ($Dv->{errno}) {
      return $Dv->{errno};
    }
    else {
      $Dv->{TP_INFO}->{MONTH_FEE} = 0;
      dv_get_month_fee($Dv, { QUITE => 1 });
    }
  }
  elsif ($type eq 'status') {
    $Dv->change(
      {
        UID    => $uid,
        STATUS => $action
      }
    );

    #Get fee for holdup service
    if ($action == 3) {
      my ($hold_up_min_period, $hold_up_max_period, $hold_up_period, $holdup_fees, $hold_fees_deposit, $active_fees) = split(/:/, $conf{DV_USER_SERVICE_HOLDUP});
      if ($active_fees && $active_fees > 0) {
        my $user = $users->info($uid);
        $fees->take(
          $user,
          $active_fees,
          {
            DESCRIBE => "$_HOLD_UP",
            DATE     => "$ADMIN_REPORT{DATE} $TIME",
          }
        );
        if ($fees->{errno}) {
          print "Error: Holdup fees: $fees->{errno} $fees->{errstr}\n";
        }
      }
    }

    if ($Dv->{errno} && $Dv->{errno} == 15) {
      return $Dv->{errno};
    }
  }

  return 1;
}

#***********************************************************
# dv_report
#***********************************************************
sub dv_report {
  my ($type, $attr) = @_;
  my $REPORT = "Module: DV\n";

  %LIST_PARAMS = %{ $attr->{LIST_PARAMS} } if (defined($attr->{LIST_PARAMS}));

  if ($type eq 'daily') {
    $REPORT .= sprintf("%-14s| %5s| %9s| %9s| %10s| %9s|\n", $_LOGIN, $_SESSIONS, $_TRAFFIC, "$_TRAFFIC 2", $_DURATION, $_SUM);
    $REPORT .= "---------------------------------------------------------\n";

    $list = $sessions->reports({%LIST_PARAMS});
    foreach my $line (@$list) {
      $REPORT .= sprintf("%-14s| %5d| %9s| %9s| %8s| %9.4f|\n", $line->[1], $line->[2], int2byte($line->[3]), int2byte($line->[4]), $line->[5], $line->[6]);
    }

    $REPORT .= "---------------------------------------------------------\n";
    $REPORT .= sprintf(
      "%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n",
      $_USERS, $sessions->{USERS}, $_SESSIONS, $sessions->{SESSIONS}, $_TRAFFIC, int2byte($sessions->{TRAFFIC}),
      "$_TRAFFIC 2", int2byte($sessions->{TRAFFIC_2}),
      $_DURATION, $sessions->{DURATION}, $_SUM, $sessions->{SUM}
    );

  }
  elsif ($type eq 'monthly') {
    $REPORT .= sprintf(" %12s| %5s| %5s| %10s| %10s| %12s| %9s|\n", $_DATE, $_USERS, $_SESSIONS, $_TRAFFIC, "$_TRAFFIC 2", $_DURATION, $_SUM);
    $REPORT .= "---------------------------------------------------------\n";

    my $list = $sessions->reports({%LIST_PARAMS});

    foreach my $line (@$list) {

      #   u.id, count(l.id), sum(l.sent + l.recv), sum(l.sent2 + l.recv2), sec_to_time(sum(l.duration)), sum(l.sum), l.id
      $REPORT .= sprintf(" %12s| %5s| %5s| %10s| %10s| %12s| %9.4f|\n", $line->[0], $line->[1], $line->[2], int2byte($line->[3]), int2byte($line->[4]), $line->[5], $line->[6]);
    }

    $REPORT .= "---------------------------------------------------------\n";
    $REPORT .= sprintf(
      "%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n%-14s| %20s|\n",
      $_USERS, $sessions->{USERS}, $_SESSIONS, $sessions->{SESSIONS}, $_TRAFFIC, int2byte($sessions->{TRAFFIC}),
      "$_TRAFFIC 2", int2byte($sessions->{TRAFFIC_2}),
      $_DURATION, $sessions->{DURATION}, $_SUM, $sessions->{SUM}
    );
  }

  return $REPORT;
}

#*******************************************************************
# Make cards
#*******************************************************************
sub dv_cards {
  require "Abills/modules/Cards/webinterface";

  if ($admin->{MODULES} && !$admin->{MODULES}{Cards}) {
    $html->message('err', $_ERROR, "$ERR_ACCESS_DENY");
    return 0;
  }
  $FROM{CARDS_FORM} = 1;

  my $expire = $FORM{EXPIRE};
  my $dv_tpl = dv_wizard_user(
    {
      OUTPUT2RETURN => 1,
      NO_EXTRADATA  => 1,
      TPLS          => {
        '2:' => '',
        '3:' => ''
      }
    }
  );
  $FORM{EXPIRE} = $expire;
  my $cards_hash = cards_users_add({ EXTRA_TPL => $dv_tpl });

  $FORM{add} = 1;
  if (scalar keys %FORM_BASE < 1) {
    %FORM_BASE = %FORM;
  }

  my $CREATED     = '';
  my $added_count = 0;

  my $table = $html->table(
    {
      width      => '100%',
      border     => 1,
      caption    => "$_USERS",
      title      => [ "$_LOGIN", "ID", "$_INFO" ],
      cols_align => [ 'left', 'right', 'right' ],
      ID         => 'ADDED_USERS'
    }
  );

  if (ref($cards_hash) eq 'ARRAY') {
    foreach my $line (@$cards_hash) {
      %FORM = ();
      %FORM = %FORM_BASE;
      while (my ($k, $v) = each %$line) {
        $FORM{$k} = clearquotes($v);
      }

      $FORM{'1.LOGIN'}       = $line->{LOGIN};
      $FORM{'1.PASSWORD'}    = $line->{PASSWORD};
      $FORM{'1.CREATE_BILL'} = 1;
      $line->{UID} = dv_wizard_user({ SHORT_REPORT => 1 });

      if ($line->{UID} < 1) {
        $html->message('err', "$_ERROR", "$_LOGIN: '$line->{LOGIN}'");
        last if (!$line->{SKIP_ERRORS});
      }
      else {

        #Confim card creation
        $added_count++;
        $table->addrow($html->button($line->{LOGIN}, "index=11&UID=$UID"), "$UID", "$FORM{ex_message}");
        if (cards_users_gen_confim({ %$line, SUM => ($FORM{'5.SUM'}) ? $FORM{'5.SUM'} : 0 }) == 0) {
          return 0;
        }
      }
    }
  }

  if ($added_count > 0) {
    $html->message('info', $_INFO, "$_ADDED:  $added_count");
    print $table->show();
  }
}

#*******************************************************************
#
#*******************************************************************
sub dv_wizard_user {
  my ($attr) = @_;

  my $fees = Finance->fees($db, $admin, \%conf);
  $FORM{DV_WIZARD} = 1;

  if ($FORM{print}) {
    require "Abills/modules/Docs/webinterface";
    if ($FORM{PRINT_CONTRACT}) {
      docs_contract({%$Dv});
    }
    else {
      docs_invoice();
    }
    return 0;
  }

  my %add_values = ();

  if ($FORM{add}) {
    foreach my $k (sort %FORM) {
      if ($k =~ m/^[0-9]+\.[_a-zA-Z0-9]+$/) {
        $k =~ s/%22//g;
        my ($id, $main_key) = split(/\./, $k, 2);
        $add_values{$id}{$main_key} = $FORM{$k};
      }
    }

    # Password
    $add_values{1}{GID} = $admin->{GID} if ($admin->{GID});

    my $user = $users->add({ %{ $add_values{1} }, CREATE_EXT_BILL => ((defined($FORM{'5.EXT_BILL_DEPOSIT'}) || $FORM{'1.CREATE_EXT_BILL'}) ? 1 : 0) });
    my $message = '';
    if (!$user->{errno}) {
      $UID  = $user->{UID};
      $user = $user->info($UID);

      #2
      if (defined($FORM{'2.newpassword'}) && $FORM{'2.newpassword'} ne '') {
        if (length($FORM{'2.newpassword'}) < $conf{PASSWD_LENGTH}) {
          $html->message('err', "$_PASSWD : $_ERROR", "$err_strs{6}");
        }
        elsif ($FORM{'2.newpassword'} eq $FORM{'2.confirm'}) {
          $add_values{2}{PASSWORD} = $FORM{'2.newpassword'};
          $add_values{2}{UID}      = $UID;
          $add_values{2}{DISABLE}  = $FORM{'1.DISABLE'};
        }
        elsif ($FORM{'2.newpassword'} ne $FORM{'2.confirm'}) {
          $html->message('err', "$_PASSWD : $_ERROR", "$err_strs{5}");
        }

        $user->change($UID, { %{ $add_values{2} } });

        if ($conf{external_useradd}) {
          if (!_external($conf{external_useradd}, { LOGIN => $add_values{1}{LOGIN}, %{ $add_values{2} } })) {
            return 0;
          }
        }
      }

      #3 personal info
      $user->pi_add({ UID => "$UID", %{ $add_values{3} } });

      #5 Payments section
      if ($FORM{'5.SUM'}) {
        if ($FORM{'5.SUM'} + 0 > 0) {
          my $er = ($FORM{'5.ER'}) ? $payments->exchange_info($FORM{'5.ER'}) : { ER_RATE => 1 };
          $payments->add($user, { %{ $add_values{5} }, ER => $er->{ER_RATE} });

          if ($payments->{errno}) {
            $html->message('err', "$_PAYMENTS : $_ERROR", "[$payments->{errno}] $err_strs{$payments->{errno}}");
            return 0;
          }
          else {
            $message = "$_PAYMENTS $_SUM: $FORM{'5.SUM'} $er->{ER_SHORT_NAME}\n";
          }
        }
        elsif ($FORM{'5.SUM'} + 0 < 0) {
          my $er = ($FORM{'5.ER'}) ? $payments->exchange_info($FORM{'5.ER'}) : { ER_RATE => 1 };
          $fees->take($user, abs($FORM{'5.SUM'}), { DESCRIBE => 'MIGRATION', ER => $er->{ER_RATE} });

          if ($fees->{errno}) {
            $html->message('err', "$_ERROR : $_FEES", "[$fees->{errno}] $err_strs{$fees->{errno}}");
            return 0;
          }
          else {
            $message = "$_FEES $_SUM: $FORM{'5.SUM'} $er->{ER_SHORT_NAME}\n";
          }
        }
      }

      # Ext bill add
      if ($FORM{'5.EXT_BILL_DEPOSIT'}) {
        $add_values{5}{SUM} = $FORM{'5.EXT_BILL_DEPOSIT'};

        # if Bonus $conf{BONUS_EXT_FUNCTIONS}
        if (in_array('Bonus', \@MODULES) && $conf{BONUS_EXT_FUNCTIONS}) {
          require "Abills/modules/Bonus/webinterface";
          my $Bonus = Bonus->new($db, $admin, \%conf);

          my $sum = $FORM{'5.EXT_BILL_DEPOSIT'};
          %FORM      = %{ $add_values{8} };
          $FORM{UID} = $UID;
          $FORM{SUM} = $sum;
          $FORM{add} = $UID;
          if ($FORM{SUM} < 0) {
            $FORM{ACTION_TYPE} = 1;
            $FORM{SUM}         = abs($FORM{SUM});
          }
          $FORM{SHORT_REPORT} = 1;
          bonus_user_log({ USER_INFO => $user });
        }
        else {
          if ($FORM{'5.EXT_BILL_DEPOSIT'} + 0 > 0) {
            my $er = ($FORM{'5.ER'}) ? $payments->exchange_info($FORM{'5.ER'}) : { ER_RATE => 1 };
            $payments->add(
              $user,
              {
                %{ $add_values{5} },
                BILL_ID => $user->{EXT_BILL_ID},
                ER      => $er->{ER_RATE}
              }
            );

            if ($payments->{errno}) {
              $html->message('err', "$_PAYMENTS : $_ERROR", "[$payments->{errno}] $err_strs{$payments->{errno}}");
              return 0;
            }
            else {
              $message = "$_SUM: $FORM{'5.SUM'} $er->{ER_SHORT_NAME}\n";
            }
          }
          elsif ($FORM{'5.EXT_BILL_DEPOSIT'} + 0 < 0) {
            my $er = ($FORM{'5.ER'}) ? $payments->exchange_info($FORM{'5.ER'}) : { ER_RATE => 1 };
            $fees->take(
              $user,
              abs($FORM{'5.EXT_BILL_DEPOSIT'}),
              {
                BILL_ID  => $user->{EXT_BILL_ID},
                DESCRIBE => 'MIGRATION',
                ER       => $er->{ER_RATE}
              }
            );

            if ($fees->{errno}) {
              $html->message('err', "$_ERROR : $_FEES", "[$fees->{errno}] $err_strs{$fees->{errno}}");
              return 0;
            }
            else {
              $message = "$_SUM: $FORM{'5.EXT_BILL_DEPOSIT'} $er->{ER_SHORT_NAME}\n";
            }
          }
        }
      }

      #4 Dv
      # Make Dv service only with TP
      if ($add_values{4}{TP_ID}) {
        if ($add_values{4}{IP} =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $add_values{4}{IP} ne '0.0.0.0') {
          my $list = $Dv->list({ IP => $add_values{4}{IP} });
          if ($Dv->{TOTAL} > 0 && $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ] != $FORM{UID}) {
            $html->message('err', $_ERROR, "IP: $FORM{IP} $_EXIST. \n $_LOGIN: " . $html->button("$list->[0][0]", "index=15&UID=" . $list->[0][ 6 + $Dv->{SEARCH_FIELDS_COUNT} ]));
            return 0;
          }
        }

        my $user_fees;
        $Dv->add({ UID => $UID, %{ $add_values{4} } });
        if ($Dv->{errno}) {
          $html->message('err', "Dv:$_ERROR", "Dv Modules [$Dv->{errno}] $err_strs{$Dv->{errno}}");
          return 0;
        }
        elsif (!$FORM{SERIAL}) {
          if (!$add_values{4}{STATUS} && $Dv->{TP_INFO}->{MONTH_FEE} > 0) {
            $Dv->{UID}              = $UID;
            $Dv->{ACCOUNT_ACTIVATE} = $add_values{1}{ACTIVATE};
            $user_fees              = dv_get_month_fee($Dv);
          }
        }
      }

      # Add E-Mail account
      my $Mail;
      if (in_array('Mail', \@MODULES) && $FORM{'6.USERNAME'}) {
        require "Abills/modules/Mail/webinterface";
        $Mail = Mail->new($db, $admin, \%conf);

        $FORM{'6.newpassword'} = $FORM{'6.PASSWORD'} if ($FORM{'6.PASSWORD'});

        $Mail->mbox_add(
          {
            UID => "$UID",
            %{ $add_values{6} },
            PASSWORD => $FORM{'6.newpassword'},
          }
        );
        $Mail->{PASSWORD} = $FORM{'6.newpassword'};

        if ($Mail->{errno}) {
          $html->message('err', "E-MAIL : $_ERROR", "[$Mail->{errno}] $err_strs{$Mail->{errno}}");
          return 0;
        }
        elsif ($FORM{'6.SEND_MAIL'}) {
          my $message = $html->tpl_show(_include('mail_test_msg', 'Mail'), $Mail, { OUTPUT2RETURN => 1 });
          sendmail("$conf{ADMIN_MAIL}", "$Mail->{USER_EMAIL}", "Test mail", "$message", "$conf{MAIL_CHARSET}", "");
        }

        $Mail = $Mail->mbox_info({ MBOX_ID => $Mail->{MBOX_ID} });
        $Mail->{EMAIL_ADDR} = $Mail->{USERNAME} . '@' . $Mail->{DOMAIN};
      }

      # Msgs
      if (in_array('Msgs', \@MODULES) && $add_values{7} && $FORM{'7.SUBJECT'}) {
        require "Abills/modules/Msgs/webinterface";
        $FORM{INNER_MSG} = 1;
        my $Msgs = Msgs->new($db, $admin, \%conf);

        %FORM      = %{ $add_values{7} };
        $FORM{UID} = $UID;
        $FORM{add} = $UID;
        msgs_admin_add({ SEND_ONLY => 1 });
      }

      # Abon
      if (in_array('Abon', \@MODULES) && $add_values{9}) {
        require "Abills/modules/Abon/webinterface";
        %FORM         = %{ $add_values{9} };
        $FORM{UID}    = $UID;
        $FORM{change} = $UID;
        abon_user({ QUITE => 1 });
      }

      #Fees wizard form
      if ($add_values{10}) {
        %FORM      = %{ $add_values{10} };
        $FORM{UID} = $UID;
        $FORM{add} = $UID;
        form_fees_wizard({ USER_INFO => $user });
      }

      # Info
      my $dv = $Dv->info($UID);
      my $pi = $user->pi({ UID => $UID });
      $user  = $user->info($UID, { SHOW_PASSWORD => 1 });

      if (!$attr->{SHORT_REPORT}) {
        $FORM{ex_message} = $message;
        if (in_array('Docs', \@MODULES)) {
          $message .= "$_CONTRACT: $pi->{CONTRACT_SUFIX}$pi->{CONTRACT_ID}" . $html->button("$_PRINT $_CONTRACT", "qindex=$index&UID=$UID&PRINT_CONTRACT=$UID&print=1" . (($conf{DOCS_PDF_PRINT}) ? '&pdf=1' : ''), { ex_params => 'target=_new', CLASS => 'print' });
        }

        $html->message('info', $_ADDED, "LOGIN: $add_values{1}{LOGIN}\nUID: $UID\n$message");
        $html->tpl_show(templates('form_user_info'), { %$user, %$pi, DATE => $DATE, TIME => $TIME });
        $dv->{STATUS} = $service_status[ $dv->{STATUS} ];
        $html->tpl_show(_include('dv_user_info', 'Dv'), $dv);
        $html->tpl_show(_include('mail_user_info', 'Mail'), $Mail) if ($Mail);

        #If docs module enable make account
        if (in_array('Docs', \@MODULES) && $FORM{'4.NO_ACCOUNT'}) {
          $LIST_PARAMS{UID} = $UID;

          if ($user_fees->{MONTH_FEE} + $user_fees->{ACTIVATE} > 0) {
            require "Abills/modules/Docs/lng_$html->{language}.pl";
            require "Abills/modules/Docs/webinterface";

            $FORM{DATE}     = $DATE;
            $FORM{CUSTOMER} = $pi->{FIO} || '-';
            $FORM{PHONE}    = $pi->{PHONE};
            $FORM{UID}      = $UID;

            $FORM{'IDS'}     = '1, 2';
            $FORM{'ORDER_1'} = "$_DV";
            $FORM{'COUNT_1'} = 1;
            $FORM{'UNIT_1'}  = 0;
            $FORM{'SUM_1'}   = $user_fees->{MONTH_FEE};

            if ($tariffs->{ACTIV_PRICE}) {
              $FORM{'ORDER_2'} = "$_ACTIVATE";
              $FORM{'COUNT_2'} = 1;
              $FORM{'UNIT_2'}  = 0;
              $FORM{'SUM_2'}   = $user_fees->{MONTH_FEE};
            }

            $FORM{'create'} = 1;
            docs_invoice();
          }
        }
      }

      return $UID;
    }
    else {
      if ($users->{errno} == 7) {
        $html->message('err', "$_ERROR", "$_LOGIN: '$add_values{1}{LOGIN}' $_USER_EXIST");
      }
      else {
        $html->message('err', "[$users->{errno}] $err_strs{$users->{errno}}", "$_LOGIN: '$add_values{1}{LOGIN}'");
      }
      return 0 if ($attr->{SHORT_REPORT});
    }

  }

  foreach my $k (keys %FORM) {
    next if ($k eq '__BUFFER');
    my $val = $FORM{$k};
    if ($k =~ /\d+\.([A-Z0-9\_]+)/ig) {
      my $key = $1;
      $FORM{"$key"} = $val;
    }
  }

  my $users_defaults = $users->defaults();
  $users_defaults->{DISABLE} = ($users_defaults->{DISABLE} == 1) ? ' checked' : '';
  $users_defaults->{GID} = sel_groups();

  #Info fields

  if (!$attr->{NO_EXTRADATA}) {
    $users_defaults->{EXDATA} = $user_info->{EXDATA} .= $html->tpl_show(templates('form_user_exdata_add'), { CREATE_BILL => ' checked' }, { OUTPUT2RETURN => 1 });
    $users_defaults->{EXDATA} .= $html->tpl_show(templates('form_ext_bill_add'), { CREATE_EXT_BILL => ' checked' }, { OUTPUT2RETURN => 1 }) if ($conf{EXT_BILL_ACCOUNT});
  }

  my $dv_defaults = $Dv->defaults();
  $dv_defaults->{STATUS_SEL} = $html->form_select(
    'STATUS',
    {
      SELECTED => $FORM{STATUS} || undef,
      SEL_ARRAY    => \@service_status,
      STYLE        => \@service_status_colors,
      ARRAY_NUM_ID => 1
    }
  );

  $dv_defaults->{TP_ID} = $html->form_select(
    'TP_ID',
    {
      SELECTED          => $FORM{TP_ID},
      SEL_MULTI_ARRAY   => $tariffs->list({ MODULE => 'Dv' }),
      MULTI_ARRAY_KEY   => 0,
      MULTI_ARRAY_VALUE => 1,
    }
  );
  delete($FORM{TP_ID});
  $dv_defaults->{CALLBACK} = '';

  my $password_form;
  $password_form->{GEN_PASSWORD} = mk_unique_value(8);
  $password_form->{PW_CHARS}     = $conf{PASSWD_SYMBOLS} || "abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ";
  $password_form->{PW_LENGTH}    = $conf{PASSWD_LENGTH} || 6;

  #Info fields
  my %pi_form = ();

  my $i = 0;

  my $list = $users->config_list({ PARAM => 'ifu*', SORT => 2 });

  foreach my $line (@$list) {
    my $field_id = '';
    if ($line->[0] =~ /ifu(\S+)/) {
      $field_id = "3." . $1;
      my ($position, $type, $name, $user_portal) = split(/:/, $line->[1]);

      my $input = '';
      if ($type == 2) {
        my $table_name = $field_id;
        $table_name =~ s/3\.//;

        $input = $html->form_select(
          "$field_id",
          {
            SELECTED          => $FORM{$field_id},
            SEL_MULTI_ARRAY   => $users->info_lists_list({ LIST_TABLE => $table_name . '_list' }),
            MULTI_ARRAY_KEY   => 0,
            MULTI_ARRAY_VALUE => 1,
            SEL_OPTIONS       => { 0 => '-N/S-' },
            NO_ID             => 1
          }
        );

      }
      elsif ($type == 4) {
        $input = $html->form_input($field_id, 1, { TYPE => 'checkbox', STATE => ($FORM{$field_id}) ? 1 : undef });
      }
      elsif ($type == 3) {
        $input = $html->form_textarea($field_id, "$users->{INFO_FIELDS_VAL}->[$i]");
      }
      elsif ($type == 13) {
        $input = $html->form_input($field_id, "$users->{INFO_FIELDS_VAL}->[$i]", { TYPE => 'file' });
      }
      else {
        $input = $html->form_input($field_id, "", { SIZE => 40 });
      }

      $pi_form{INFO_FIELDS} .= "<tr><td>$name:</td><td>$input</td></tr>\n";
      $i++;
    }
  }

  if ($conf{DOCS_CONTRACT_TYPES}) {

    #PREFIX:SUFIX:NAME;

    $conf{DOCS_CONTRACT_TYPES} =~ s/\n//g;
    my (@contract_types_list) = split(/;/, $conf{DOCS_CONTRACT_TYPES});

    my %CONTRACTS_LIST_HASH = ();
    foreach my $line (@contract_types_list) {
      my ($prefix, $sufix, $name, $tpl_name) = split(/:/, $line);
      $prefix =~ s/ //g;
      $CONTRACTS_LIST_HASH{"$prefix|$sufix"} = $name;
    }

    $pi_form{CONTRACT_TYPE} = " $_TYPE: "
    . $html->form_select(
      'CONTRACT_TYPE',
      {
        SELECTED => '',
        SEL_HASH => { '' => '', %CONTRACTS_LIST_HASH },
        NO_ID    => 1
      }
    );
  }

  $pi_form{PASPORT_DATE} = $html->date_fld2(
    'PASPORT_DATE',
    {
      FORM_NAME => 'user_form',
      WEEK_DAYS => \@WEEKDAYS,
      MONTHES   => \@MONTHES,
      DATE      => $user_pi->{PASPORT_DATE}
    }
  );

  $pi_form{CONTRACT_DATE} = $html->date_fld2(
    'CONTRACT_DATE',
    {
      FORM_NAME => 'user_form',
      WEEK_DAYS => \@WEEKDAYS,
      MONTHES   => \@MONTHES,
      DATE      => $user_pi->{CONTRACT_DATE}
    }
  );

  if ($conf{ADDRESS_REGISTER}) {
    $pi_form{ADDRESS_TPL} = $html->tpl_show(templates('form_address_sel'), $user_pi, { OUTPUT2RETURN => 1 });
  }
  else {
    $pi_form{ADDRESS_TPL} = $html->tpl_show(templates('form_address'), undef, { OUTPUT2RETURN => 1 });
  }

  $dv_defaults->{JOIN_SERVICE} = '';
  $list = $Nas->ip_pools_list({ STATIC => 1 });

  $dv_defaults->{STATIC_IP_POOL} = $html->form_select(
    'STATIC_IP_POOL',
    {
      SELECTED          => $FORM{STATIC_POOL},
      SEL_MULTI_ARRAY   => [ [ '', '' ], @$list ],
      MULTI_ARRAY_KEY   => 8,
      MULTI_ARRAY_VALUE => '1',
      NO_ID             => 1
    }
  );

  my %tpls = (
    "01:$_LOGIN::"  => $html->tpl_show(templates('form_user'),     { %$users_defaults, %FORM }, { OUTPUT2RETURN => 1, ID => 'FORM_USER' }),
    "02:$_PASSWD::" => $html->tpl_show(templates('form_password'), { %$password_form,  %FORM }, { OUTPUT2RETURN => 1, ID => 'FORM_PASSWORD' }),
    "03:$_INFO::"   => $html->tpl_show(templates('form_pi'),       { %pi_form,         %FORM }, { OUTPUT2RETURN => 1, ID => 'FORM_PI' }),
    "04:Internet::" => $html->tpl_show(_include('dv_user', 'Dv'), { %$dv_defaults, %FORM }, { OUTPUT2RETURN => 1, ID => 'DV_USER' }),
  );

  #Payments
  if ($permissions{1} && $permissions{1}{1}) {
    $payments->{SEL_METHOD} = $html->form_select(
      'METHOD',
      {
        SELECTED => $FORM{METHOD} || undef,
        SEL_ARRAY    => \@PAYMENT_METHODS,
        ARRAY_NUM_ID => 1
      }
    );
    $payments->{SUM}    = '0.00';
    $payments->{SEL_ER} = $html->form_select(
      'ER',
      {
        SELECTED          => undef,
        SEL_MULTI_ARRAY   => [ [ '', '', '', '', '' ], @{ $payments->exchange_list() } ],
        MULTI_ARRAY_KEY   => 4,
        MULTI_ARRAY_VALUE => '1,2',
        NO_ID             => 1
      }
    );

    $tpls{"05:$_PAYMENTS::"} = $html->tpl_show(templates('form_payments'), $payments, { OUTPUT2RETURN => 1, ID => 'FORM_PAYMENTS' });
  }

  #If mail module added
  if (in_array('Mail', \@MODULES)) {
    require "Abills/modules/Mail/webinterface";
    my $Mail = Mail->new($db, $admin, \%conf);

    $Mail->{PASSWORD} = qq{  
	<tr><td>$_PASSWD:</td><td><input type="password" id="text_pma_pw_mail" name="newpassword" title="$_PASSWD" onchange="pred_password.value = 'userdefined';" /></td></tr>
  <tr><td>$_CONFIRM_PASSWD:</td><td><input type="password" name="confirm" id="text_pma_pw2_mail" title="$_CONFIRM" onchange="pred_password.value = 'userdefined';" /></td></tr>
  <tr><td>  <input type="button" id="button_generate_password_mail" value="$_GET $_USER $_PASSWD" onclick="CopyInputField('text_pma_pw', 'generated_pw_mail');" />
          <input type="button" id="button_copy_password_mail" value="Copy" onclick="CopyInputField('generated_pw_mail', 'text_pma_pw_mail'); CopyInputField('generated_pw_mail', 'text_pma_pw2_mail')" />
    </td><td><input type="text" name="generated_pw" id="generated_pw_mail" /></td></tr>
     };

    $Mail->{SEND_MAIL} = 'checked';

    $Mail->{DOMAINS_SEL} = $html->form_select(
      'DOMAIN_ID',
      {
        SELECTED          => $Mail->{DOMAIN_ID},
        SEL_MULTI_ARRAY   => $Mail->domain_list(),
        MULTI_ARRAY_KEY   => 8,
        MULTI_ARRAY_VALUE => 0,
        SEL_OPTIONS       => { 0 => '-N/S-' },
        NO_ID             => 1
      }
    );

    $tpls{"06:E-Mail::"} = $html->tpl_show(_include('mail_box', 'Mail'), $Mail, { OUTPUT2RETURN => 1, ID => 'MAIL_BOX' });
  }

  #If msgs module added
  if (in_array('Msgs', \@MODULES) && !defined($FROM{CARDS_FORM})) {
    require "Abills/modules/Msgs/webinterface";
    my $Msgs = Msgs->new($db, $admin, \%conf);
    $FORM{UID} = -1;
    $tpls{"07:$_MESSAGE::"} = msgs_admin_add({ OUTPUT2RETURN => 1 });
  }

  $tpls{"10:$_FEES::"} = form_fees_wizard({ OUTPUT2RETURN => 1 });

  if ($attr->{TPLS}) {
    while (my ($k, $v) = each %{ $attr->{TPLS} }) {
      $tpls{$k} = $v;
    }
  }

  my $wizard;

  my $template         = '';
  my @sorted_templates = sort keys %tpls;

  foreach my $key (@sorted_templates) {
    my ($n, $descr, $pre, $post) = split(/:/, $key, 4);
    $n = int($n);
    $template .= "<tr class='title_color'><th>$descr</th></tr>\n";
    my $sub_tpl .= $html->tpl_show($tpls{"$key"}, $wizard, { OUTPUT2RETURN => 1, ID => "$descr" });
    $sub_tpl =~ s/(<input .*?UID.*?>)//gi;
    $sub_tpl =~ s/(<input .*?index.*?>)//gi;
    $sub_tpl =~ s/name=[\'\"]?([A-Z_0-9]+)[\'\"]? /name=$n.$1 /ig;
    my $class = ($n % 2) ? 'odd' : 'even';
    $template .= "<tr><th class=$class align=center>" . $sub_tpl . "</th></tr>\n";
  }

  $template =~ s/(<form .*?>)//gi;
  $template =~ s/<\/form>//ig;
  $template =~ s/(<input .*?type=submit.*?>)//gi;
  $template =~ s/<hr>//gi;

  $template = "<table width=\"100%\">$template</table>";
  if ($attr->{OUTPUT2RETURN}) {
    return $template;
  }

  print $html->form_main(
    {
      CONTENT => $template,
      HIDDEN  => { index => "$index" },
      SUBMIT  => { add => "$_ADD" },
      NAME    => 'user_form',
      ENCTYPE => 'multipart/form-data'
    }
  );

}

#**********************************************************
#
#**********************************************************
sub dv_registration {
  my ($attr) = @_;

  if ($FORM{reg}) {
    if ($attr->{CAPTCHA} && $attr->{CAPTCHA_OBJ}->check_code("$FORM{CCODE}", "$FORM{C}") != 1) {
      $Dv->{MESSAGE} = $html->message('err', $_ERROR, "$ERR_WRONG_CAPTCHA");
    }
    elsif ($FORM{EMAIL} !~ /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/) {
      $Dv->{MESSAGE} = $html->message('err', $_ERROR, "$_WRONG_EMAIL");
    }
    elsif (!$FORM{ACCEPT_RULES}) {
      $html->message('err', $_ERROR, "$ERR_ACCEPT_RULES");
    }
    else {
      my $password = mk_unique_value(8);

      my $user = $users->add(
        {
          LOGIN       => $FORM{LOGIN},
          CREATE_BILL => 1,
          PASSWORD    => $password
        }
      );
      my $message = '';
      if (!$user->{errno}) {
        my $UID = $user->{UID};
        $user = $user->info($UID);

        #3 personal info
        $user->pi_add(
          {
            %FORM,
            UID   => "$UID",
            FIO   => "$FORM{FIO}",
            EMAIL => "$FORM{EMAIL}"
          }
        );

        if ($user->{errno}) {
          $Dv->{MESSAGE} = $html->message('err', $_ERROR, "[$user->{errno}] $err_strs{$user->{errno}}");
          goto REG_FORM;
        }

        #4 Dv
        $conf{SHARING_DEFAULT_TP} = 0 if (!$conf{SHARING_DEFAULT_TP});
        $Dv->add(
          {
            UID   => $UID,
            TP_ID => $FORM{TP_ID} || $conf{SHARING_DEFAULT_TP}
          }
        );

        if (!$Dv->{errno}) {
          if ($conf{REGISTRATION_SHOW_PASSWD}) {
            $Dv->{PASSWD} = $password;
          }
          else {
            $Dv->{PASSWD} = "E-mail $_SENDED";
          }

          $html->tpl_show(_include('dv_reg_complete', 'Dv'), { %$Dv, %FORM });

          #Send mail
          my $message = $html->tpl_show(_include('dv_reg_complete_mail', 'Dv'), { %$Dv, %FORM, PASSWORD => "$password" }, { OUTPUT2RETURN => 1 });
          sendmail("$conf{ADMIN_MAIL}", "$FORM{EMAIL}", "$_REGISTRATION", "$message", "$conf{MAIL_CHARSET}", '');

          return 2;
        }
        else {
          $html->message('err', $_ERROR, "[$Dv->{errno}] $err_strs{$Dv->{errno}}");
        }

      }
      else {
        if ($user->{errno} == 7) {
          $html->message('err', $_ERROR, "$_USER_EXIST");
        }
        else {
          $html->message('err', $_ERROR, "[$user->{errno}] $err_strs{$user->{errno}}");
        }
        goto REG_FORM;
      }
    }
  }

  REG_FORM:

  if ($conf{DV_REGISTRATION_TP_GIDS}) {
    $LIST_PARAMS{TP_GID} = $conf{DV_REGISTRATION_TP_GIDS};
  }
  else {
    $LIST_PARAMS{TP_GID} = '>0';
  }

  $Dv->{TP_SEL} = $html->form_select(
    'TP_ID',
    {
      SELECTED          => $FORM{TP_ID},
      SEL_MULTI_ARRAY   => $tariffs->list({ %LIST_PARAMS, MODULE => 'Dv' }),
      MULTI_ARRAY_KEY   => 0,
      MULTI_ARRAY_VALUE => 1,
    }
  );

  $html->tpl_show(_include('dv_registration', 'Dv'), { %$Dv, %$attr, %FORM }, { ID => 'DV_REGISTRATION' });

  return 0;
}

#**********************************************************
#
#Make month feee
#**********************************************************
sub dv_get_month_fee {
  my ($Dv, $attr) = @_;

  my %total_sum = (
    ACTIVATE  => 0,
    MONTH_FEE => 0
  );

  $users = $user if ($user->{UID});

  #Make bonus
  if ($conf{DV_BONUS}) {
    eval { require Bonus_rating; };
    if (!$@) {
      Bonus_rating->import();
    }
    else {
      $html->message('err', $_ERROR, "Can't load 'Bonus_rating'. Purchase this module http://abills.net.ua") if (!$attr->{QUITE});
      return 0;
    }

    my $Bonus_rating = Bonus_rating->new($db, $admin, \%conf);
    $Bonus_rating->info($Dv->{TP_INFO}->{TP_ID});

    if ($Bonus_rating->{TOTAL} > 0) {
      my $bonus_sum = 0;
      if ($FORM{add} && $Bonus_rating->{ACTIVE_BONUS} > 0) {
        $bonus_sum = $Bonus_rating->{ACTIVE_BONUS};
      }
      elsif ($Bonus_rating->{CHANGE_BONUS} > 0) {
        $bonus_sum = $Bonus_rating->{CHANGE_BONUS};
      }

      if ($bonus_sum > 0) {
        if (!$users->{BILL_ID}) {
          $users->info($Dv->{UID});
        }

        $payments->add(
          {
            BILL_ID => ($Bonus_rating->{EXT_BILL_ACCOUNT}) ? $users->{EXT_BILL_ID} : $users->{BILL_ID},
            UID => $users->{UID}
          },
          {
            SUM      => $bonus_sum,
            METHOD   => 4,
            DESCRIBE => "$_BONUS: $_TARIF_PLAN: $Dv->{TP_ID}",
          }
        );
        if ($payments->{errno}) {
          $html->message('err', $_ERROR, "[$payments->{errno}] $payments->{errstr}") if (!$attr->{QUITE});
        }
        else {
          $html->message('info', $_INFO, "$_BONUS: $bonus_sum") if (!$attr->{QUITE});
        }
      }
    }
  }

  #Get active price
  if ($Dv->{TP_INFO}->{ACTIV_PRICE} > 0) {
    my $users = Users->new($db, $admin, \%conf);
    my $user  = $users->info($Dv->{UID});
    my $date  = ($user->{ACTIVATE} ne '0000-00-00') ? $user->{ACTIVATE} : $DATE;
    my $time  = ($user->{ACTIVATE} ne '0000-00-00') ? '00:00:00' : $TIME;

    if (!$Dv->{OLD_STATUS} || $Dv->{OLD_STATUS} == 2) {
      $fees->take(
        $user,
        $Dv->{TP_INFO}->{ACTIV_PRICE},
        {
          DESCRIBE => "$_ACTIVATE $_TARIF_PLAN",
          DATE     => "$date $time"
        }
      );
      $total_sum{ACTIVATE} = $Dv->{TP_INFO}->{ACTIV_PRICE};
      $html->message('info', $_INFO, "- $_ACTIVATE $_TARIF_PLAN") if ($html);
    }
  }

  #Get month fee
  if ($Dv->{TP_INFO}->{MONTH_FEE} > 0) {
    my $sum   = $Dv->{TP_INFO}->{MONTH_FEE};
    my $users = Users->new($db, $admin, \%conf);
    my $user  = $users->info($Dv->{UID});

    if ($Dv->{TP_INFO}->{EXT_BILL_ACCOUNT}) {
      if ($user->{EXT_BILL_ID}) {
        if (!$conf{BONUS_EXT_FUNCTIONS} || ($conf{BONUS_EXT_FUNCTIONS} && $user->{EXT_BILL_DEPOSIT} > 0)) {
          $user->{MAIN_BILL_ID} = $user->{BILL_ID};
          $user->{BILL_ID}      = $user->{EXT_BILL_ID};
        }
      }
    }

    my $message = '';

    #Current Month
    my ($y, $m, $d) = split(/-/, $DATE, 3);

    my ($active_y, $active_m, $active_d) = split(/-/, $Dv->{ACCOUNT_ACTIVATE} || $users->{ACTIVATE}, 3);

    if (int("$y$m$d") < int("$active_y$active_m$active_d")) {
      return \%total_sum;
    }

    if ($Dv->{TP_INFO}->{PERIOD_ALIGNMENT} && !$Dv->{TP_INFO}->{ABON_DISTRIBUTION}) {
      $message = "$_MONTH_ALIGNMENT, ";
      my $days_in_month = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($y % 400) || !($y % 4) && ($y % 25) ? 29 : 28));

      if ($Dv->{ACCOUNT_ACTIVATE} && $Dv->{ACCOUNT_ACTIVATE} ne '0000-00-00') {
        $days_in_month = ($active_m != 2 ? (($active_m % 2) ^ ($active_m > 7)) + 30 : (!($active_y % 400) || !($active_y % 4) && ($active_y % 25) ? 29 : 28));
        $d = $active_d;
      }
      $conf{START_PERIOD_DAY} = 1 if (!$conf{START_PERIOD_DAY});
      my $calculation_days = ($d < $conf{START_PERIOD_DAY}) ? $conf{START_PERIOD_DAY} - $d : $days_in_month - $d + $conf{START_PERIOD_DAY};
      
      $sum = sprintf("%.2f", ($sum / $days_in_month) * $calculation_days);
    }

    return \%total_sum if ($sum == 0);

    my $periods = 0;
    if (int($active_m) > 0 && int($active_m) < $m) {
      $periods = $m - $active_m;
      if (int($active_d) > int($d)) {
        $periods--;
      }
    }
    elsif (int($active_m) > 0 && (int($active_m) >= int($m) && int($active_y) < int($y))) {
      print "/ if (int($active_d) > int($d)) { /";
      $periods = 12 - $active_m + $m;
      if (int($active_d) > int($d)) {
        $periods--;
      }
    }

    #Make reduction
    if ($user->{REDUCTION} > 0 && $Dv->{TP_INFO}->{REDUCTION_FEE}) {
      $sum = $sum * (100 - $users->{REDUCTION}) / 100;
    }

    $message .= "Internet: $_MONTH_FEE_SHORT $Dv->{TP_INFO}->{NAME} ($Dv->{TP_INFO}->{ID})";

    if ($Dv->{TP_INFO}->{ABON_DISTRIBUTION}) {
      $sum = $sum / (($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($y % 400) || !($y % 4) && ($y % 25) ? 29 : 28)));
      $message .= " - $_ABON_DISTRIBUTION";
    }

    if ($Dv->{ACCOUNT_ACTIVATE} ne '0000-00-00' && ($Dv->{OLD_STATUS} == 5)) {
      #if activation in cure month curmonth
      if ($periods == 0 || ($periods == 1 && $d < $active_d)) {
        $periods = -1;
      }
      else {
        $periods = 0;
      }
    }

    $m = $active_m if ($active_m > 0);

    for (my $i = 0 ; $i <= $periods ; $i++) {
      if ($m > 12) {
        $m        = 1;
        $active_y = $active_y + 1;
      }

      $m = sprintf("%.2d", $m);

      if ($i > 0) {
        if ($user->{REDUCTION} > 0 && $Dv->{TP_INFO}->{REDUCTION_FEE}) {
          $sum = $Dv->{TP_INFO}->{MONTH_FEE} * (100 - $users->{REDUCTION}) / 100;
        }

        #$message = "$_MONTH_FEE: $sum ($Dv->{TP_INFO}->{ID})";
        $message = "Internet: $_MONTH_FEE_SHORT $Dv->{TP_INFO}->{NAME} ($Dv->{TP_INFO}->{ID})";

        if ($Dv->{ACCOUNT_ACTIVATE}) {
          $DATE = $Dv->{ACCOUNT_ACTIVATE};
          my $end_period = strftime "%Y-%m-%d", localtime((mktime(0, 0, 0, $active_d, ($m - 1), ($active_y - 1900), 0, 0, 0) + 30 * 86400));
          $message .= " ($DATE-$end_period)";

          $users->change(
            $Dv->{UID},
            {
              ACTIVATE => "$DATE",
              UID      => $Dv->{UID}
            }
          );

        }
        else {
          $DATE = "$active_y-$m-01";
          my $days_in_month = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($active_y % 400) || !($active_y % 4) && ($active_y % 25) ? 29 : 28));
          $message .= " ($DATE-$active_y-$m-$days_in_month)";
        }
      }
      elsif ($Dv->{ACCOUNT_ACTIVATE} && $Dv->{ACCOUNT_ACTIVATE} ne '0000-00-00') {
        if ($Dv->{TP_INFO}->{PERIOD_ALIGNMENT}) {
          $users->change(
            $Dv->{UID},
            {
              ACTIVATE => '0000-00-00',
              UID      => $Dv->{UID}
            }
          );
        }
        elsif ($Dv->{OLD_STATUS} == 5) {
          $users->change(
            $Dv->{UID},
            {
              ACTIVATE => "$DATE",
              UID      => $Dv->{UID}
            }
          );
        }
        else {
          $DATE = "$active_y-$m-$active_d";
        }
        my $end_period = strftime "%Y-%m-%d", localtime((mktime(0, 0, 0, $active_d, ($m - 1), ($active_y - 1900), 0, 0, 0) + 30 * 86400));
        $Dv->{ACCOUNT_ACTIVATE} = strftime "%Y-%m-%d", localtime((mktime(0, 0, 0, $active_d, ($m - 1), ($active_y - 1900), 0, 0, 0) + 31 * 86400));
        $message .= " ($active_y-$m-$active_d-$end_period)";
      }
      else {
        my $days_in_month = ($m != 2 ? (($m % 2) ^ ($m > 7)) + 30 : (!($active_y % 400) || !($active_y % 4) && ($active_y % 25) ? 29 : 28));
        my $start_date = ($Dv->{TP_INFO}->{PERIOD_ALIGNMENT}) ? (($Dv->{ACCOUNT_ACTIVATE} && $Dv->{ACCOUNT_ACTIVATE} ne '0000-00-00') ? $Dv->{ACCOUNT_ACTIVATE} : $DATE) : "$y-$m-01";
        $message .= " ($start_date-$y-$m-$days_in_month)";
      }

      $TIME = "00:00:00";
      if ($conf{EXT_BILL_ACCOUNT}) {
        if ($user->{EXT_BILL_DEPOSIT} < $sum && $user->{MAIN_BILL_ID}) {
          $sum = $sum - $user->{EXT_BILL_DEPOSIT};
          $fees->take(
            $users,
            $user->{EXT_BILL_DEPOSIT},
            {
              DESCRIBE => $message,
              METHOD   => ($Dv->{TP_INFO}->{FEES_METHOD}) ? $Dv->{TP_INFO}->{FEES_METHOD} : 1,
              DATE     => "$DATE $TIME"
            }
          );
          $user->{BILL_ID}      = $user->{MAIN_BILL_ID};
          $user->{MAIN_BILL_ID} = undef;
        }
      }

      if ($sum > 0) {
        $fees->take(
          $users, $sum,
          {
            DESCRIBE => $message,
            METHOD   => ($Dv->{TP_INFO}->{FEES_METHOD}) ? $Dv->{TP_INFO}->{FEES_METHOD} : 1,
            DATE     => "$DATE $TIME"
          }
        );

        $total_sum{MONTH_FEE} += $sum;
        if ($fees->{errno}) {
          $html->message('err', $_ERROR, "[$fees->{errno}] $fees->{errstr}") if (!$attr->{QUITE});
        }
        else {
          $html->message('info', $_INFO, $message) if ($html && !$attr->{QUITE});
        }
      }

      $m++;
    }
  }

  return \%total_sum;
}

#**********************************************************
# Add discovery mac to Dhcphosts
#**********************************************************
sub dv_dhcp_get_mac_add {
  my ($ip, $DHCP_INFO, $attr) = @_;

  use Dhcphosts;
  my $Dhcphosts = Dhcphosts->new($db, $admin, \%conf);
  my @dhcp_nets = split(/;/, $conf{DV_IP_DISCOVERY});
  my $default_params = "IP,MAC";

  foreach my $nets (@dhcp_nets) {
    my %PARAMS_HASH = ();

    my ($id, $net, $params) = split(/:/, $nets);
    $params = $default_params if (!$params);
    my @params_arr = split(/,/, $params);

    foreach my $param (@params_arr) {
      $PARAMS_HASH{$param} = $DHCP_INFO->{$param};
    }

    my $start_ip = '0.0.0.0';
    my $bit_mask = 0;
    ($start_ip, $bit_mask) = split(/\//, $net) if ($net);
    my $mask = 0b0000000000000000000000000000001;
    my $address_count = sprintf("%d", $mask << (32 - $bit_mask));

    if (ip2int($ip) >= ip2int($start_ip) && ip2int($ip) <= ip2int($start_ip) + $address_count) {
      my $list = $Dhcphosts->hosts_list(
        {
          NETWORK   => $id,
          SORT      => 3,
          DESC      => 'DESC',
          PAGE_ROWS => 1,

          #%PARAMS_HASH
        }
      );

      #make Discovery
      if ($Dhcphosts->{errno}) {
        $html->message('err', $_ACTIVATE, "$_ERROR DHCP get ip error", { ID => 116 });
        return 0;
      }
      elsif ($Dhcphosts->{TOTAL} < 1) {

        $Dhcphosts->network_info($id);
        if ($Dhcphosts->{TOTAL} < 0) {
          $html->message('err', $_ACTIVATE, "$_ERROR Can't find your network '$id' ", { ID => 117 });
          return 0;
        }

        $PARAMS_HASH{IP} = int2ip(ip2int($Dhcphosts->{NETWORK}) + 1) if (defined($PARAMS_HASH{IP}));
      }
      else {
        $PARAMS_HASH{IP} = int2ip($list->[0]->[2] + 1) if (defined($PARAMS_HASH{IP}));
      }

      $Dhcphosts->host_add(
        {
          NETWORK  => $id,
          HOSTNAME => "$user->{LOGIN}_$id",
          UID      => $user->{UID},
          %PARAMS_HASH
        }
      );

      if ($Dhcphosts->{errno}) {
        if ($Dhcphosts->{errno} == 7) {
          $html->message('err', $_ERROR . ' ' . $_ACTIVATE, $html->b("$ERR_HOST_REGISTRED") . "\n $_RENEW_IP \n \n MAC: '$DHCP_INFO->{MAC}' \n IP: '$DHCP_INFO->{IP}' \n HOST: '$user->{LOGIN}_$id'", { ID => 118 });
        }
        else {
          $html->message('err', $_ACTIVATE, "$_ERROR: DHCP add hosts error", { ID => 119 });
        }
      }
      else {
        require "Abills/modules/Dhcphosts/webinterface";
        dhcphosts_config(
          {
            NETWORKS => $id,
            reconfig => 1,
            QUITE    => 1,
            %PARAMS_HASH
          }
        );
        $Dv->{NEW_IP} = $PARAMS_HASH->{IP};
        return 1;
      }

      return 0;
    }
  }

  $html->message('err', $_ACTIVATE, "$_ERROR: Can't find assign network IP: '$ip' ", { ID => 120 });
  return 0;
}

#**********************************************************
# Get MAC from hcl leaseds
#**********************************************************
sub dv_dhcp_get_mac {
  my ($ip, $attr) = @_;

  use Dhcphosts;
  my $Dhcphosts = Dhcphosts->new($db, $admin, \%conf);

  $Dhcphosts->host_info(0, { IP => $ip });
  my $MAC    = '';
  my %PARAMS = ();

  if ($Dhcphosts->{TOTAL} > 0) {
    %PARAMS = (
      IP     => $Dhcphosts->{IP},
      MAC    => $Dhcphosts->{MAC},
      NAS_ID => $Dhcphosts->{NAS_ID},
      PORTS  => $Dhcphosts->{PORTS},
      VLAN   => $Dhcphosts->{VLAN}
    );

    if ($attr->{CHECK_STATIC}) {
      $PARAMS{STATIC} = 1;
    }
    if ($PARAMS{MAC} ne '00:00:00:00:00:00') {
      return \%PARAMS;
    }
  }

  #Get mac from DB
  if ($conf{DHCPHOSTS_LEASES} eq 'db') {
    my $list = $Dhcphosts->leases_list({ IP => $ip, STATE => 2 });

    if ($Dhcphosts->{TOTAL} > 0) {
      %PARAMS = (
        IP     => $list->[0]->[1],
        MAC    => $list->[0]->[3],
        NAS_ID => $list->[0]->[11],
        PORTS  => $list->[0]->[12],
        VLAN   => $list->[0]->[13],
      );
    }
    return \%PARAMS;
  }

  #Get mac from leases file
  else {
    my $logfile = $conf{DHCPHOSTS_LEASES} || '/var/db/dhcpd/dhcpd.leases';
    my %list    = ();
    my $l_ip    = '';

    open(FILE, $logfile) or $html->message('err', $_ERROR, "Can't read file '$logfile' $!");
    while (<FILE>) {
      next if /^#|^$/;

      if (/^lease (\d+\.\d+\.\d+\.\d+)/) {
        $l_ip = $1;
        $list{$ip}{ip} = sprintf("%-17s", $ip);
      }
      elsif (/^\s*hardware ethernet (.*);/) {
        my $mac = $1;
        if ($ip eq $l_ip) {
          $list{$ip}{hardware} = sprintf("%s", $mac);
          return $list{$ip}{hardware} if ($list{$ip}{active});
        }
      }
      elsif (/^\s+binding state active/) {
        $list{$ip}{active} = 1;
      }
    }
    close FILE;
  }

  $PARAMS{MAC} = ($list{$ip}{hardware}) ? $list{$ip}{hardware} : '';

  return \%PARAMS;
}

#**********************************************************
#
#**********************************************************
sub dv_compensation () {

  if ($FORM{add}) {
    my ($FROM_Y, $FROM_M, $FROM_D) = split(/-/, $FORM{FROM_DATE}, 3);
    my $from_date = mktime(0, 0, 0, $FROM_D, ($FROM_M - 1), ($FROM_Y - 1900), 0, 0, 0);

    ($TO_Y, $TO_M, $TO_D) = split(/-/, $FORM{TO_DATE}, 3);

    my $to_date = mktime(0, 0, 0, $TO_D, ($TO_M - 1), ($TO_Y - 1900), 0, 0, 0);
    my $sum     = 0.00;
    my $days    = 0;
    $days_in_month = 31;

    $Dv->info($FORM{UID});

    my $table = $html->table(
      {
        width       => '400',
        caption     => "$_COMPENSATION $_FROM: $FORM{FROM_DATE} $_TO: $FORM{TO_DATE}",
        border      => 1,
        title_plain => [ "$_MONTH", "$_DAYS", "$_SUM" ],
        cols_align  => [ 'right', 'right', 'right', ],
        ID          => 'DV_COMPENSATION_DESCRIBE'
      }
    );

    if ($users->{ACTIVATE} ne '0000-00-00') {
      my $from_seltime = POSIX::mktime(0, 0, 0, $FROM_D, ($FROM_M - 1), ($FROM_Y - 1900));
      my $to_seltime   = POSIX::mktime(0, 0, 0, $TO_D,   ($TO_M - 1),   ($TO_Y - 1900));
      $days = int(($to_seltime - $from_seltime) / 86400);
      $sum = $days * ($Dv->{MONTH_ABON} / 30);
    }
    else {
      if ("$FROM_Y-$FROM_M" eq "$TO_Y-$TO_M") {
        $days          = $TO_D - $FROM_D;
        $days_in_month = ($FROM_M != 2 ? (($FROM_M % 2) ^ ($FROM_M > 7)) + 30 : (!($FROM_Y % 400) || !($FROM_Y % 4) && ($FROM_Y % 25) ? 29 : 28));
        $sum           = sprintf("%.2f", $days * $Dv->{DAY_ABON} + $days * ($Dv->{MONTH_ABON} / $days_in_month));

        $table->addrow("$FROM_Y-$FROM_M", $days, $sum);
      }
      elsif ("$FROM_Y-$FROM_M" ne "$TO_Y-$TO_M") {
        $FROM_D--;
        do {
          $days_in_month = ($FROM_M != 2 ? (($FROM_M % 2) ^ ($FROM_M > 7)) + 30 : (!($FROM_Y % 400) || !($FROM_Y % 4) && ($FROM_Y % 25) ? 29 : 28));
          my $month_days = ($FROM_M == $TO_M) ? $TO_D : $days_in_month - $FROM_D;
          $FROM_D = 0;
          my $month_sum = sprintf("%.2f", $month_days * $Dv->{DAY_ABON} + $month_days * ($Dv->{MONTH_ABON} / $days_in_month));
          $sum  += $month_sum;
          $days += $month_days;
          $table->addrow("$FROM_Y-$FROM_M", $month_days, $month_sum);

          if ($FROM_M < 12) {
            $FROM_M = sprintf("%02d", $FROM_M + 1);
          }
          else {
            $FROM_M = sprintf("%02d", 1);
            $FROM_Y += 1;
          }
        } while (($FROM_Y < $TO_Y) || ($FROM_M <= $TO_M && $FROM_Y == $TO_Y));
      }
    }

    if ($users->{REDUCTION}) {
      $sum = $sum - (($sum / 100) *	$users->{REDUCTION});
    }

    $table->{color} = $_COLORS[3];

    $table->addrow($html->b("$_TOTAL:"), $html->b("$days"), $html->b("$sum"));
    $payments->add(
      {
        BILL_ID => $users->{BILL_ID},
        UID     => $users->{UID}
      },

      {
        SUM            => $sum,
        METHOD         => 6,
        DESCRIBE       => "$_COMPENSATION. $_DAYS: $FORM{FROM_DATE}/$FORM{TO_DATE} ($days)" . (($FORM{DESCRIBE}) ? ". $FORM{DESCRIBE}" : ''),
        INNER_DESCRIBE => $FORM{INNER_DESCRIBE}
      }
    );

    if ($fees->{errno}) {
      $html->message('err', $_ERROR, "$_ERROR: [$fees->{errno}] $fees->{errstr} ");
    }
    else {
      $html->message('info', "$_COMPENSATION", "$_COMPENSATION $_SUM: $sum");
      print $table->show();
    }
  }

  $Dv->{FROM_DATE} = $html->date_fld2('FROM_DATE', { MONTHES => \@MONTHES, FORM_NAME => 'compensation', WEEK_DAYS => \@WEEKDAYS });
  $Dv->{TO_DATE}   = $html->date_fld2('TO_DATE',   { MONTHES => \@MONTHES, FORM_NAME => 'compensation', WEEK_DAYS => \@WEEKDAYS });

  $html->tpl_show(_include('dv_compensation', 'Dv'), $Dv);
}

#**********************************************************
# Shedule form for Dv modules
#**********************************************************
sub dv_form_shedule () {

  my $Shedule = Shedule->new($db, $admin, \%conf);

  if ($FORM{add}) {
    my ($Y, $M, $D) = split(/-/, $FORM{DATE}, 3);

    $Shedule->add(
      {
        UID    => $FORM{UID},
        TYPE   => "$FORM{Shedule}",
        ACTION => $FORM{ACTION},
        D      => $D,
        M      => $M,
        Y      => $Y,
        MODULE => 'Dv'
      }
    );

    if ($Shedule->{errno}) {
      $html->message('err', $_ERROR, "[$Shedule->{errno}] $err_strs{$Shedule->{errno}}");
    }
    else {
      $html->message('info', $_CHANGED, "$_SHEDULE $_ADDED");
    }
  }
  elsif ($FORM{Shedule}) {
    if ($FORM{Shedule} eq 'status') {
      my $table = $html->table(
        {
          width    => '100%',
          rowcolor => 'row_active',
          rows     => [
            [
              "$_FROM: ",
              $html->date_fld2('DATE', { MONTHES => \@MONTHES, FORM_NAME => 'Shedule', WEEK_DAYS => \@WEEKDAYS }),
              "$_STATUS: ",
              $html->form_select(
                'ACTION',
                {
                  SELECTED => $FORM{ACTION},
                  SEL_HASH => {
                    0 => $service_status[0],
                    1 => $service_status[1],
                    2 => $service_status[2],
                    3 => $service_status[3]
                  },
                  NO_ID => 1
                }
              ),
              $html->form_input('add', $_ADD, { TYPE => 'submit' })
            ]
          ],
        }
      );

      print $html->form_main(
        {
          CONTENT => $table->show({ OUTPUT2RETURN => 1 }),
          HIDDEN  => {
            sid     => "$sid",
            index   => "$index",
            Shedule => "status",
            UID     => "$FORM{UID}",
          },
          NAME => 'Shedule'
        }
      );
    }

  }
  elsif ($FORM{del} && $FORM{is_js_confirmed}) {
    $Shedule->del({ ID => $FORM{del} });
    if ($Shedule->{errno}) {
      $html->message('err', $_ERROR, "[$Shedule->{errno}] $err_strs{$Shedule->{errno}}");
    }
    else {
      $html->message('info', $_DELETED, "$_DELETED [$FORM{del}]");
    }
  }

  my $list = $Shedule->list(
    {
      UID    => $FORM{UID},
      MODULE => 'Dv'
    }
  );

  my $table = $html->table(
    {
      width      => '100%',
      border     => 1,
      title      => [ "$_HOURS", "$_DAY", "$_MONTH", "$_YEAR", "$_COUNT", "$_USER", "$_TYPE", "$_VALUE", "$_MODULES", "$_ADMINS", "$_CREATED", "-" ],
      cols_align => [ 'right', 'right', 'right', 'right', 'right', 'left', 'right', 'right', 'right', 'left', 'right', 'center' ],
      qs         => $pages_qs,
      pages      => $Shedule->{TOTAL},
      ID         => 'DV_SHEDULE'
    }
  );

  foreach my $line (@$list) {
    my $delete = ($permissions{0}{4}) ? $html->button($_DEL, "index=$index&del=$line->[14]&UID=$line->[13]", { MESSAGE => "$_DEL [$line->[13]]?", CLASS => 'del', TEXT => $_DEL }) : '-';

    $table->addrow(
      $html->b($line->[0]),
      $line->[1], $line->[2], $line->[3], $line->[4], $html->button($line->[5], "index=15&UID=$line->[13]"),
      "$line->[6]", ($line->[6] eq 'status') ? $html->color_mark($service_status[ $line->[7] ], $service_status_colors[ $line->[7] ]) : $line->[7],
      "$line->[8]", "$line->[9]", "$line->[10]", $delete
    );
  }

  print $table->show();

  $table = $html->table(
    {
      width      => '100%',
      cols_align => [ 'right', 'right', 'right', 'right' ],
      rows => [ [ "$_TOTAL:", $html->b($Shedule->{TOTAL}) ] ]
    }
  );
  print $table->show();
}

#**********************************************************
#
#**********************************************************
sub dv_traffic_classes {
  my ($attr) = @_;

  $tariffs->{ACTION}     = 'add';
  $tariffs->{LNG_ACTION} = $_ADD;

  if ($FORM{add}) {
    $tariffs->traffic_class_add({%FORM});
    if (!$tariffs->{errno}) {
      $html->message('info', $_INFO, "$_ADDED");
    }
  }
  elsif ($FORM{change}) {
    $tariffs->traffic_class_change({ %FORM, CHANGED => "$DATE $TIME" });

    if (!$tariffs->{errno}) {
      $html->message('info', $_INFO, "$_CHANGED");
    }
  }
  elsif ($FORM{chg}) {
    $tariffs->traffic_class_info($FORM{chg});
    $tariffs->{ACTION}     = 'change';
    $tariffs->{LNG_ACTION} = $_CHANGE;
    if (!$tariffs->{errno}) {
      $html->message('info', $_INFO, "$_CHANGED");
    }
  }
  elsif ($FORM{del} && $FORM{is_js_confirmed}) {
    $tariffs->traffic_class_del({ ID => $FORM{del} });
    if (!$tariffs->{errno}) {
      $html->message('info', $_INFO, "$_DELETED");
    }
  }

  if ($tariffs->{errno}) {
    $html->message('err', $_ERROR, "[$tariffs->{errno}] $err_strs{$tariffs->{errno}}");
  }

  $html->tpl_show(_include('dv_traffic_class', 'Dv'), $tariffs);

  my $list  = $tariffs->traffic_class_list({%LIST_PARAMS});
  my $table = $html->table(
    {
      width   => '100%',
      caption => "$_TRAFFIC_CLASS",
      border  => 1,
      title   => [ '#', "$_NAME", 'NETS', "$_COMMENTS", "$_CHANGED", '-', '-' ],
      cols_align => [ 'right', 'left', 'left', 'center:noprint', 'center:noprint' ],
      qs         => $pages_qs,
      pages      => $Dv->{TOTAL},
      ID         => 'DV_TRAFFIC_CLASSES'
    }
  );

  my $br = $html->br();
  foreach my $line (@$list) {
    $line->[2] =~ s/\n/$br/g;
    $table->addrow("$line->[0]", "$line->[1]", "$line->[2]", "$line->[3]", "$line->[4]", $html->button("$_CHANGE", "index=$index&chg=$line->[0]", { CLASS => 'change' }), $html->button("$_DEL", "index=$index&del=$line->[0]", { MESSAGE => "$_DEL $line->[0]?", CLASS => 'del' }));
  }
  print $table->show();

  return 0;
}

#**********************************************************
#
#**********************************************************
sub dv_payments_maked {
  my ($attr) = @_;

  return '' if ($FORM{DISABLE});

  $Dv->info($attr->{USER_INFO}->{UID});

  my $deposit = $attr->{USER_INFO}->{DEPOSIT} + (($attr->{USER_INFO}->{CREDIT} > 0) ? $attr->{USER_INFO}->{CREDIT} : $Dv->{TP_CREDIT});

  my $abon_fees = ($attr->{USER_INFO}->{REDUCTION}) ? $Dv->{MONTH_ABON} + $Dv->{DAY_ABON} : ($Dv->{MONTH_ABON} + $Dv->{DAY_ABON}) * (100 - $attr->{USER_INFO}->{REDUCTION}) / 100;

  if($conf{DV_FULL_MONTH}) {
  	$abon_fees = ($attr->{USER_INFO}->{REDUCTION}) ? $Dv->{MONTH_ABON} + $Dv->{DAY_ABON}*30 : ($Dv->{MONTH_ABON} + $Dv->{DAY_ABON}*30) * (100 - $attr->{USER_INFO}->{REDUCTION}) / 100;
  }


  if ($Dv->{STATUS} > 3 && ($deposit > $abon_fees || (! $conf{DV_FULL_MONTH} && $Dv->{ABON_DISTRIBUTION}) )) {
    $Dv->change(
      {
        UID    => $attr->{USER_INFO}->{UID},
        STATUS => 0
      }
    );
    $Dv->{ACCOUNT_ACTIVATE} = $attr->{USER_INFO}->{ACTIVATE} || '0000-00-00';
    dv_get_month_fee($Dv, $attr);
  }
}

#**********************************************************
# Pay to function
#**********************************************************
sub dv_pay_to {
  my ($attr) = @_;

  my $Dv = $attr->{Dv};

  if ($FORM{DATE}) {
    my ($from_year, $from_month, $from_day) = split(/-/, $DATE,       3);
    my ($to_year,   $to_month,   $to_day)   = split(/-/, $FORM{DATE}, 3);
    $Dv->{ACTION_LNG} = "$_PAYMENTS";
    $Dv->{DATE}       = "$DATE - $FORM{DATE}";
    $Dv->{SUM}        = 0.00;
    $Dv->{DAYS}       = 0;

    if ($Dv->{MONTH_ABON} && $Dv->{ABON_DISTRIBUTION} || $Dv->{DAY_ABON}) {
      if ($from_year . '-' . $from_month eq $to_year . '-' . $to_month) {
        $Dv->{DAYS} = $to_day - $from_day;
        my $days_in_month = ($FROM_M != 2 ? (($FROM_M % 2) ^ ($FROM_M > 7)) + 30 : (!($FROM_Y % 400) || !($FROM_Y % 4) && ($FROM_Y % 25) ? 29 : 28));
        $Dv->{SUM} = sprintf("%.2f", $Dv->{DAYS} * $Dv->{DAY_ABON} + $Dv->{DAYS} * ($Dv->{MONTH_ABON} / $days_in_month));
      }
      elsif ("$from_year-$from_month" ne "$to_year-$to_month") {
        $from_day--;
        do {
          $days_in_month = ($from_month != 2 ? (($from_month % 2) ^ ($from_month > 7)) + 30 : (!($from_year % 400) || !($from_year % 4) && ($from_year % 25) ? 29 : 28));
          my $month_days = ($from_month == $to_month) ? $to_day : $days_in_month - $from_day;
          $from_day = 0;
          my $month_sum = sprintf("%.2f", $month_days * $Dv->{DAY_ABON} + $month_days * ($Dv->{MONTH_ABON} / $days_in_month));
          $Dv->{SUM}  += $month_sum;
          $Dv->{DAYS} += $month_days;
          if ($from_month < 12) {
            $from_month = sprintf("%02d", $from_month + 1);
          }
          else {
            $from_month = sprintf("%02d", 1);
            $from_year += 1;
          }

          #} while(($from_year < $to_year) || ($from_month <= $to_month && $from_month == $to_month));
        } while (($from_year < $to_year) || ($from_month <= $to_month));
      }
    }
    elsif ($Dv->{MONTH_ABON}) {
      $Dv->{SUM} = $Dv->{MONTH_ABON};
    }
    else {
      $Dv->{SUM} = 0;
    }
    $index = 2;
  }
  else {
    $Dv->{ACTION_LNG} = "$_RECALCULATE";
    $Dv->{DATE} = $html->date_fld2('DATE', { MONTHES => \@MONTHES, FORM_NAME => 'pay_to', WEEK_DAYS => \@WEEKDAYS });
  }

  $html->tpl_show(_include('dv_pay_to', 'Dv'), $Dv);
}

#**********************************************************
# get services for invoice
#**********************************************************
sub dv_docs {
  my ($attr) = @_;

  my $uid = $attr->{UID} || $FORM{UID};
  my @services = ();
  $Dv->info($uid);
  
  if ($Dv->{TOTAL}==0 || ! $Dv->{DAY_ABON} || $Dv->{STATUS}) {
  	return \@services;
  }
  
  if ($Dv->{MONTH_ABON} > 0) {
    push @services, "Internet: $_MONTH_FEE_SHORT $Dv->{TP_NAME} ($Dv->{TP_ID})||$Dv->{MONTH_ABON}";
    #"$_MONTH_FEE: ($Dv->{TP_ID})||$Dv->{MONTH_ABON}";
  }

  if ($Dv->{DAY_ABON} > 0) {
    my ($Y, $M, $D) = split(/-/, $DATE);
    if ($M < 12) {
      $M = sprintf("%02d", $M + 1);
    }
    else {
      $M = sprintf("%02d", 1);
      $Y++;
    }


    my $days_in_month = ($M != 2 ? (($M % 2) ^ ($M > 7)) + 30 : (!($Y % 400) || !($Y % 4) && ($Y % 25) ? 29 : 28));

    push @services, "Internet: $_DAY_FEE_SHORT: $Dv->{TP_NAME} ($Dv->{TP_ID})|$days_in_month $_DAY|" . sprintf("%.2f", ($Dv->{DAY_ABON} * $days_in_month));
  }

  return \@services;
}


#**********************************************************
#
#**********************************************************
sub dv_report_debetors {
	my ($attr)=@_;
	
	my $list = $Dv->report_debetors({ %LIST_PARAMS });
	
my $table = $html->table(
  {
    caption     => "$_DEBETORS",
    width       => '100%',
    title       => [ "$_LOGIN", "$_FIO", "$_PHONE", "$_TARIF_PLAN", "$_DEPOSIT", "$_CREDIT", "$_STATUS" ],
    cols_align  => [ 'left', 'right', 'right', 'right', 'right', 'right' ],
    pages       => $Dv->{TOTAL},
    rowcolor    => 'odd',
    ID          => 'DEBETORS'
  }
);

foreach my $line (@$list) {
  $table->addrow($html->button($line->[0], "index=11&UID=$line->[7]"), 
   $line->[1], 
   $line->[2], 
   $line->[3], 
   $line->[4], 
   $line->[5],
   $html->color_mark($service_status[$line->[6]], $service_status_colors[$line->[6]]));
}
	
print $table->show();


$table = $html->table(
  {
    width      => '100%',
    cols_align => [ 'right', 'right' ],
    rows       => [ [ "$_TOTAL:", $html->b($Dv->{TOTAL}) ] ]
  }
);

print $table->show();
}

1

