#!/usr/bin/perl

#use utf8;
use strict;
use CGI;

use Time::localtime;
use Opals::Context;
use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_preference
);

use Opals::User qw(
    user_getInformationById
    user_isUserBc
);
use Opals::Circulation qw(
    circ_getUserCircStatus
    circ_getItemStatus
    circ_getItemInfo
    circ_getRecID
    circ_getActiveLoanId
    circ_processLoan
    circ_placeHold
    circ_fillHold
    circ_cancelHold
    circ_placeReserve
    circ_fillReserve
    circ_resetReserve
    circ_setAvailable
    circ_processRenew
    Circ_validateFollettBarcode
    Circ_validateSpectrumBarcode
    Circ_validateLeadingZeroBc
    circ_record_ODL
    circ_processReturn
    circ_numItemsAvailable
);
use Opals::Date qw(
    date_getDeadLineDate
    date_deltaWorkDay   
    date_parse
    date_today
    date_text

);

use Opals::BookingSystem qw(
    bs_numCopyBooked
    bs_isItemBooked_cat
    bs_getBooked4UidList
    bs_isBcHold4Uid
    bs_isItemLoan2Uid
    bs_isBcHold
    bs_isItemBooked4Uid
    bs_numBItemPending
    bs_placeHold
    bs_getBookingId4hold
    bs_getBookingInfo
    bs_fill
    bs_isBItemLoan2Uid

);
use Opals::Transaction qw(
    trans_doReverseLost
    
);
use Opals::BarcodeMgmt qw(
    bcm_validateBc
);


use Opals::Constant;

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

my $cgi      = CGI->new;
my $input    = $cgi->Vars();
my $uid      = $input->{"uid"};
my $barcode  = $input->{"barcode"};
my $dueDate  = $input->{"duedate"};
my $cmdCode  = $input->{"command"};
my $loanType = $input->{"loanType"};

if(!defined $loanType || $loanType ne 'hourly'){
    $loanType = 'daily';
}

my ($status,$errorCode,$errorMsg)    ;
my ($permission, $cookie, $template) = tmpl_read(
    {
        dbh             => $dbh,
        cgi             => $cgi,
        tmplFile        => 'ajax/circ/loan.tmpl',
        reqPermission   => 'circ_loan',
    }
);
my $syspref  = tmpl_preference($dbh);
my $chargeFine   = $syspref->{'charge_overdue'};
my $loginuid = $template->param('curUserId');
my $tm = localtime;
my $todayStr = sprintf("%04d-%02d-%02d", $tm->year+1900, ($tm->mon)+1, $tm->mday);
my $dLast  = Opals::Context->preference('dateLast');
my $lang=$template->param('curLang');

my @cookieList = (@$cookie);
if ($permission && $permission->{'circ_loan'}) {
    my ($userInfo, $guardian) = user_getInformationById($dbh, $uid);
    if(!$userInfo->{'uid'} ){
    }
    my $status=$userInfo->{'status'};
    my $loanOverride     = $cgi->cookie('loanOverride');
    my $validateBc       = $syspref->{'validateBarcode'}; 
    my $barcodeType      = $syspref->{'barcodeType'}; 
    my $circulationSound = $syspref->{'circulationSound'};
   # Load borrower type (or permissions) --- quick user entry   
 


    my $itemCategory=$input->{'itemCategory'};
    if(!$itemCategory || $itemCategory !~ m/Library|Textbook/gi){
        $itemCategory= "Library";
    }

    push @cookieList, $cgi->cookie(
        -name   => 'borrower',
        -value  => $uid
    );
    push @cookieList, $cgi->cookie(
        -name   => 'loanOverride',
        -value  => $loanOverride
    );

    $barcode    =~ s/^\s+|\s+$//g;
    $barcode = bcm_validateBc($dbh,$barcode,$barcodeType) if($validateBc eq '1');
                 
    my ($processCode,$userMsgCode,$itemMsgCode,$msgCode)=('','','');
    my ($return,$hold,$reserve,$bookingInfo)=({},{},{},{});
    my $loanId=0;
    if($barcode ne ''){
        my $rid            = circ_getRecID($dbh,$barcode);
        my $itemInfo       = circ_getItemInfo($dbh, $barcode, $uid);
        my $loanPeriod = ($itemInfo->{'loanPeriod'})? $itemInfo->{'loanPeriod'} :0;
        $dueDate = validateDueDate($dueDate,$loanPeriod,$itemCategory); 
        my $userStatus     = circ_getUserCircStatus($dbh,$uid,$barcode);
        my $itemCircStatus = circ_getItemStatus($dbh, $barcode, $uid);
        my $nCopyBooked    = bs_numCopyBooked($dbh, $rid,1,'',$dueDate);
        if($nCopyBooked>0){
            $itemCircStatus->{'itemBooked'}      = bs_numBItemPending($dbh,$rid,1);
        }
        if ($itemCircStatus->{'itemBooked'}){
            $itemCircStatus->{'booked4Uid'}       = bs_isItemBooked4Uid($dbh,$uid,$rid,1,'',$dueDate);
            $itemCircStatus->{'hold4CurUid'}      = bs_isBcHold4Uid($dbh,$uid,$barcode,1,'',$dueDate);
            $itemCircStatus->{'booked4UidList'}   = bs_getBooked4UidList($dbh, $rid,1,'',$dueDate);
            $itemCircStatus->{'itemLoan2Uid'}     = bs_isBItemLoan2Uid($dbh, $itemCircStatus->{'booked4Uid'},$rid,1,$uid);
            $itemCircStatus->{'itemOnHold'}       = bs_isBcHold($dbh,$barcode,1,'',$dueDate);
        }
        my $itemMsgCode    = getMsgCode_item($itemCircStatus,$uid);
        my $userMsgCode    = getMsgCode_user($userStatus);
  
  
        if($itemCircStatus->{'status'}==IT_STAT_NOEXIST){
            my $tmpUid =user_isUserBc($dbh,$barcode);
            if($tmpUid>0){
                $itemMsgCode='19';
            }
        }

        elsif (($itemMsgCode ne '00')&&($itemInfo->{'loanPeriod'} ==0)){
            $itemMsgCode ='02';
        }
        my $holdList=undef;
        $holdList = $itemCircStatus->{'holdList'} if($itemCircStatus->{'holdList'});
        my $reserveList=undef;
        $reserveList = $itemCircStatus->{'reserveList'}if($itemCircStatus->{'reserveList'});

        my $allowOD = $syspref->{'allowOverdue'}; 
        if(($itemMsgCode eq '05' || $itemMsgCode eq '08' ||
           $itemMsgCode eq '12' || $itemMsgCode eq '16' ||
           $itemMsgCode eq '17' || $itemMsgCode eq '21' 
           || $itemMsgCode eq '22' || $itemMsgCode eq '23' 
           || $itemMsgCode eq '24' || $itemMsgCode eq '25' 
           || $itemMsgCode eq '26' || $itemMsgCode eq '27' || $itemMsgCode eq '28' 
           || $itemMsgCode eq '29' || $itemMsgCode eq '30' || $itemMsgCode eq '31'
           || $itemMsgCode eq '32') 
            && ( substr( $userMsgCode, 0, 3) eq '100')){         
           ($processCode,$loanId,$return,$reserve,$hold,$bookingInfo) = processCmd($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$itemCategory);
           if($itemMsgCode eq '22' || $itemMsgCode eq '25' || $itemMsgCode eq '28' || $itemMsgCode eq '31'){
                $dueDate = $bookingInfo->{'reserveTo'};
           }
        }
        elsif($cmdCode && $cmdCode ne '') {
            ($processCode,$loanId,$return,$reserve,$hold) = processCmd($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$cmdCode,$dueDate,$itemCategory);
         }
        elsif($itemCircStatus->{'status'} !=IT_STAT_NOEXIST){
            my $maxLoanBit = substr( $userMsgCode, 2, 1);
            my $overdueBit = substr( $userMsgCode, 1, 1);
            if(substr($loanOverride, 1, 1) eq '1'){
                $allowOD = 2;
            }
            if($maxLoanBit eq '1'){
                if(substr($loanOverride, 2, 1) eq '1' ){
                    ($processCode,$loanId,$return,$reserve,$hold) = processCmd($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$itemCategory);
                }
                else{
                    $msgCode        = $itemMsgCode ."-" . $userMsgCode;
                }
            }
            elsif($overdueBit eq '1' && $allowOD == 0){
                $processCode='no_override';
                    
            }
            elsif($overdueBit eq '1' && $allowOD == 2){
                ($processCode,$loanId,$return,$reserve,$hold) = processCmd($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$itemCategory);
            }
            else{
                $msgCode =$itemMsgCode ."-" . $userMsgCode;
           }
       }
        my $dateLoanStr= date_text($todayStr, 0,$lang);
        my $dueDateStr= date_text($dueDate, 0,$lang);
        $template->param(
            uid          => $uid,
            processCode  => $processCode,
            userMsgCode  => $userMsgCode,
            itemMsgCode  => $itemMsgCode,
            msgCode      => $msgCode,
            itemCategory => $itemCategory,
            duedate      => $dueDateStr,
            dateloan     => $dateLoanStr,
         );
        if($return->{'lid'} && $return->{'lid'}>0){
             $template->param(
                return_lid=>$return->{'lid'},
                return_overdue=>$return->{'overdue'},
                return_odl_id=>$return->{'odl_id'},
                );
        }
        if($reserve->{'reserveId'}){
            $template->param(
                r_reserveId=>$reserve->{'reserveId'},
                r_uid=>$reserve->{'uid'},
                r_firstName=>$reserve->{'firstName'},
                r_lastName=>$reserve->{'lastName'},
                r_dateReserve=>$dateLoanStr,
                r_expiryDate=>date_text($reserve->{'expiryDate'}, 0,$lang),
                ) ;
        }
        if($hold->{'reserveId'}){
            $template->param(
                h_reserveId=>$hold->{'reserveId'},
                h_uid=>$hold->{'uid'},
                h_firstName=>$hold->{'firstName'},
                h_lastName=>$hold->{'lastName'},
                h_dateReserve=>$dateLoanStr,
                h_expiryDate=>date_text($hold->{'expiryDate'}, 0,$lang)
                ) ;
        }
        if(defined $bookingInfo){
            $template->param(
               b_bookingId=>  $bookingInfo->{'bookingId'},
               b_reqFirstname=>  $bookingInfo->{'reqFirstname'},
               b_reqLastname=>  $bookingInfo->{'reqLastname'},
               b_department=>  $bookingInfo->{'department'},
               b_course=>  $bookingInfo->{'course'},
               b_reserveFrom=>  $bookingInfo->{'reserveFrom'},
               b_reserveTo=>  $bookingInfo->{'reserveTo'}
            );

        }
        $template->param(barcode   => $barcode);
        $template->param(holdList => $holdList) if($holdList);
        $template->param(reserveList => $reserveList) if($reserveList);
        if($itemCircStatus->{'status'}!=IT_STAT_NOEXIST){ 
            $template->param(
                lid             => $loanId,
                rid             => $itemInfo->{'rid'},
                l_title         => $itemInfo->{'title'},
                l_author        => $itemInfo->{'author'},
                l_pubName       => $itemInfo->{'pubName'},
                l_pubDate       => $itemInfo->{'pubDate'},
                l_price         => $itemInfo->{'price'},
                l_itemType      => $itemInfo->{'itemId'},
                l_callNumber    => $itemInfo->{'callNumber'},
                l_maxRenewal    => $itemInfo->{'maxRenewal'},
                isTempILL       => $itemCircStatus->{'isTempILL'},
                );
      }


  
    }

}
tmpl_write($dbh, $cgi, $cookie, $template);
#-------------------------------------------------------------------------------------------
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_FULL_AVAIL && getReserveId($uid,$holdList)>0 ){
          $retCode="05";
    }    
    elsif($itemCircStatus->{'status'}==IT_STAT_HAVE_RSVR ){
#     Thu, Apr 15, 2010 @ 15:35:33 EDT
        if($itemCircStatus->{'itemBooked'}>0){
            if($itemCircStatus->{'booked4Uid'}){
                $retCode=$itemCircStatus->{'itemLoan2Uid'}?"23":"22";
            }
            else{
                $retCode="21";
            }
        }
#/end Thu, Apr 15, 2010 @ 15:35:44 EDT        
        elsif(scalar(@$reserveList)){
            my $topReserveUID = @$reserveList[0]->{'uid'};
            if($itemCircStatus->{'inLibrary'}){
                if($uid ==$topReserveUID){
                    $retCode="08";            }
                elsif(getReserveId($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){
        if($itemCircStatus->{'itemBooked'}>0){
            if($itemCircStatus->{'booked4Uid'}){
                $retCode=$itemCircStatus->{'itemLoan2Uid'}?"26":"25";
            }
            else{
                $retCode="24";
            }
        }
        elsif($uid eq $itemCircStatus->{'l_uid'}){
            $retCode="15";    }
        elsif($uid ne $itemCircStatus->{'l_uid'}){
            $retCode="16";    }
    }
    else{ # fully available
        if($itemCircStatus->{'itemBooked'}>0){
            if($itemCircStatus->{'itemOnHold'}){
                if($itemCircStatus->{'hold4CurUid'}){
                    $retCode=$itemCircStatus->{'itemLoan2Uid'}?"29":"28";
                }
                else{
                    $retCode="27";
                }
            }
            else{
                if($itemCircStatus->{'booked4Uid'}){
                    $retCode=$itemCircStatus->{'itemLoan2Uid'}?"32":"31";
                }
                else{
                    $retCode="30";
                }
            }
        }
        else{
             $retCode= "17";
        }
    }
    return $retCode;    
}

#-------------------------------------------------------------------------------------------
sub isInBook4List{
    my ($uid,$book4List)=@_;
    # Fri, Apr 16, 2010 @ 09:35:45 EDT
    my $retVal = 0;
    foreach my $ii(@{$book4List}){
        if($ii == $uid){
            $retVal=1;  #item currently booked for this user
            last;
        }
    }
    return $retVal;
}
#-------------------------------------------------------------------------------------------
sub processCmd {
    my ($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$cmdCode,$dueDate,$type) =@_;
    my $dateReturn =$todayStr;
    my $loanId=0;
    my $return={}  ;
    my $reserve={};
    my $hold={};
    my $retVal; 
    my $bookingId=0;
    if ($cmdCode eq '03'){
        circ_setAvailable($dbh,$barcode,IT_STAT_LOST);       
        trans_doReverseLost($dbh,$barcode,$loginuid);
    }
    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   = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        my $idReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal =  "p1_07_R";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uid);
        $reserve={
            reserveId=>$idReserve,
            uid=>$uid,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        return ($retVal,$loanId,$return,$reserve,$hold);

    }
    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   = date_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";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };

        return ($retVal,$loanId,$return,$reserve,$hold);
     }
    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   = date_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";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        
        return ($retVal,$loanId,$return,$reserve,$hold);
    }
    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   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        $dateExpiry   = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        $idReserve = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        ($userInfo, $guardian) = user_getInformationById($dbh, $uid);
        $reserve={
            reserveId=>$idReserve,
            uid=>$uid,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        $retVal =  "p1_10_HR";
        return ($retVal,$loanId,$return,$reserve,$hold);
    }
    elsif($cmdCode eq '11' || $cmdCode eq '15'){
        my $renewal = circ_processRenew($dbh,$uid,$barcode,$dueDate);
        $retVal =  "p". $renewal->{'renewal_ok'} . "_" .$cmdCode;
        $loanId=circ_getActiveLoanId($dbh,$barcode,$uid);
        return ($retVal,$loanId,$return,$reserve,$hold);
    }
    elsif($cmdCode eq '11_H' ){
        $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   = date_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";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        return ($retVal,$loanId,$return,$reserve,$hold);
    }
    elsif($cmdCode eq '12' || $cmdCode eq '13'){
        $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $fillReserve  = circ_fillReserve($dbh,$uid ,$itemCircStatus->{'rid'});
    }
    elsif($cmdCode eq '13_H'){
        $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   = date_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";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };

        return ($retVal,$loanId,$return,$reserve,$hold);
    }
    elsif($cmdCode eq '14' || $cmdCode eq '16'){
        $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
    }
    elsif($cmdCode eq '14_H'){
        $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   = date_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";
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        
        return ($retVal,$loanId,$return,$reserve,$hold);
    }

    elsif($cmdCode eq '14_HR'){
        $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   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        my ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $hold={
            reserveId=>$idReserve,
            uid=>$uidReserve,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };
        $dateExpiry  = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        $idReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal      =  "p1_14_HR";
        ($userInfo, $guardian) = user_getInformationById($dbh, $uidReserve);
        $reserve={
            reserveId=>$idReserve,
            uid=>$uid,
            firstName=>$userInfo->{'firstname'},
            lastName=>$userInfo->{'lastname'},
            expiryDate=>$dateExpiry
            };

        return ($retVal,$loanId,$return,$reserve,$hold);
    }
#Mon, Apr 19, 2010 @ 11:17:02 EDT
# booking cases
    elsif($cmdCode eq '21' || $cmdCode eq '23' || $cmdCode eq '24' || $cmdCode eq '26'){
        $return     = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        $bookingId  = bs_placeHold($dbh,$bookingId,$barcode,$itemCircStatus->{'rid'},1);
        my $bInfo   = bs_getBookingInfo($dbh,$bookingId);
        $retVal     =  "p0_$cmdCode";
        return ($retVal,$loanId,$return,$reserve,$hold,$bInfo);
    }
    elsif($cmdCode eq '22' || $cmdCode eq '25' ){
         $return     = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
         $bookingId  = $itemCircStatus->{'booked4Uid'};
         $bookingId  = bs_placeHold($dbh,$bookingId,$barcode,$itemCircStatus->{'rid'},1);
         my $bInfo   = bs_getBookingInfo($dbh,$bookingId);
         $dueDate    = $bInfo->{'reserveTo'};
    }
    elsif($cmdCode eq '27' ||$cmdCode eq '29' ){
        my $bInfo  = bs_getBookingInfo($dbh,$itemCircStatus->{'itemOnHold'});
        $retVal    =  "p0_$cmdCode";
        return ($retVal,$loanId,$return,$reserve,$hold,$bInfo);
    }
    elsif( $cmdCode eq '30' || $cmdCode eq '32' ){
        $bookingId =bs_placeHold($dbh,$bookingId,$barcode,$itemCircStatus->{'rid'},1);
        my $bInfo  = bs_getBookingInfo($dbh,$bookingId);
        $retVal    =  "p0_$cmdCode";
        return ($retVal,$loanId,$return,$reserve,$hold,$bInfo);
    }
    elsif($cmdCode eq '28' || $cmdCode eq '31'){
         $bookingId = $itemCircStatus->{'booked4Uid'};
         my $bInfo  = bs_getBookingInfo($dbh,$bookingId);
         $dueDate   = $bInfo->{'reserveTo'};
    }
      
# /booking cases


#   2006-09-28
#   fill hold if item is availbale and on hold for the same patron        
#   BEGIN    
    my $idReserve =getReserveId($uid,$itemCircStatus->{'holdList'});
    if($idReserve && ($cmdCode eq '16' || $cmdCode eq 17)){
            my $fillHold  = circ_fillHold($dbh,$idReserve,$barcode);
    }
#   END     
    my $loan = circ_processLoan($dbh,$uid ,$barcode,$todayStr,$dueDate,$type);
    $loanId=circ_getActiveLoanId($dbh,$barcode,$uid);
    if($cmdCode eq '22' || $cmdCode eq '25' || $cmdCode eq '28' || $cmdCode eq '31'){
         bs_fill($dbh,$loanId,$bookingId,$barcode,$itemCircStatus->{'rid'},1);
    }
    $retVal = "p" .$loan  ."_" .$cmdCode ;
    return ($retVal,$loanId,$return,$reserve,$hold);

}
#-------------------------------------------------------------------------------------------
sub getMsgCode_user{
    my($userStatus)=@_;
    return $userStatus->{'status'}.$userStatus->{'overdue'}.$userStatus->{'maxLoan'}.$userStatus->{'maxRenew'}.$userStatus->{'maxReserve'};
}
#----------------------------------------------------------------------------------
#       this function is mainly used to check if a given uid is in the
#       reserve list or hold list and return its idReserve.
#----------------------------------------------------------------------------------
sub getReserveId{
    my($uid,$list)=@_;
    if(!$list){
        return 0;
    }
    for(my $i=0; $i < scalar(@$list); $i++){
        if(@$list[$i]->{'uid'} == $uid){
            return @$list[$i]->{'idReserve'};
        }
    }
    return 0;
}
#----------------------------------------------------------------------------------
sub getTopReserveId{
    my($list)=@_;
    if(!$list){
        return 0;
    }
   return @$list[0]->{'idReserve'};
}
#----------------------------------------------------------------------------------
sub getLastReserveId{
    my($list)=@_;
    if(!$list){
        return 0;
    }
    my $i =scalar(@$list) -1;
    return @$list[$i]->{'idReserve'};
}


#-------------------------------------------------------------------------------------------
sub validateBc{
   my($dbh,$barcode,$barcodeType)=@_;
   if($barcodeType eq '1'){#follett
        $barcode  = Circ_validateFollettBarcode($dbh,$barcode );
    }
    elsif($barcodeType eq '2'){#spectrum
        $barcode  = Circ_validateSpectrumBarcode($dbh,$barcode );
    }
    elsif($barcodeType eq '3'){#leading zero
        $barcode  = Circ_validateLeadingZeroBc($dbh,$barcode );
    }

    #else{#follett
    #    $barcode  = Circ_validateFollettBarcode($dbh,$barcode );
    #}
    return $barcode;
}

#-------------------------------------------------------------------------------------------
sub validateDueDate{
    my ($dueDate,$loanPeriod,$itemCategory)=@_;    
    my $time=" 23:59:59";
    if($loanType eq 'hourly' && $dueDate =~ m/(\d\d\d\d-\d\d-\d\d) (dd:dd:dd)/g){
        $time=$2;
    }
    if($dueDate && $dueDate ne ''){
        my $today = date_today();
        my $dd = date_parse($dueDate);
        if($dd && $dd <$today){
            $dueDate="";
        }
    }
    if(!$dueDate || $dueDate eq ''){
        if($itemCategory &&  $itemCategory =~ m/Textbook/gi){
            $dueDate = $dLast;
        }
        else{
            $dueDate = date_getDeadLineDate($loanPeriod ,$todayStr);
        }
    }
    else{
         $dueDate .= $time;
    }
    return $dueDate;
    
}
#-------------------------------------------------------------------------------
sub doReturn{
    my ($dbh,$uid,$barcode,$dateReturn)=@_;
    
    my $sth = $dbh->prepare("select idloan, dateDue from opl_loan where uid=? && barcode=? && dateReturn is null");
    $sth->execute($uid,$barcode);
    my $rec = $sth->fetchrow_hashref;
    my $idloan   = $rec->{'idloan'};
    my $dateDue    = date_parse($rec->{'dateDue'});
    my $dateRet = date_parse($dateReturn);
    my $NumOfOverdue = date_deltaWorkDay($dateDue, $dateRet);
    my $odl_id =0;
    # Even overduefine = 0, it is still recorded to keep track how many times
    # user make overdue
    if ($NumOfOverdue>0)
    {
        $odl_id = circ_record_ODL($dbh,$idloan ,'overdue',$NumOfOverdue);
    }
   my $return={lid=>$idloan,overdue=>$NumOfOverdue,odl_id=>$odl_id};
   circ_processReturn($dbh,$barcode,$dateReturn);
   return $return;
}

