Location: PHPKode > projects > SENAYAN Library Automation > senayan3-stable5/admin/modules/circulation/circulation_base_lib.inc.php
<?php

/*

VERSION : 3.0
CODENAME : SENAYAN
AUTHOR :
    Code and Programming : ARIE NUGRAHA (hide@address.com)
    Database Design : HENDRO WICAKSONO (hide@address.com) & WARDIYONO (hide@address.com)

SENAYAN Library Automation System
Copyright (C) 2007

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program (GPL License.txt); if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

/* CIRCULATION BASE LIBRARY */

// define some circulation/loan status
define('LOAN_LIMIT_REACHED', 1);
define('ITEM_NOT_FOUND', 2);
define('ITEM_SESSION_ADDED', 3);
define('ITEM_UNAVAILABLE', 4);
define('TRANS_FLUSH_ERROR', 5);
define('TRANS_FLUSH_SUCCESS', 6);
define('LOAN_NOT_PERMITTED', 7);
define('ITEM_LOAN_FORBID', 8);
define('ITEM_RESERVED', 9);

class circulation extends member
{
    protected $loan_limit = 0;
    protected $loan_periode = 0;
    protected $reborrow_limit = 0;
    protected $fine_each_day = 0;
    protected $item_loan_rules = 0;
    protected $overdue_days = 0;
    protected $grace_periode = 0;
    public $holiday_dayname = array('Sun');
    public $holiday_date = array();
    public $loan_have_overdue = false;

    # class constructor
    public function __construct($obj_db, $str_member_id)
    {
        parent::__construct($obj_db, $str_member_id);
        $this->loan_limit = intval($this->member_type_prop['loan_limit']);
        $this->loan_periode = intval($this->member_type_prop['loan_periode']);
        $this->reborrow_limit = intval($this->member_type_prop['reborrow_limit']);
        $this->fine_each_day = intval($this->member_type_prop['fine_each_day']);
        $this->grace_periode = intval($this->member_type_prop['grace_periode']);
    }


    # Set complex loan rules
    # return : void
    public function setLoanRules($int_coll_type = 0, $int_gmd_id = 0)
    {
        // if the collection type and gmd is not specified
        // get from the membership type directly
        if (!$int_coll_type AND !$int_gmd_id) {
            return;
        }

        $ctype_string = '';
        if ($int_coll_type) {
            $ctype_string .= ' AND coll_type_id='.intval($int_coll_type).' ';
        }
        $gmd_string = '';
        if ($int_gmd_id) {
            $gmd_string .= ' AND gmd_id='.intval($int_gmd_id).' ';
        }

        // get the data from the loan rules table
        $_loan_rules_q = $this->obj_db->query("SELECT * FROM mst_loan_rules
            WHERE member_type_id=".intval($this->member_type_id)." $ctype_string $gmd_string");
        // check if the loan rules exists
        if ($_loan_rules_q->num_rows > 0) {
            $_loan_rules_d = $_loan_rules_q->fetch_assoc();
            $this->loan_limit = $_loan_rules_d['loan_limit'];
            $this->loan_periode = $_loan_rules_d['loan_periode'];
            $this->reborrow_limit = $_loan_rules_d['reborrow_limit'];
            $this->fine_each_day = $_loan_rules_d['fine_each_day'];
            $this->grace_periode = $_loan_rules_d['grace_periode'];
            $this->item_loan_rules = $_loan_rules_d['loan_rules_id'];
        } else {
            // get data from the loan rules table with collection type specified but GMD not specified
            $_loan_rules_q = $this->obj_db->query("SELECT * FROM mst_loan_rules
                WHERE member_type_id=".intval($this->member_type_id)." $ctype_string");
            // check if the loan rules exists
            if ($_loan_rules_q->num_rows > 0) {
                $_loan_rules_d = $_loan_rules_q->fetch_assoc();
                $this->loan_limit = $_loan_rules_d['loan_limit'];
                $this->loan_periode = $_loan_rules_d['loan_periode'];
                $this->reborrow_limit = $_loan_rules_d['reborrow_limit'];
                $this->fine_each_day = $_loan_rules_d['fine_each_day'];
                $this->grace_periode = $_loan_rules_d['grace_periode'];
                $this->item_loan_rules = $_loan_rules_d['loan_rules_id'];
            } else {
                // get data from the loan rules table with GMD specified but collection type not specified
                $_loan_rules_q = $this->obj_db->query("SELECT * FROM mst_loan_rules
                    WHERE member_type_id=".intval($this->member_type_id)." $gmd_string");
                // check if the loan rules exists
                if ($_loan_rules_q->num_rows > 0) {
                    $_loan_rules_d = $_loan_rules_q->fetch_assoc();
                    $this->loan_limit = $_loan_rules_d['loan_limit'];
                    $this->loan_periode = $_loan_rules_d['loan_periode'];
                    $this->reborrow_limit = $_loan_rules_d['reborrow_limit'];
                    $this->fine_each_day = $_loan_rules_d['fine_each_day'];
                    $this->grace_periode = $_loan_rules_d['grace_periode'];
                    $this->item_loan_rules = $_loan_rules_d['loan_rules_id'];
                }
            }
        }
        // destroy query object
        unset($_loan_rules_q);
    }


    # add item to loan session
    # return : boolean
    public function addLoanSession($str_item_code, $bool_ignore_rules = false)
    {
        // you cant borrow any collection if your membership is expired
        if ($this->is_expire) {
            return LOAN_NOT_PERMITTED;
        }
        $_q = $this->obj_db->query("SELECT b.title, i.coll_type_id, b.gmd_id, ist.rules FROM biblio AS b
            LEFT JOIN item AS i ON b.biblio_id=i.biblio_id
            LEFT JOIN mst_item_status AS ist ON i.item_status_id=ist.item_status_id
            WHERE i.item_code='$str_item_code'");
        $_d = $_q->fetch_row();
        if ($_q->num_rows > 0) {
            // first, check for availability for this item
            $_avail_q = $this->obj_db->query("SELECT item_code FROM loan AS L
                WHERE L.item_code='$str_item_code' AND L.is_lent=1 AND L.is_return=0");
            // if we find any record then it means the item is unavailable
            if ($_avail_q->num_rows > 0) {
                return ITEM_UNAVAILABLE;
            }
            // check status for item
            if ($_d[3]) {
                $arr_rules = @unserialize($_d[3]);
                if ($arr_rules) {
                    if (in_array(NO_LOAN_TRANSACTION, $arr_rules)) {
                        return ITEM_LOAN_FORBID;
                    }
                }
            }

            if (!defined('IGNORE_LOAN_RULES')) {
                // check if this item is being reserved by other member
                $_resv_q = $this->obj_db->query("SELECT l.loan_id FROM reserve AS rs
                    INNER JOIN loan AS l ON rs.item_code=l.item_code
                    WHERE rs.item_code='$str_item_code' AND rs.member_id!='".$_SESSION['memberID']."'");
                if ($_resv_q->num_rows > 0) {
                    return ITEM_RESERVED;
                }
            }

            $_loan_date = date('Y-m-d');
            // set loan rules
            self::setLoanRules($_d[1], $_d[2]);
            // calculate due date
            $_due_date = simbio_date::getNextDate($this->loan_periode, $_loan_date);
            $_due_date = simbio_date::getNextDateNotHoliday($_due_date, $this->holiday_dayname, $this->holiday_date);
            // check if due date is not more than member expiry date
            $_expiry_date_compare = simbio_date::compareDates($_due_date, $this->expire_date);
            if ($_expiry_date_compare != $this->expire_date) {
                $_due_date = $this->expire_date;
            }
            $_curr_loan_num = count(parent::getItemLoan($this->item_loan_rules));
            $_curr_session_loan_num = count($_SESSION['temp_loan']);
            // get number of temporay loan session for specific loan rules
            if ($this->item_loan_rules) {
                $_curr_session_loan_num = 0;
                foreach ($_SESSION['temp_loan'] as $loan_session_item) {
                    if ($loan_session_item['loan_rules_id'] == $this->item_loan_rules) {
                        $_curr_session_loan_num++;
                    }
                }
            }

            // check if we ignoring loan rules
            if (defined('IGNORE_LOAN_RULES')) {
                $_SESSION['temp_loan'][$str_item_code] = array(
                    'item_code' => $str_item_code,
                    'loan_rules_id' => $this->item_loan_rules,
                    'title' => $_d[0],
                    'loan_date' => $_loan_date,
                    'due_date' => $_due_date
                );
                return ITEM_SESSION_ADDED;
            } else if ($this->loan_limit > ($_curr_loan_num + $_curr_session_loan_num)) {
                // are the loan limit reached?
                $_SESSION['temp_loan'][$str_item_code] = array(
                    'item_code' => $str_item_code,
                    'loan_rules_id' => $this->item_loan_rules,
                    'title' => $_d[0],
                    'loan_date' => $_loan_date,
                    'due_date' => $_due_date
                );
                return ITEM_SESSION_ADDED;
            } else {
                return LOAN_LIMIT_REACHED;
            }
        } else {
            return ITEM_NOT_FOUND;
        }
    }


    # remove item from loan session
    # return : void
    public function removeLoanSession($str_item_code)
    {
        unset($_SESSION['temp_loan'][$str_item_code]);
    }


    # return an item from loan
    # return : void
    public function returnItem($int_loan_id)
    {
        $_return_date = date('Y-m-d');
        // check for overdue
        $_fines = self::countOverdueValue($int_loan_id, $_return_date);
        // put data to fines table
        if ($_fines) {
            // set overdue flags
            $this->loan_have_overdue = true;
            $this->overdue_days = $_fines['days'];
            if (is_numeric($this->overdue_days) AND $this->overdue_days > 0) {
                $this->obj_db->query("INSERT INTO fines VALUES(NULL, '$_return_date', '".$this->member_id ."', ".$_fines['value'].", 0, 'Overdue fines for item ".$_fines['item']."')");
            }
        }
        // update the loan data
        $this->obj_db->query("UPDATE loan SET is_return=1, return_date='$_return_date' WHERE loan_id=$int_loan_id AND member_id='".$this->member_id."' AND is_lent=1 AND is_return=0");
        // check if this item is being reserved by other member
        $_resv_q = $this->obj_db->query("SELECT l.item_code FROM reserve AS rs
            INNER JOIN loan AS l ON rs.item_code=l.item_code
            WHERE l.loan_id=$int_loan_id AND rs.member_id!='".$this->member_id."'");
        if ($_resv_q->num_rows > 0) {
            return ITEM_RESERVED;
        }
        return true;
    }


    # extend item loan
    # return : void
    public function extendItemLoan($int_loan_id)
    {
        // check if this item is being reserved by other member
        $_resv_q = $this->obj_db->query("SELECT l.item_code FROM reserve AS rs
            INNER JOIN loan AS l ON rs.item_code=l.item_code
            WHERE l.loan_id=$int_loan_id AND rs.member_id!='".$_SESSION['memberID']."'");
        if ($_resv_q->num_rows > 0) {
            return ITEM_RESERVED;
        }
        // return this item first
        self::returnItem($int_loan_id);
        // get loan rules for this loan
        $_loan_rules_q = $this->obj_db->query("SELECT loan_periode FROM mst_loan_rules AS lr LEFT JOIN
            loan AS l ON lr.loan_rules_id=l.loan_rules_id WHERE loan_id=$int_loan_id");
        if ($_loan_rules_q->num_rows > 0) {
            $_loan_rules_d = $_loan_rules_q->fetch_row();
            $this->loan_periode = $_loan_rules_d[0];
        }
        // due date
        $_loan_date = date('Y-m-d');
        // calculate due date
        $_due_date = simbio_date::getNextDate($this->loan_periode, $_loan_date);
        $_due_date = simbio_date::getNextDateNotHoliday($_due_date, $this->holiday_dayname, $this->holiday_date);
        $query = $this->obj_db->query("UPDATE loan SET renewed=renewed+1, due_date='$_due_date', is_return=0
            WHERE loan_id=$int_loan_id AND member_id='".$this->member_id."'");
        $_SESSION['reborrowed'][] = $int_loan_id;
        return true;
    }


    # count overdue value
    # return : array on success
    public function countOverdueValue($int_loan_id, $str_return_date)
    {
        $_on_grace_periode = false;
        // get due date for this loan
        $_loan_q = $this->obj_db->query("SELECT l.due_date, l.loan_rules_id, l.item_code FROM loan AS l WHERE loan_id=$int_loan_id");
        $_loan_d = $_loan_q->fetch_row();
        // compare dates
        $_date = simbio_date::compareDates($str_return_date, $_loan_d[0]);
        if ($_date == $str_return_date) {
            // how many days the overdue
            $_overdue_days = simbio_date::calcDay($str_return_date, $_loan_d[0]);
            // count holiday and subtract it from overdue days
            $_holiday_count = simbio_date::countHolidayBetween($_loan_d[0], $str_return_date, $this->holiday_dayname, $this->holiday_date);
            $_overdue_days = $_overdue_days-$_holiday_count;
            if ($_overdue_days < 1) {
                return false;
            }
            // check for grace periode
            if (!empty($this->grace_periode)) {
                $_due_plus_grace_date = simbio_date::getNextDate($this->grace_periode, $_loan_d[0]);
                $_latest_date = simbio_date::compareDates($str_return_date, $_due_plus_grace_date);
                if ($_latest_date == $_due_plus_grace_date) {
                    $_on_grace_periode = true;
                }
            }
            // check for loan rules if any
            if (!empty($_loan_d[1])) {
                $_loan_rules_q = $this->obj_db->query('SELECT fine_each_day, grace_periode FROM mst_loan_rules WHERE loan_rules_id='.$_loan_d[1]);
                $_loan_rules_d = $_loan_rules_q->fetch_row();
                $this->fine_each_day = $_loan_rules_d[0];
                // check for grace periode
                if (!empty($_loan_rules_d[1])) {
                    $_due_plus_grace_date = simbio_date::getNextDate($_loan_rules_d[1], $_loan_d[0]);
                    $_latest_date = simbio_date::compareDates($str_return_date, $_due_plus_grace_date);
                    if ($_latest_date == $_due_plus_grace_date) {
                        $_on_grace_periode = true;
                    }
                }
            }
            // calculate fines value
            if ($_on_grace_periode) {
                return array('days' => 'On Grace Periode', 'value' => 0, 'item' => $_loan_d[2]);
            } else {
                $_fines_value = $this->fine_each_day*$_overdue_days;
                return array('days' => $_overdue_days, 'value' => $_fines_value, 'item' => $_loan_d[2]);
            }
        }
        return false;
    }


    # get overdue days
    # return : integer
    public function getOverdueDays()
    {
        return $this->overdue_days;
    }


    # finish loan transaction session
    # return : void
    public function finishLoanSession()
    {
        if (count($_SESSION['temp_loan']) > 0) {
            $error_num = 0;
            foreach ($_SESSION['temp_loan'] as $loan_item) {
                // insert loan data to database
                if ($loan_item['loan_rules_id']) {
                    $data['loan_rules_id'] = $loan_item['loan_rules_id'];
                } else {
                    $data['loan_rules_id'] = 'literal{0}';
                }
                $data['item_code'] = $loan_item['item_code'];
                $data['member_id'] = $this->member_id;
                $data['loan_date'] = $loan_item['loan_date'];
                $data['due_date'] = $loan_item['due_date'];
                $data['renewed'] = 'literal{0}';
                $data['is_lent'] = 1;
                $data['is_return'] = 'literal{0}';
                $sql_op = new simbio_dbop($this->obj_db);
                if (!$sql_op->insert('loan', $data)) {
                    $error_num++;
                } else {
                    // remove any reservation related to this items
                    @$this->obj_db->query('DELETE FROM reserve WHERE member_id=\''.$this->member_id.'\' AND item_code=\''.$data['item_code'].'\'');
                }
            }
            // clean all circulation sessions
            $_SESSION['temp_loan'] = array();
            $_SESSION['reborrowed'] = array();
            unset($_SESSION['memberID']);
            // return the status
            if ($error_num) {
                return TRANS_FLUSH_ERROR;
            } else {
                return TRANS_FLUSH_SUCCESS;
            }
        } else {
            // clean all circulation sessions
            $_SESSION['temp_loan'] = array();
            $_SESSION['reborrowed'] = array();
            unset($_SESSION['memberID']);
        }
    }
}
?>
Return current item: SENAYAN Library Automation