#!/usr/bin/perl

use strict;
use CGI;

use Opals::Context;

use POSIX qw(
    floor
);

use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_preference
);

use Opals::User qw(
    user_list
    user_getInformationById
    user_isUserBc
);

use Opals::Equipment qw(
    eq_defRecord_getList
    eq_defItem_getList
    eq_def_colDisplayCount
);

use Opals::Eq_Circulation qw(
    circ_getItemInfo
    circ_getItemStatus
    
    circ_getUserCircStatus
    circ_getUserListLoan
    circ_getUserListReserve
    circ_getUserLoanHistory

    circ_processLoan
    circ_processReturn
    circ_processRenew

    circ_fillHold
    circ_placeHold
    circ_cancelHold
    circ_cancelHold_all
    circ_isOnHold

    circ_fillReserve
    circ_placeReserve
    circ_cancelReserve
    circ_resetReserve

    circ_declareLost
    circ_setAvailable
    circ_record_ODL

);
use Opals::Eq_BarcodeMgmt qw(
    eq_bcm_validateBc
);

use Time::localtime;


use Date::Calc qw(
    Add_Delta_DHMS
);

use Opals::Date qw(

    date_time_text
    date_deltaWorkDay   
    date_parse
    date_getDeadLineDateTime
    date_getDeadLineDate

);

use Opals::Constant;

my $dbh = Opals::Context->dbh();
END { $dbh->disconnect(); }

my $cgi = CGI->new;
my $input = $cgi->Vars();
my ($permission, $cookie, $template) = tmpl_read(
    {
        dbh             => $dbh,
        cgi             => $cgi,
        tmplFile        => 'eqmnt/loan.tmpl',
        reqPermission   => 'eq_circ_loan',
    }
);

my @cookieList = (@$cookie);
my $syspref    = tmpl_preference($dbh);
my $validateBc       = $syspref->{'validateBarcode'};
my $barcodeType      = $syspref->{'barcodeType'};

open debug, ">/tmp/debugEQLoan";
print debug ( $cgi->cookie('eq_loan_bc') , "\n");

my @bcList_loan = split(",",$cgi->cookie('eq_loan_bc'));
print debug @bcList_loan , "\n";

my $tm = localtime;
my $todayStr = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $tm->year+1900, ($tm->mon)+1, $tm->mday, $tm->hour, $tm->min, $tm->sec);
my $tomorrowStr = sprintf("%04d-%02d-%02d", $tm->year+1900, ($tm->mon)+1, ($tm->mday)+1);
my $dateDue = $todayStr;
my $dateDueFormat_text;

my $uInput = $input->{'uInput'};
my($uid,$status,$loanOverrid) = getUID();
       if ($uid >= 0){
        push @cookieList, $cgi->cookie(
            -name   =>'borrower',
            -value  => $uid,
        );
        getUserInfo($dbh, $uid);
        my $op = $input->{'op'};
        if ($op eq ''){
            my $barcode = $input->{'bc'};
            $barcode    =~ s/^\s+|\s+$//g;
            $barcode = eq_bcm_validateBc($dbh, $barcode, $barcodeType) if ($validateBc eq '1');
            my $cmdCode = $input->{'cmdCode'};
            print debug "1 \n" ;
            if ($barcode ne '') {
                my $userCircStatus  = circ_getUserCircStatus($dbh, $uid, $barcode);
                my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$barcode, uid=>$uid}); 
                my $userMsgCode     = getMsgCode_user($userCircStatus);
                my $itemMsgCode     = getMsgCode_item($itemCircStatus,$uid);
                my $itemInfo        = circ_getItemInfo($dbh, $barcode,$uid);
                if ($itemCircStatus->{'status'} == IT_STAT_NOEXIST){
                    #check if enter userbarcode into item barcode input
                    my $isUId = user_isUserBc($dbh,$barcode);
                    if ($isUId){
                        $uid = $isUId;
                        goto L_USER;
                    }
                  
                     $template->param(msgCode=>1);
                     $template->param("msgItem_" . $itemMsgCode =>1); 
                     goto L_USER;
                }
                my $loanPeriod   = ($itemInfo->{'loanPeriod'})? $itemInfo->{'loanPeriod'}:0;
                my $loanUnit = ($itemInfo->{'loanUnit'})? $itemInfo->{'loanUnit'} : 'day';
                #get datedue
                my $loanDDType   = $input->{'loanDDType'};
                my ($lHour,$lDate,$lStandard)=(0,0,0);
                my $tmp_date = ($loanDDType eq "hour")? $input->{'hdateDue'} :$input->{'ddateDue'} ;
                my $lhourDue = ($loanDDType eq "hour")? $tmp_date:0;
                if ($tmp_date && $loanDDType && ($loanDDType eq "hour" || $loanDDType eq "day")){
                    $dateDue = formatStrDateDue($tmp_date, $loanDDType);   
                }
                else{
                    $dateDue = getItemDueDate($loanPeriod, $loanUnit , $todayStr ); 
                }
                chomp($dateDue);
                if ($loanDDType eq "hour"){
                    $lHour =1;
                }
                elsif ($loanDDType eq "day") {
                    $lDate =1;
                }
                else {
                    $lStandard =1;
                }
                $template->param(
                    ldateDue    =>substr($dateDue,0,10),
                    lhourDue    =>$lhourDue,
                    lHour       =>$lHour,
                    lDay        =>$lDate,
                    lStandard   =>$lStandard,
                );

                #if loan period is 0 day/hour
                if ($loanPeriod == 0 && (!$tmp_date || $tmp_date <= 0 || $tmp_date eq "" )){
                    $template->param(msgCode=>1);
                    $template->param("msgItem_02" =>1); 
                    if ($itemCircStatus->{'status'} != IT_STAT_NOEXIST && $itemInfo){
                        $template->param(
                            rname   =>  $itemInfo->{'rname'},
                            barcode =>  $barcode,
                            sfList  =>  $itemInfo->{'fields'},
                            barcode =>  $barcode,
                            uid     =>  $uid,
                        );
                    }
                    goto L_USER;
                }
                $dateDueFormat_text =  date_time_text($dateDue, 1, 'en' );
                $template->param(cmdCode =>$cmdCode);
                if ($itemCircStatus->{'status'} != IT_STAT_NOEXIST && $itemInfo){
                    $template->param(
                            rname   =>  $itemInfo->{'rname'},
                            barcode =>  $barcode,
                            sfList  =>  $itemInfo->{'fields'},
                            barcode =>  $barcode,
                            uid     =>  $uid,
                    );
                    my $type;
                    if (($itemMsgCode eq '05' || $itemMsgCode eq '08' || 
                        $itemMsgCode eq '12' || $itemMsgCode eq '16' || $itemMsgCode eq '17') 
                        && substr($userMsgCode, 0, 3 ) eq '100'){
                        my $processCode = processCmd($dbh, $uid, $barcode, $itemInfo, $itemCircStatus, $itemMsgCode, $dateDue, $type);
                        $template->param($processCode=>1);
                        $template->param(processRSCode=>1);
                    }
                    elsif($cmdCode && $cmdCode ne ''){
                        if ($cmdCode eq '11' || $cmdCode eq '15'){ #renewal
                            $dateDue = getDeadLineDate($itemInfo->{'renewalPeriod'},$todayStr);
                        }
                        my $processCode = processCmd($dbh, $uid, $barcode, $itemInfo, $itemCircStatus, $cmdCode, $dateDue, $type);
                        $template->param($processCode=>1);
                        $template->param(processRSCode=>1);
                    }
                    else {
                        my $maxLoanBit  = substr ( $userMsgCode, 2 ,1); 
                        my $overdueBit  = substr ( $userMsgCode, 1 ,1);
                        if ($maxLoanBit eq '1')     {
                            $template->param(msgCode=>$itemMsgCode . "-" . $userMsgCode); 
                            $template->param('msgItem_' . $itemMsgCode=>1);
                            $template->param(userMsgcode=>1);
                            $template->param('msgUser_' .$userMsgCode=>1);
                        }
                        elsif ($overdueBit eq '1') {
                            $template->param(msgCode=>$itemMsgCode . "-" . $userMsgCode); 
                            $template->param('msgItem_' . $itemMsgCode=>1);
                            $template->param(userMsgcode=>1);
                            $template->param('msgUser_' .$userMsgCode=>1);
                            my $processCode ;
                            $template->param($processCode=>1);
                            $template->param(processRSCode=>1);
                        }
                        else {
                            $template->param(msgCode=>$itemMsgCode . "-" . $userMsgCode); 
                            $template->param(msgCode=>1);
                            $template->param("msgItem_" . $itemMsgCode =>1); 
                        }
                    }
                }
            }
        }#end $op eq ''
        elsif ($op eq 'return'){
            print debug "return \n" ;
            my @returnList = split /,/,$input->{'itemList'};
            for (my $i = 0; $i<scalar(@returnList); $i++){
                my $retRS = processReturn($dbh, $uid, $returnList[$i]);
            }
        }
        elsif ($op eq 'renew'){
            print debug "renew \n" ;
            my $rndateDue = "";
            my $selDate = $input->{'renewDate'};
            my $tmp_date = ($selDate eq "hour")? $input->{'rhdateDue'} :$input->{'rddateDue'},0 ;
            my $rnhourDue = ($selDate eq "hour")? $tmp_date:0;
            if ($selDate eq "hour" || $selDate eq "day"){
                $rndateDue = formatStrDateDue($tmp_date, $selDate); 
            }
            my $renewError = processRenew($dbh, $uid, $input->{'itemList'}, $rndateDue,0);
            if (scalar(@$renewError)){
                if (${$renewError}[2]->{'renewable'}==0){
                    $template->param(   
                        renewalMaxError=>1,
                    );    
                }
                my ($rnHour,$rnDate,$rnStandard)=(0,0,0);

                if ($selDate eq "hour"){
                    $rnHour =1;
                }
                elsif ($selDate eq "day") {
                    $rnDate =1;
                }
                else {
                    $rnStandard =1;
                }
                $template->param(
                    renewalError    =>1, 
                    renewFailList   =>$renewError,
                    rndateDue       =>$rndateDue,
                    rndayDue        => substr($rndateDue,0,10),
                    rnhourDue       =>$rnhourDue, 
                    rnHour          =>$rnHour,
                    rnDay           =>$rnDate,
                    rnStandard      =>$rnStandard,
                );
            }
        }
        elsif ($op eq 'renew_od'){
            print debug "renew_od \n" ;
            my $rndateDue; 
            my $selDate = $input->{'renewDate'};
            #my $tmp_date = ($selDate eq "hour")? $input->{'rhdateDue'} :$input->{'rddateDue'};
            my $tmp_date  ;
            if ($selDate eq "hour"){
                $tmp_date = $input->{'rhdateDue'};
            }
            elsif($selDate eq "day"){
                $tmp_date = $input->{'rddateDue'};
            }
            else{
                $tmp_date = "";
            }
            my $rnhourDue = ($selDate eq "hour")? $tmp_date:0;
            if ($selDate eq "hour" || $selDate eq "day"){
                $rndateDue = formatStrDateDue($tmp_date, $selDate); 
            }
            else{
                $rndateDue = "";
            }
            my $renewError = processRenew($dbh, $uid, $input->{'itemList'}, $rndateDue,1);
            if (scalar(@$renewError)){
                if (${$renewError}[2]->{'renewable'} ==0){
                    $template->param(renewalMaxError=>1);    
                }
                my ($rnHour,$rnDate,$rnStandard)=(0,0,0);

                if ($selDate eq "hour"){
                    $rnHour =1;
                }
                elsif ($selDate eq "day") {
                    $rnDate =1;
                }
                else {
                    $rnStandard =1;
                }
                $template->param(
                    renewalError    =>1, 
                    renewFailList   =>\@$renewError,
                    rndateDue       =>$rndateDue,
                    rnHour          =>$rnHour,
                    rnDay           =>$rnDate,
                    rnStandard      =>$rnStandard,
                );
            }
        }
        elsif ($op eq 'lost'){
            print debug "lost \n" ;
            declareLost($dbh, $uid, $input->{'itemList'});
        }
        elsif ($op eq 'cancelReserve'){
            print debug "cancelReserve \n" ;
            for (my $i = 0; $i < $input->{'totalid'}; $i++){
                if ($input->{'idrsrv' .$i}){
                    circ_cancelReserve($dbh, $input->{'idrsrv' .$i});
                    circ_cancelHold_all($dbh, $input->{'idrsrv' .$i});
                }
            }
        }
        elsif ($op eq 'listLoan') {
            print debug "listLoan \n";
            my $listLoan = processListLoan($dbh, $uid, $input);
        }

L_USER:
        getUserInfo($dbh, $uid);
    }#if($uid>=0)
    
my $dateDueFormat = $dateDue;
$dateDueFormat =~ s/ / \/  /; 
close debug;
$template->param(   
    dateDue             => $dateDueFormat,
    dateDueFormat_text  => $dateDueFormat_text,
    );
tmpl_write($dbh, $cgi, \@cookieList, $template);

#############################################################33

sub getUID{
    my($uid, $status, $loanOverride)=(-1,0,'');
    if ($input->{'uInput'}){
        my @uList = user_list($dbh, $input->{'uInput'},undef);
        if (scalar(@uList) == 1){
            $uid    = $uList[0]->{'uid'};
            $status = $uList[0]->{'status'};
            if ($status == 1){
                $template->param(block => 0);
                @uList[0]->{'block'} = 0;
            }
            else{
                $template->param(block =>1);
            }
            $template->param(uPerson =>1);
        }
        elsif(scalar(@uList)>1){
            for(my $i=0; $i<scalar(@uList); $i++){
                @uList[$i]->{'block'} = @uList[$i]->{'status'}==1?0:1;
            }
            $template->param(uList => \@uList);
        }
        else {#patron not in system
            $template->param(userNotMatch=>1);
        }
        #$template->param(uList => \@uList);
    }
    elsif ($input->{'InputFromList'}){
        $uid = $input->{'InputFromList'};
        my ($uInfo,$ttt) = user_getInformationById($dbh, $uid);
        $status = $uInfo->{'status'};
    }
    else{
        if ($input->{'hiddenid'}){
            $uid    = $input->{'hiddenid'};
        }
        else{
            #$uid = $input->{'uid'};
            $uid = $cgi->cookie('borrower'); }
        my ($uInfo,$ttt) = user_getInformationById($dbh, $uid);
        $status = $uInfo->{'status'};
    }
    if ($uid && $uid >= 0){
        $template->param(hasUser=>1,);   }
    else{
        $template->param(noUser=>1, );    }

    return ($uid, $status,$loanOverride);
}#end sub

sub getUserInfo{
    my ($dbh, $uid) = @_;
    my ($userInfo, $guardian) = user_getInformationById($dbh, $uid);
    getLoanItemList($dbh, $template,$uid);
    getReservedItemList($dbh, $template, $uid);
    getToDoLoanItemList($dbh, $template, $uid);
    my $loanHistory    = circ_getUserLoanHistory($dbh, {uid=>$uid});
    
    my $balance = 0;
    $balance = floor($balance*100  + 0.50)/100;
    $balance = sprintf("%.2f",$balance);

    $template->param(
        user_uid        => $userInfo->{'uid'},
        user_barcode    => $userInfo->{'userbarcode'},
        user_username   => $userInfo->{'username'},
        user_firstname  => $userInfo->{'firstname'},
        user_lastname   => $userInfo->{'lastname'},
        homeroom        => $userInfo->{'homeroom'},
        teacher         => $userInfo->{'teacher'},
        grade           => $userInfo->{'grade'},
        notes           => $userInfo->{'notes'},
        hiddenid        => $userInfo->{'uid'},
        balance         => $balance,
        loanHistory     => $loanHistory,
    );
}

sub getToDoLoanItemList {

    my ($dbh, $template, $uid) = @_;
    my @list = ();
    foreach my $bc(@bcList_loan){
        push @list, {
            barcode => $bc,
        }
    }
    $template->param(
        list_to_loan        => \@list,
    );
}

sub getLoanItemList{
    my($dbh, $template, $uid) = @_;
    my $loanList    = circ_getUserListLoan($dbh, {uid=>$uid});
    my $nCols       = eq_def_colDisplayCount($dbh, {defType=>'item', showOnBrief=>1});
    my $count = 0;
    my $odCount = 0;
    foreach my $loan (@$loanList){
        if ($loan->{'overdue'} ) 
            {$odCount++;}
        $loan->{'number'} = $count++;
        if ($loan->{'dateDue'}){
            $loan->{'dateDueFormat'} = $loan->{'dateDue'};
            $loan->{'dateDueFormat'} =~ s/ / \/ /; 
            $loan->{'dateDueFormat_text'} = date_time_text ($loan->{'dateDue'}, 0, 'en');
            #$dateDueFormat =~ s/([\d]{4}-[\d]{2}-[\d]{2}) ([\d]{2}:[\d]{2}:[\d]{2})/$1 \/ $2/; 
        }
        if ($loan->{'dateLoan'}){
            $loan->{'dateLoanFormat'}  = $loan->{'dateLoan'};
            $loan->{'dateLoanFormat'}  =~ s/ / \/ /; 
            $loan->{'dateLoanFormat_text'} = date_time_text ($loan->{'dateLoan'},0, 'en');
        }
    }
    $template->param(
        loanList        => $loanList,
        ncolspan        => $nCols + 5,
        loanCount       => scalar(@$loanList),
        numOfOverdue    => $odCount,
    );
}

sub getReservedItemList{
    my ($dbh,$template,$uid) = @_;
    my $reserveList = circ_getUserListReserve($dbh,$uid);
    my $order = 0;
    foreach my $r (@$reserveList){
        $r->{'order'} = $order++;
        if ($r->{'dateReserve'}){
            $r->{'dateReserveFormat'} = $r->{'dateReserve'};
            $r->{'dateReserveFormat'}  =~ s/ / \/ /; 
            $r->{'dateReserveFormat_text'} = date_time_text($r->{'dateReserve'}, 0, 'en' );
        }
        if ($r->{'dateExpiry'}){
            $r->{'dateExpiryFormat'} = $r->{'dateExpiry'};
            $r->{'dateExpiryFormat'}  =~ s/ / \/ /; 
            $r->{'dateExpiryFormat_text'} = date_time_text($r->{'dateExpiry'}, 0, 'en' );
        }
        if ($r->{'holdExpiry'}){
            $r->{'holdExpiryFormat'} = $r->{'holdExpiry'};
            $r->{'holdExpiryFormat'}  =~ s/ / \/ /; 
            $r->{'holdExpiryFormat_text'} = date_time_text($r->{'holdExpiry'}, 0, 'en' );
        }
    }
    $template->param(
        reserveList     =>  \@$reserveList,
        numOfReserves   =>  scalar(@$reserveList),
    );
}

sub getMsgCode_item{
    my ($itemCircStatus, $uid) = @_;
    my $retCode='';
    my $reserveList = $itemCircStatus->{'reserveList'};
    my $holdList    = $itemCircStatus->{'holdList'};
    if ($itemCircStatus->{'status'} == IT_STAT_NOEXIST) {
        $retCode = "00";    }
    elsif ($itemCircStatus->{'status'} ==IT_STAT_UNAVAIL){
        $retCode = "01";    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_RESTRICTED){
        $retCode = "02";    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_LOST){
        $retCode = "03";    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_MISSING){
        $retCode = "18";    }
    elsif( $itemCircStatus->{'status'} == IT_STAT_DAMAGED){
        $retCode = "04";    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_ONHOLD){
        if (getReserveId($uid, $holdList) > 0){
            $retCode = "05";    }
        elsif(getReserveId($uid, $reserveList) > 0){
            $retCode = "06";    }
        else{
            $retCode = "07";    }
    }
    elsif($itemCircStatus->{'status'} == IT_STAT_HAVE_RSVR){
        if (scalar(@$reserveList)){
            my $topReserveUID = @$reserveList[0]->{'uid'};
            if ($itemCircStatus->{'inLibrary'}){
                if ($uid == $topReserveUID){
                    $retCode = "08";    }
                elsif (getReserseId($uid, $reserveList)> 0){
                    $retCode = "09";    }
                else{
                    $retCode = "10";    }
            }
            else{
                if ($uid == $itemCircStatus->{'l_uid'}){
                    $retCode = "11";    }
                elsif($uid == $topReserveUID){
                    $retCode = "12";    }
                elsif(getReserveId($uid,$reserveList)>0){
                    $retCode = "13";    }
                else{
                    $retCode = "14";    }
           }
        }
    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_ONLOAN && $uid eq $itemCircStatus->{'l_uid'}) {
        $retCode = "15";}
    elsif( $itemCircStatus->{'status'} == IT_STAT_ONLOAN && $uid ne $itemCircStatus->{'l_uid'}){
        $retCode = "16";}
    else{
        $retCode = "17";}
    return $retCode;
}

sub getReserveId{
    my ($uid, $list)=@_;
    if (!$list){
        return 0;
    }
    foreach my $id(@$list){
        if ($id->{'uid'} == $uid){
            return $id->{'idReserve'};
        }
    }
    return 0;
}

sub getLastReserveId{
    my($list) = @_;
    if (!$list){
        return 0;
    }
    my $i = scalar(@$list) - 1;
    return @$list[$i]->{'idReserve'};
}

sub getMsgCode_user{
    my ($userStatus)=@_;
    return $userStatus->{'status'}.$userStatus->{'overdue'}.$userStatus->{'maxLoan'}.$userStatus->{'maxRenew'}.$userStatus->{'maxReserve'};
}

sub processCmd{

    my ($dbh, $uid, $barcode, $itemInfo, $itemCircStatus, $cmdCode, $dateDue, $type) = @_;
    my $dateReturn = $todayStr;
    my $retVal;
    if ($cmdCode eq '03'){
        circ_setAvailable($dbh, $barcode, IT_STAT_LOST);
    }
    if ($cmdCode eq '18'){
        circ_setAvailable($dbh, $barcode, IT_STAT_MISSING);
    }
    elsif ($cmdCode eq '04'){
        circ_setAvailable($dbh, $barcode, IT_STAT_DAMAGED);
    }
    elsif($cmdCode eq '05'){
        my $idReserve = getReserveId($uid, $itemCircStatus->{'holdList'});
        my $fillHold  = circ_fillHold($dbh, $idReserve, $barcode);
    }
    elsif ($cmdCode eq '06'){
        my $idReserve       = getReserveId($uid, $itemCircStatus->{'reserveList'});
        my $fillReserve     = circ_fillReserve($dbh, $uid, $itemCircStatus->{'rid'});
        my $idReserve       = getLastReserveId($itemCircStatus->{'holdList'});
        my $cancelHold      = circ_cancelHold($dbh, $idReserve);
        my $resetReserve    = circ_resetReserve($dbh, $idReserve);
    }
    elsif($cmdCode eq '07'){
        my $idReserve   = getLastReserveId($itemCircStatus->{'holdList'});
        my $cancelHold  = circ_cancelHold($dbh, $idReserve);
        my $resetReserve = circ_resetReserve($dbh, $idReserve);
    }
    elsif($cmdCode eq '07_R'){
        my $dateExpiry      = getDeadLineDate($itemInfo->{'reservePeriod'}, $todayStr);
        my $placeReserve    = circ_placeReserve($dbh, $uid, $itemCircStatus->{'rid'}, 1,$todayStr, $dateExpiry);
        $retVal = 'p1_07_R';
        return $retVal;
    }
    elsif($cmdCode eq '08' || $cmdCode eq '09'){
        my $fillReserve = circ_fillReserve($dbh, $uid,$itemCircStatus->{'rid'});
    }
    elsif($cmdCode eq '09_H'){
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_09_H";
        return $retVal;
     }
    elsif($cmdCode eq '10_H'){
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_10_H";
        return $retVal;
    }
    elsif($cmdCode eq '10_HR'){
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
           $dateExpiry   = getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        my $putReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal =  "p1_10_HR";
        return $retVal;
    }
    elsif ($cmdCode eq '11' || $cmdCode eq '15'){
        my $renew = circ_processRenew($dbh, {uid=>$uid, barcode=>$barcode, rnDate=>$dateDue});
        return $retVal = "p" . $renew . "_" .$cmdCode;
    }
    elsif($cmdCode eq '11_H' ){
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_11_H";
        return $retVal ;
    }
    elsif($cmdCode eq '12' || $cmdCode eq '13'){
        my $return      = doReturn($dbh, $itemCircStatus->{'l_uid'}, $barcode, $dateReturn);
        my $fillReserve = circ_fillReserve($dbh, $uid, $itemCircStatus->{'rid'});
    }
    elsif($cmdCode eq '13_H'){
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_13_H";
        return  $retVal;
    }
    elsif ($cmdCode eq '14' || $cmdCode eq '16'){
        my $return  = doReturn($dbh, $itemCircStatus->{'l_uid'}, $barcode, $dateReturn);
    }
    elsif($cmdCode eq '14_H'){
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_14_H";
        return $retVal;
    }
    elsif($cmdCode eq '14_HR'){
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
           $dateExpiry   = getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        my $putReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal =  "p1_14_HR";
        return $retVal;
    }
    my $idReserve =getReserveId($uid,$itemCircStatus->{'holdList'});
    if($idReserve && ($cmdCode eq '16' || $cmdCode eq 17)){
        my $fillHold  = circ_fillHold($dbh,$idReserve,$barcode);
    }
    my $loan = circ_processLoan($dbh, {uid=>$uid,barcode=>$barcode, dateLoan=>$todayStr, dateDue=>$dateDue});
    $retVal = "p" .$loan ."_" .$cmdCode;
    return $retVal;
}

sub doReturn{
    my ($dbh, $uid,$barcode,$dateReturn)= @_;
    my $sth = $dbh->prepare("select id as idLoan, dateDue from eq_loan where uid=? && barcode =? && dateReturn is null");
    $sth->execute($uid,$barcode);
    my $rec = $sth->fetchrow_hashref;
    my ($idLoan,$dateDue) = ($rec->{'idLoan'}, date_parse($rec->{'dateDue'}));
    my $dateRet = date_parse($dateReturn);
    my $odCount = date_deltaWorkDay($dateDue,$dateRet) ? date_deltaWorkDay($dateDue,$dateRet) : 0 ;
    my $odl_id = 0;
    if ($odCount > 0) {
        $odl_id = circ_record_ODL($dbh,$idLoan,'overdue',$odCount);
    }
    $sth->finish;
    return circ_processReturn($dbh, {uid=>$uid, barcode=>$barcode , dateReturn=>$dateReturn});
}

sub processReturn{
    my ($dbh, $uid, $barcode) = @_;
    my $retVal;
    my $itemInfo = circ_getItemInfo($dbh, $barcode);
    $retVal->{'itemInfo'} = $itemInfo;
    my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$barcode});
    if ($itemCircStatus->{'status'} == IT_STAT_ONLOAN || $itemCircStatus->{'status'} == IT_STAT_HAVE_RSVR){
        my $return = doReturn($dbh, $uid, $barcode, $todayStr);
        my $reserveList = $itemCircStatus->{'reserveList'};
        $retVal->{'uid'} = $itemCircStatus->{'l_uid'};
        #check if current item is on reserve
        if ($reserveList && scalar(@$reserveList) > 0){
            my $idReserve   = @$reserveList[0]->{'idReserve'};
            my $uidReserve  = @$reserveList[0]->{'uid'};
            my ($reserveUser, $guardien) = user_getInformationById($dbh, $uidReserve);
            $itemInfo   = circ_getItemInfo($dbh, $barcode, $uidReserve);
            my $reserveExpiry  = @$reserveList[0]->{'dateExpiry'};
            my $dateExpiry      = getDeadLineDate($itemInfo->{'holdPeriod'}, $todayStr);
            if ($dateExpiry > $reserveExpiry){
                $dateExpiry = $reserveExpiry;
            }
            circ_fillReserve($dbh, $uidReserve, $itemCircStatus->{'rid'});
            my $placeOnHold = circ_placeHold($dbh, $idReserve, $todayStr, $dateExpiry);
        }
    }
    return $retVal;
}

sub processRenew{
    my ($dbh, $uid, $bcList, $rnDateDue,$override)= @_;
    my @arrRenew = split/,/, $bcList;
    my @renewFailList = ();
    my $renewStatus;
    my $renewable = 0;
    for (my $i= 0; $i < scalar(@arrRenew); $i++){
        my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$arrRenew[$i]});
        my $itemInfo        = circ_getItemInfo($dbh, $arrRenew[$i], $uid);
        $renewStatus = 0;
        $renewable = $override? 1: ($itemCircStatus->{'renewalCount'} < $itemCircStatus->{'maxRenewal'} ) ? 1:0;
        if ($itemCircStatus->{'l_uid'} == $uid && $renewable){
            my $dateDue = ($rnDateDue ne '')? $rnDateDue:getRenewDueDate($itemInfo->{'renewalPeriod'}, $itemCircStatus->{'l_duedate'},$todayStr);
            $renewStatus = circ_processRenew($dbh, {uid=>$uid, barcode=>$arrRenew[$i], rnDate=>$dateDue});
        }
        if (!$renewStatus){
            push @renewFailList, {
                        bc      =>$arrRenew[$i], 
                        rname   =>$itemInfo->{'rname'}, 
                        renewable=>$renewable,
            };
        }
    }
    return \@renewFailList;
}

sub declareLost{
    my ($dbh, $uid, $bcList) = @_;
    my @arrLost = split/,/,$bcList;
    for (my $i = 0; $i < @arrLost; $i++){
        my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$arrLost[$i]});
        my $itemInfo        = circ_getItemInfo($dbh, $arrLost[$i], $uid);
        if ($itemCircStatus->{'l_uid'} == $uid){
            circ_declareLost($dbh, $uid ,$arrLost[$i]);
        }
        if ($itemCircStatus->{'l_idLoan'}){
            my $lost_odl_id = circ_record_ODL($dbh,$itemCircStatus->{'l_idLoan'},'lost', 0 );
        }
    }
}

sub getDeadLineDate{
    my ($length, $dateStr) = @_;
    my $retDate;

    if ($length <= 0){
        return $retDate =  `date -d'+%Y-%m-%d %H:%M:%S'`;
    }
    return $retDate =  `date -d '$length hour' '+%Y-%m-%d %H:%M:%S'`;
}

sub getRenewDueDate{
    
    #my ($Dh, $duedate,$todayStr) = @_;
    my ($renewalPeriod, $duedate,$todayStr) = @_;
    my $retDate;
    my ($year,$month,$day,$hour,$min,$sec) = ($todayStr =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$/);
    #my ($DYear, $DMonth,$DDay,$DHour,$DMin,$DSec) = Add_Delta_DHMS($year,$month,$day,$hour,$min,$sec, 0,$Dh,0,0);
    #$retDate = sprintf("%04d-%02d-%02d %02d:%02d:%02d" ,$DYear, $DMonth,$DDay,$DHour,$DMin,$DSec);
    #return $retDate;
    return $retDate = date_getDeadLineDate($renewalPeriod, $todayStr);

}

sub processListLoan {

    my ($dbh,$uid,$input) = @_;
    my $listLoanDDateType = $input->{'listLoanDDate'};
    my @bcList  = ($cgi->param('bc_listLoan')) ;
    my $dueDate = "";
    if ($listLoanDDateType eq "hour" || $listLoanDDateType eq "day"){
        my $tmp_date = ( $listLoanDDateType eq "hour")? $input->{'llhDueDate'} :$input->{'lldDueDate'} ;
        $dueDate = formatStrDateDue($tmp_date, $listLoanDDateType); 
    }
    elsif ( $listLoanDDateType eq "ind"){
        $dueDate = formatStrDateDue("2100-12-31", "d");
    }
    foreach my $bc (@bcList){
        my $loan = doListLoan ($dbh,$uid,$bc,$dueDate);
    }
}

sub doListLoan {
    
    my ($dbh,$uid,$bc,$dueDate) = @_;
    my $loan = circ_processLoan($dbh, {uid=>$uid,barcode=>$bc, dateLoan=>$todayStr, dateDue=>$dueDate});
    return $loan;
}

sub getItemDueDate{
    my($loanPeriod,$loanUnit, $todayStr) = @_;
    my $retDD;
    #return $retDD = `date -d '$loanPeriod hour' '+%Y-%m-%d %H:%M:%S'`
    if ($loanUnit eq 'hour' ){
        $retDD = date_getDeadLineDateTime($loanPeriod, $todayStr);
    }
    else {
        $retDD = date_getDeadLineDate($loanPeriod, $todayStr);
    }
    return $retDD;
}

sub formatStrDateDue{
    my ($t_date,$h_d) = @_;
    my $retDD;
    return if ($t_date eq '' || $h_d eq '');
    if ($h_d eq 'd' || $h_d eq 'day' ){
          return $retDD = $t_date . ' 23:59:59';
    }
    return $retDD = `date -d '$t_date hour' '+%Y-%m-%d %H:%M:%S'`;
}

