<?php
// +---------------------------------------------------------------------------------------+
// | TenderSystem                                                                          |
// +---------------------------------------------------------------------------------------+
// | The contents of this file are subject to the TenderSystem Public License Version 1.1  |
// | ("License"); you may not use this file except in compliance with the License. You may |
// | obtain a copy of the License at http://www.tendersystem.com/tpl/                      |
// |                                                                                       |
// | Software distributed under the License is distributed on an "AS IS" basis, WITHOUT    |
// | WARRANTY OF ANY KIND, either express or implied. See the License for the specific     |
// | language governing rights and limitations under the License.                          |
// |                                                                                       |
// | All copies of the Covered Code must include the "Powered by TenderSystem" logo and    |
// | ValueCard copyright notice on every user interface screen and in every outgoing       |
// | email in the same form as they appear in the distribution.                            |
// |                                                                                       |
// | The Original Code is: TenderSystem                                                    |
// | The Initial Developer of the Original Code is ValueCard (Pty) Limited.                |
// | Portions created by ValueCard are Copyright (C) 2002 ValueCard (Pty) Limited.         |
// | All Rights Reserved.                                                                  |
// | Contributor(s): __________________.                                                   |
// +---------------------------------------------------------------------------------------+

/**
* Procure class
* @package TenderSystem
* @subpackage procure
* @copyright Copyright &copy; 2002, ValueCard (Pty) Ltd
* @license http://www.tendersystem.com/tpl/ TenderSystem Public License
* @version 
*/

// Security - ensure that file never called directly
// not required if global variables are off or API is hosted on a non-public server
if (eregi(basename(__FILE__),$_SERVER['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Class procure {
	// set paramaters
	var $error;
	
	function procure() {
		// allow php5 to work
		$this->error = array();	
	}
	
		/**
	 * Create a Tender item complete information
	 * 
	 * @param array params Tender item complete information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed Purchase Order ID on Success or FALSE on error  
	 */
	function create_tender_item_complete($params,$cfg,$conn){
		$this->tender = $params;
		// Check if main parameters exist 
		if (!$this->tender['user_id']){
			// Missing user id
			$this->error[] = "209";
		}
		if (!$this->tender['tender_item']){
			// Missing tender item id
			$this->error[] = "273";
		}
		// errors 
		if (!empty($this->error)) {
			$this->error[] = "260";
			return FALSE;
		}
		// the table name
		$new_database = new database;
		$table_name = "~tender_item_complete";
		// no id
		if(!$this->tender['id']) {
			// generate an id 
			$this->tender['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		}
		$new_database->setTime("created",$this->tender,"",$cfg);
		$new_database->parse_sql($table_name,$cfg);
		// execute
		$conn->AutoExecute($table_name,$this->tender,"INSERT");
	    if ($conn->ErrorMsg()) {
	    	// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while inserting into database 
			$this->error[] = "1064";
			// response
			return FALSE;
      	}
      	// response
		return $this->tender['id'];
	}
	
	/**
	 * Create a tender quote
	 * 
	 * @param array quote Tender Quote Information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed Quote ID or FALSE on error  
	 */
	function create_tender_quote($quote,$cfg,$conn) {
		// get the next id 
		$new_database = new database;
		$table_name = "~tender_quote";
		$quote['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		if (!$quote['id']) {
			// set the errors
			$this->error = $new_database->error;
			// response
			return FALSE;
		}
		// insert the items in the database
		$new_database = new database;
		$new_database->setTime("created",$quote,"",$cfg);
		if(!$quote['valid_until']) {
			$quote['valid_until'] =  date("Y-m-d");
		}
		if(!isset($quote['classification'])) {
			$quote['classification'] =  "1";
		}
		$table_name = "~tender_quote";
		$new_database->parse_sql($table_name,$cfg);
		// execute the query
 		$recordSet = $conn->AutoExecute($table_name,$quote,"INSERT");
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	}
		// response
		return $quote['id'];
	}
	
	/**
	 * create an tender item
	 *
	 * @param array item Tender Item information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed item id on success or FALSE on error  
	 */
	function create_tender_item($item,$cfg,$conn) {
		// get the next id 
		$new_database = new database;
		$table_name = "~tender_item";
		$item['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		if (!$item['id']) {
			// set the errors
			$this->error = $new_database->error;
			// response
			return FALSE;
		}
		if(!$item['quote']) {
			$item['quote'] = "0.00";
		}
		if(!$item['budget']) {
			$item['budget'] = "0.00";
		}
		// insert the items in the database
		$new_database->setTime("created",$item,"",$cfg);
		// execute the query
		$new_database->parse_sql($table_name,$cfg);
 		$conn->AutoExecute($table_name,$item,"INSERT");
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	} 
		// return item id
		return $item['id'];
	}
	
	/**
	 * Updates Tender  item Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function update_tender_item($update,$where,$cfg,$conn) {
		$new_database = new database;
		if(!$new_database->update_table("~tender_item",$update,$where,$cfg,$conn)) {
			if(!empty($new_database->error)) {
				$this->error = array_merge($this->error,$new_database->error);
			}
			// Error in Procure Class
			$this->error[] = "1029";
			return FALSE;
		} 
      	return TRUE;
	}
	
	/**
	 * Updates Tender  item Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function complete_tender_item($id,$cfg,$conn) {
		return $this->calculate_tender_item_transaction_fee($id,"6",$cfg,$conn);
	}
	
	function calculate_tender_item_transaction_fee($id,$status,$cfg,$conn) {
		// get transaction fee
		$sqlstr = "SELECT ~organisation.transaction_fee, ~organisation.transaction_min, ";
		$sqlstr.= "~tender_quote.price ";
		// FROM
		$sqlstr.= "FROM ~tender, ~tender_item, ~users, ~organisation,";
		$sqlstr.= " ~tender_quote ";
		// WHERE
		$sqlstr.= "WHERE ~tender.id = ~tender_item.tender ";
		$sqlstr.= "AND ~tender_item.id = '".$id."' ";
		$sqlstr.= "AND ~tender_quote.tender_item = '".$id."' ";
		$sqlstr.= "AND ~tender_quote.status != '0' ";
		$sqlstr.= "AND ~tender.user_id = ~users.id ";
		$sqlstr.= "AND ~organisation.id = ~users.organisation ";
		$sqlstr.= "ORDER BY ~tender_quote.price ASC ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	}
		$new_database = new database;
		if($status || $status === "0") {
			$update['status'] = $status;
		}
		$update['transaction_fee'] = max(($row['transaction_fee'] / 100) * $row['price'], $row['transaction_min']);
		$where = "id = ".$id." ";
		return $this->update_tender_item($update,$where,$cfg,$conn);
	}
	
	/**
	 * Updates Tender  item Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function close_tender_item($id,$cfg,$conn) {
		return $this->calculate_tender_item_transaction_fee($id,"4",$cfg,$conn);
	}
	
	function delete_tender_item($id,$error,$cfg,$conn) {
		$update['status'] = "0";
		$update['error'] = $error;
		$where = "id = ".$id." ";
		return $this->update_tender_item($update,$where,$cfg,$conn);
	}
	
	/**
	 * Updates Tender  item Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function complete_tender_quote($id,$cfg,$conn) {
		$new_database = new database;
		$update['status'] = "6";
		$where = "id = ".$id." ";
		return $this->update_tender_quote($update,$where,$cfg,$conn);
	}
	
	/**
	 * Updates Tender quote Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function update_tender_quote($update,$where,$cfg,$conn) {
		$new_database = new database;
		if(!$new_database->update_table("~tender_quote",$update,$where,$cfg,$conn)) {
			if(!empty($new_database->error)) {
				$this->error = array_merge($this->error,$new_database->error);
			}
			// Error in Procure Class
			$this->error[] = "1029";
			return FALSE;
		} 
      	return TRUE;
	}
	
	/**
	 * Updates Tender  item Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function update_tender($update,$where,$cfg,$conn) {
		$new_database = new database;
		if(!$new_database->update_table("~tender",$update,$where,$cfg,$conn)) {
			if(!empty($new_database->error)) {
				$this->error = array_merge($this->error,$new_database->error);
			}
			// Error in Procure Class
			$this->error[] = "1029";
			return FALSE;
		} 
      	return TRUE;
	}
	
	/**
	 * Updates Tender item complete Information
	 * 
	 * @param array update Tender item Information
	 * @param string where Where Statement
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on Success or FALSE on error  
	 */
	function update_item_complete($update,$where,$cfg,$conn) {
		$new_database = new database;
		if(!$new_database->update_table("~tender_item_complete",$update,$where,$cfg,$conn)) {
			if(!empty($new_database->error)) {
				$this->error = array_merge($this->error,$new_database->error);
			}
			// Error in Tender Class
			$this->error[] = "260";
			return FALSE;
		} 
      	return TRUE;
	}
	
	function get_attachment_info($id,$cfg,$conn) {	
		// determine if present
		$sqlstr = "SELECT ~attachment.id, ~attachment.authentication, ~attachment.name ";
		$sqlstr.= "FROM ~tender, ~attachment ";
		$sqlstr.= "WHERE ~tender.id = '".$id."' ";
		$sqlstr.= "AND ~tender.attachment = ~attachment.id ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		$row = $conn->GetRow($sqlstr);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	}
      	return $row;
	}
	
	/**
	 * Determine if valid time
	 * 
	 * @param mixed time closing time
	 * @param mixed time_i 
	 * @param mixed cfg The Config settings of tendersystem
	 * @param increment integer time increment default 3600 (60 * 60) 
	 */
	function get_valid_time($time,$time_i,$cfg,$increment=3600) {
		// get time info
		$time_info = localtime($time,1);
		// reformat holidays
		$holiday = array();
		foreach($cfg['holiday'] as $holi_value) {
			$holi_info = explode("-",$holi_value['date']);
			if(is_numeric($holi_info[0]) && is_numeric($holi_info[1])
			   && $holi_info[0] > "0" && $holi_info[1] > "0"
			   && $holi_info[0] < "13" && $holi_info[1] < "32") {
				$holiday[intval($holi_info[0])-1][] = intval($holi_info[1]);
			}
		}
		// if legal time
		if($cfg['time']['open'][$time_info['tm_wday']] <= $time_info['tm_hour'] 
			&& $cfg['time']['close'][$time_info['tm_wday']] > $time_info['tm_hour']
			&& !(is_array($holiday[$time_info['tm_mon']]) && in_array($time_info['tm_mday'],$holiday[$time_info['tm_mon']]))
			&& !(($cfg['time']['lunch']['start']['hour'] * 60 + $cfg['time']['lunch']['start']['min'] <= $time_info['tm_hour'] * 60 + $time_info['tm_min']) 
			&& ($cfg['time']['lunch']['end']['hour'] * 60 + $cfg['time']['lunch']['end']['min'] > $time_info['tm_hour'] * 60 + $time_info['tm_min']))) {
			return $time;
		} else {
			// calculate next available time
			$time_within = $time - $time_i;
			// if closing within certain time
			$time_info_within = localtime($time_within,1);
			// if legal time within
			if($cfg['time']['open'][$time_info_within['tm_wday']] + 1 <= $time_info_within['tm_hour'] 
			   && $cfg['time']['close'][$time_info_within['tm_wday']] > $time_info_within['tm_hour']
			   && (!is_array($holiday[$time_info['tm_mon']]) || !in_array($time_info_within['tm_mday'],$holiday[$time_info_within['tm_mon']]))
  	  		   && !(($cfg['time']['lunch']['start']['hour'] * 60 + $cfg['time']['lunch']['start']['min'] <= 
			   $time_info['tm_hour'] * 60 + $time_info['tm_min']) 
		   	   && ($cfg['time']['lunch']['end']['hour'] * 60 + $cfg['time']['lunch']['end']['min'] > 
		   	   $time_info['tm_hour'] * 60 + $time_info['tm_min']))) {
			   		   
			   	while($cfg['time']['open'][$time_info_within['tm_wday']] <= $time_info_within['tm_hour'] 
		   			&& $cfg['time']['close'][$time_info_within['tm_wday']] > $time_info_within['tm_hour']
		   			&& (!is_array($holiday[$time_info['tm_mon']]) || !in_array($time_info['tm_mday'],$holiday[$time_info['tm_mon']]))
		   			&& !(($cfg['time']['lunch']['start']['hour'] * 60 + $cfg['time']['lunch']['start']['min'] <= 
					$time_info['tm_hour'] * 60 + $time_info['tm_min']) 
					&& ($cfg['time']['lunch']['end']['hour'] * 60 + $cfg['time']['lunch']['end']['min'] > 
					$time_info['tm_hour'] * 60 + $time_info['tm_min']))) {
						$time_within+=60;
			   			$time_info_within = localtime($time_within,1);
			   	}
				return $time_within - 60;
			} else {
				$prevent_loop = 0;
				$prevent_inc = $increment/86400;
				while(!($cfg['time']['open'][$time_info['tm_wday']] + 1 <= $time_info['tm_hour'] 
					&& $cfg['time']['close'][$time_info['tm_wday']] > $time_info['tm_hour']
					&& (!is_array($holiday[$time_info['tm_mon']]) || !in_array($time_info['tm_mday'],$holiday[$time_info['tm_mon']]))
					&& !(($cfg['time']['lunch']['start']['hour'] * 60 + $cfg['time']['lunch']['start']['min'] <= 
					$time_info['tm_hour'] * 60 + $time_info['tm_min']) 
					&& ($cfg['time']['lunch']['end']['hour'] * 60 + $cfg['time']['lunch']['end']['min'] > 
					$time_info['tm_hour'] * 60 + $time_info['tm_min'])))) {
						$time += $increment;
						$time_info = localtime($time,1);
						// this will prevent a continus looping
						$prevent_loop += $prevent_inc;
						if($prevent_loop > 365) {
							break;	
						}
				}
				return $time;
			}
		}
	}
	
	/**
	 * Get tenders information
	 * 
	 * @param integer id tender id
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function get_tender($id,$cfg,$conn) {
		$sqlstr = "SELECT * ";
		// FROM
		$sqlstr.= "FROM ~tender ";
		// WHERE
		$sqlstr.= "WHERE id = '".$id."' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $row;
	}
	
	/**
	 * Get tenders information
	 * 
	 * @param integer id tender id
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function get_purchase_order($id,$cfg,$conn) {
		$sqlstr = "SELECT * ";
		// FROM
		$sqlstr.= "FROM ~purchase_order ";
		// WHERE
		$sqlstr.= "WHERE id = ".$id." ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $row;
	}
	
	/**
	 * search for tender item information
	 * 
	 * @param array params search infromation
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function search_tender_item($params,$cfg,$conn) {
		$this->tender = $params;
		$sqlstr = "SELECT DISTINCT ~tender_item.id, ~tender_item.classification, ~tender_item.brand, ";
		$sqlstr.= "~tender_item.model, ~tender_item.description, ~tender_item.tender, ";
		$sqlstr.= "~category_sub.name AS category_subname,   ";
		$sqlstr.= "~category.name AS categoryname,   ";
		$sqlstr.= "~tender_item.quote, ~tender_item.budget, ~tender_item.status ";
		// FROM
		$sqlstr.= "FROM ~tender_item, ~category_sub, ~tender_request, ~tender, ~category ";
		// WHERE
		$sqlstr.= "WHERE ~tender_item.category_sub = ~category_sub.id ";
		$sqlstr.= "AND ~category_sub.status = '1' ";
		$sqlstr.= "AND ~category_sub.category = ~category.id ";
		$sqlstr.= "AND ~category.status = '1' ";
		$sqlstr.= "AND ~tender_item.id = ~tender_request.tender_item ";
		$sqlstr.= "AND ~tender_request.status = '1' ";
		$sqlstr.= "AND ~tender_item.tender = ~tender.id ";
		if($this->tender['searchinfo']['tenderstatus']) {
			$sqlstr.= "AND ~tender_item.status = '".$this->tender['searchinfo']['tenderstatus']."' ";
		}
		if($this->tender['searchinfo']['tenderclassification']) {
			$sqlstr.= "AND ~tender.classification = '".$this->tender['searchinfo']['tenderclassification']."' ";
		}
		if($this->tender['searchinfo']['tenderid']) {
			$sqlstr.= "AND ~tender_item.tender = '".$this->tender['searchinfo']['tenderid']."' ";
		}
		if($this->tender['searchinfo']['tenderitemid']) {
			$sqlstr.= "AND ~tender_item.id = '".$this->tender['searchinfo']['tenderitemid']."' ";
		}
		if($this->tender['searchinfo']['agentid']) {
			$sqlstr.= "AND ~tender_request.user_id = '".$this->tender['searchinfo']['agentid']."' ";
		}
		if($this->tender['searchinfo']['usersid']) {
			$sqlstr.= "AND ~tender_request.user_id = '".$this->tender['searchinfo']['agentid']."' ";
		}
		// ORDER BY
		$sqlstr.= "ORDER BY ~tender_item.tender ASC, ~tender_item.classification ASC, ~tender_item.id ASC ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$all = $conn->GetAll($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $all;
	}
	
	/**
	 * Get information about tender item
	 * 
	 * @param array id tender_item ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tenders quotes or FALSE on error  
	 */
	function get_tender_item($id,$cfg,$conn) {
		if(!$id) {
			// Missing tender item id
			$this->error[] = "273";
		}
		// errors 
		if(!empty($this->error)) {
			$this->error[] = "317";
			// reponse
			return FALSE;
		}
		$sqlstr = "SELECT *  ";
		// FROM
		$sqlstr.= "FROM ~tender_item ";
		// WHERE
		$sqlstr.= "WHERE id = '".$id."' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $row;
	}
	
	/**
	 * search for tender quote
	 * 
	 * @param array params search infromation
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function search_quote($params,$cfg,$conn) {
		$this->tender = $params;
		$sqlstr = "SELECT DISTINCT ~tender_quote.id, ~tender.status, ~tender_quote.user_id, ";
		$sqlstr.= "~tender_quote.tender_item, ~tender_quote.price, ~tender_quote.status AS tender_quotestatus, ";
		$sqlstr.= "~tender.id AS tenderid,";
		$sqlstr.= "~tender_item.status AS tender_itemstatus ";
		// FROM
		$sqlstr.= "FROM ~tender, ~tender_item, ~tender_quote ";
		// WHERE
		$sqlstr.= "WHERE ~tender_quote.status != '0' ";
		$sqlstr.= "AND ~tender_quote.tender_item = ~tender_item.id ";
		$sqlstr.= "AND ~tender_item.tender = ~tender.id ";
		if($this->tender['searchinfo']['agentid']) {
			$sqlstr.= "AND ~tender_quote.user_id = '".$this->tender['searchinfo']['agentid']."' ";
		}
		if($this->tender['searchinfo']['tenderclassification']) {
			$sqlstr.= "AND ~tender.classification = '".$this->tender['searchinfo']['tenderclassification']."' ";
		}
		if($this->tender['searchinfo']['tenderstatus']) {
			$sqlstr.= "AND ~tender.status = '".$this->tender['searchinfo']['tenderstatus']."' ";
			$sqlstr.= "AND ~tender_item.status = '".$this->tender['searchinfo']['tenderstatus']."' ";
		}
		if($this->tender['searchinfo']['mintenderstatus']) {
			$sqlstr.= "AND ~tender.status >= '".$this->tender['searchinfo']['mintenderstatus']."' ";
			$sqlstr.= "AND ~tender_item.status >= '".$this->tender['searchinfo']['mintenderstatus']."' ";
		}
		if($this->tender['searchinfo']['maxtenderstatus']) {
			$sqlstr.= "AND ~tender.status <= '".$this->tender['searchinfo']['maxtenderstatus']."' ";
			$sqlstr.= "AND ~tender_item.status <= '".$this->tender['searchinfo']['maxtenderstatus']."' ";
		}
		if($this->tender['searchinfo']['tender_quoteid']) {
			$sqlstr.= "AND ~tender_quote.id = '".$this->tender['searchinfo']['tender_quoteid']."' ";
		}
		if($this->tender['searchinfo']['tenderid']) {
			$sqlstr.= "AND ~tender.id = '".$this->tender['searchinfo']['tenderid']."' ";
		}
		if($this->tender['searchinfo']['rfqnumber']) {
			$sqlstr.= "AND ~tender.rfq_number = '".$this->tender['searchinfo']['rfqnumber']."' ";
		}
		if($this->tender['searchinfo']['tenderitemid']) {
			$sqlstr.= "AND ~tender_item.id = '".$this->tender['searchinfo']['tenderitemid']."' ";
		}
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$all = $conn->GetAll($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// Error in tender class
			$this->error[] = "315";
			// response
			return FALSE;
		}
		return $all;
	}
	
	/**
	 * Returns quote information
	 * 
	 * @param integer id quotes ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tenders or FALSE on error  
	 */
	function get_tender_quote($id,$cfg,$conn) {
		if(!$id) {
			// Missing tender quote id
			$this->error[] = "328";
		}
		// errors 
		if(!empty($this->error)) {
			$this->error[] = "317";
			// reponse
			return FALSE;
		}
		$time = date("Y-m-d",ts_time($cfg));
		$sqlstr = "SELECT * ";
		// FROM
		$sqlstr.= "FROM ~tender_quote ";
		// WHERE
		$sqlstr.= "WHERE ~tender_quote.status = 4 ";
		$sqlstr.= "AND ~tender_quote.valid_until >= '".$time."' ";
		$sqlstr.= "AND ~tender_quote.id = '".$id."' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		//$row['description'] = wordwrap($row['description']);
		return $row;
	}
	
	/**
	 * Get Transport fee
	 * 
	 * @param integer id Tender ID
	 * @param integer agent Agent's User ID
	 * @param integer type Transport Type
	 * @param integer user User's ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tenders or FALSE on error  
	 */
	function get_transport($id,$agent,$type,$usersid,$cfg,$conn) {
		$time = date("Y-m-d",ts_time($cfg));
		$this->tender = $id;
		$sqlstr = "SELECT ~tender_quote.id, ~tender_quote.tender_item, ~tender_quote.user_id, ";
		$sqlstr.= "~tender_quote.method, ~tender_quote.brand, ~tender_quote.deleted_by, ";
		$sqlstr.= "~tender_quote.model, ~tender_quote.description, ~tender_quote.quote_message, ";
		$sqlstr.= "~tender_quote.attachment, ~tender_quote.stock, ~tender_quote.valid_until, ";
		$sqlstr.= "~tender_quote.price, ~tender_quote.quote_position, ~tender_quote.created_date, ";
		$sqlstr.= "~tender_quote.created_by, ~tender_quote.status, ~tender_quote.error, ";
		$sqlstr.= "~tender_quote.created_time, ~tender_quote.deleted_date, ~tender_quote.deleted_time ";
		// FROM
		$sqlstr.= "FROM ~tender, ~tender_item, ~tender_quote ";
		// WHERE
		$sqlstr.= "WHERE (~tender_quote.status = 4 OR ~tender_quote.status = 6) ";
		$sqlstr.= "AND ~tender_item.id = ~tender_quote.tender_item ";
		$sqlstr.= "AND ~tender.id = ~tender_item.tender ";
		$sqlstr.= "AND ~tender_quote.valid_until >= '".$time."' ";
		$sqlstr.= "AND ~tender_quote.user_id = '".$agent."' ";
		$sqlstr.= "AND ~tender.id = '".$id."' ";
		$sqlstr.= "AND ~tender_item.classification = '".$type."' ";
		// ORDER BY
		$sqlstr.= "ORDER BY ~tender_item.id DESC, ~tender_quote.status ASC, ~tender_quote.id DESC ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);	
		$row = $conn->GetRow($sqlstr);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		// if already awarded
		if($row['status'] == "6") {
			// create a new one
			$quote['tender_item'] = $row['tender_item'];
			$quote['user_id'] = $row['user_id'];
			$quote['brand'] = $row['brand'];
			$quote['model'] = $row['model'];
			$quote['description'] = $row['description'];
			$quote['attachment'] = $row['attachment'];
			$quote['stock'] = $row['stock'];
			$quote['valid_until'] = $row['valid_until'];
			$quote['price'] = $row['price'];
			$quote['quote_position'] = $row['quote_position'];
			$quote['status'] = "4";
			$quote['created_by'] = $usersid;
			$quote['method'] = "Auto";
			$quote['id'] = $this->create_tender_quote($quote,$cfg,$conn);
			if($quote['id'] === FALSE) {
				// error in award class
				$this->error[] = "317";
				// A SQL error
				return FALSE;
			}
			// response
			return $quote;
		}
		// response
		return $row;
	}
	
		/**
	 * Create a Tender item complete information
	 * 
	 * @param array params Tender item complete information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed Purchase Order ID on Success or FALSE on error  
	 */
	function create_tender_client($params,$cfg,$conn){
		// Check if main parameters exist 
		if (!$params['tender']){
			// Missing tender id
			$this->error[] = "259";
		}
		if (!$params['created_by']) {
			// missing created by
			$this->error[] = "239";
		}
		// errors 
		if (!empty($this->error)) {
			$this->error[] = "260";
			return FALSE;
		}
		if (!isset($params['status'])) {
			$params['status'] = "1";
		}
		if (!$params['address']) {
			$params['address'] = "0";
		}
		if (!$params['id_number']) {
			unset($params['id_number']);
		}
		if (!$params['phone_mobile']) {
			unset($params['phone_mobile']);
		}
		if (!$params['phone_work']) {
			unset($params['phone_work']);
		}
		if (!$params['phone_fax']) {
			unset($params['phone_fax']);
		}
		if (!$params['email']) {
			unset($params['email']);
		}
		if(!$params['phone_prefix']) {
			$params['phone_prefix'] = $cfg['sms']['code'];
		}
		// the table name
		$new_database = new database;
		$table_name = "~tender_client";
		// no id
		if(!$params['id']) {
			// generate an id 
			$params['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		}
		$new_database->setTime("created",$this->tender,"",$cfg);
		$new_database->parse_sql($table_name,$cfg);
		// execute
		$conn->AutoExecute($table_name,$params,"INSERT");
	    if ($conn->ErrorMsg()) {
	    	// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while inserting into database 
			$this->error[] = "1064";
			// response
			return FALSE;
      	}
      	// response
		return $params['id'];
	}
	
	function get_tender_client_info($tenderid,$cfg,$conn) {
		if(!$tenderid) {
			// Missing tender quote id
			$this->error[] = "328";
		}
		// errors 
		if(!empty($this->error)) {
			$this->error[] = "317";
			// reponse
			return FALSE;
		}
		$sqlstr = "SELECT * ";
		// FROM
		$sqlstr.= "FROM ~tender_client ";
		// WHERE
		$sqlstr.= "WHERE ~tender_client.status = 1 ";
		$sqlstr.= "AND ~tender_client.tender = '".$tenderid."' ";
		$sqlstr.= "ORDER BY ~tender_client.id DESC ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$row = $conn->GetRow($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $row;
	}
	
	/**
	 * Send purchase_order to agent
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function send_purchase_order_agent($params,$usersid,$creatorsid,$cfg,$conn) {
		// set paramaters
		$this->user = $params;
		// check if params exist 
		if(!$this->user['language']) {
			// Missing language
			$this->error[] = "101";
		}
		if(!$this->user['id']) {
			// Missing user id
			$this->error[] = "209";
		}
		// errors 
		if(!empty($this->error)) {
			$this->error[] = "317";
			// reponse
			return FALSE;
		}
		$this->user['authentication'] = substr(md5(uniqid(rand())),1,9);
		// include email body template
		$html = $subject = FALSE;
		require($cfg['file'].'modules/procure/templates/purchase_order.php');
		// set message paramaters
		$message['classification'] = "purchase_order";
		$message['subject'] = $subject;
		$message['body'] = $html;
		$message['name'] = $message['reference'] = $this->user['name']." ".$this->user['surname'];
		$message['email'] = $this->user['email'];
		$message['cc'] = $this->user['awarderemail'];
		// instantiate object
		$new_message = new message;
		// send the email
		// set that mail to be stored in database
		$cfg['smtp']['blob'] = TRUE;
		$this->user['message_id'] = $new_message->send_email_message($message,$usersid,$creatorsid,$cfg,$conn);
		if (!$this->user['message_id']) {
			// Message errors 
			$this->error = $new_message->error;
			// Error sending email
			$this->error[] = "202";
			return FALSE;
		}
		$this->user['admin_message_id'] = 0;
		if($this->user['message_id'] && $this->user['mandate_exceeded']) {
			unset($message);
			$html = $subject = FALSE;
			// include email body template
			require($cfg['file'].'modules/procure/templates/mandate_exceeded.php');
			$message['classification'] = "mandate_exceeded";
			$message['subject'] = $subject;
			$message['body'] = $html;
			$message['name'] = $message['reference'] = $this->user['adminname']." ".$this->user['adminsurname'];
			$message['email'] = $this->user['adminemail'];
			$this->user['admin_message_id'] = $new_message->send_email_message($message,$this->user['adminid'],$creatorsid,$cfg,$conn);
			if (!$this->user['admin_message_id']) {
				// Message errors 
				$this->error = $new_message->error;
				// Error sending email
				$this->error[] = "202";
				return FALSE;
			}
		}
		// response
		return $this->user['message_id'];
	}
	
	/**
	 * Send purchase_order cancellation
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function send_purchase_order_cancellation($purchase_order,$agent_info,$subscriber_info,$user,$cfg,$conn) {
		// include the language file
		$lang = array();
		require($cfg['file'].'modules/procure/language/'.$agent_info['language'].'/award.php');
		// set the language
		$this->lang = $lang;
		// include email body template
		$html = $subject = FALSE;
		require($cfg['file'].'modules/procure/templates/purchase_order_cancellation.php');
		// set message paramaters
		$message['classification'] = "purchase_order_cancellation";
		$message['subject'] = $subject;
		$message['body'] = $html;
		$message['name'] = $message['reference'] = $agent_info['name']." ".$agent_info['surname'];
		$message['email'] = $agent_info['email'];
		$message['cc'] = $subscriber_info['email'];
		// instantiate object
		$new_message = new message;
		// send the email
		// set that mail to be stored in database
		$cfg['smtp']['blob'] = TRUE;
		$this->user['message_id'] = $new_message->send_email_message($message,$agent_info['id'],$user['id'],$cfg,$conn);
		if (!$this->user['message_id']) {
			// Message errors 
			$this->error = $new_message->error;
			// Error sending email
			$this->error[] = "202";
			return FALSE;
		}
		// response
		return $this->user['message_id'];
	}
	
	function award_tender($comment,$reason,$user,$cfg,$conn) {
		$message = $this->agent;
		// construct purchase order message
		$message['rfqnumber'] = $this->tender['rfq_number'];
		$message['rfqreference'] = $this->tender['rfq_reference'];
		$message['tenderid'] = $this->tender['id'];
		$message['awardername'] = $this->awarder['name'];
		$message['awardersurname'] = $this->awarder['surname'];
		$message['awarderphone_work'] = $this->awarder['phone_work'];
		$message['awarderphone_fax'] = $this->awarder['phone_fax'];
		$message['awarderemail'] = $this->awarder['email'];
		$message['awarderinfo'] = $this->awarder;
		$message['comment'] = $comment;
		$message['reason'] = $reason;
		// client information
		$client_info = 	$this->get_tender_client_info($this->tender['id'],$cfg,$conn);
		$message['client_title'] = $client_info['title'];
		$message['client_surname'] = $client_info['surname'];
		$message['client_idno'] = $client_info['id_number'];
		$message['client_phone_work'] =$client_info['phone_work'];
		$message['client_phone_mobile'] =$client_info['phone_mobile'];
		$message['client_phone_fax'] =$client_info['phone_fax'];
		$message['client_email'] = $client_info['email'];
		$message['client_address'] = $client_info['address'];
		$message['client_cc'] = $this->client['cc'];
		$message['excess'] = $this->excess;
		$message['assessment_fee'] = $this->assessment_fee;
		$message['collectsalvage'] = $this->collectsalvage;
		// get all the quotes for this agent
		foreach($this->tender_quote as $key1 => $value1) {
			// check if this quote belongs to this agent
			if($value1['user_id'] == $this->agent['id']) {
				// check if the quote belongs to this tender
				if($this->tender_item[$value1['tender_item']]['tender'] == $this->tender['id']) {
					// add quote to messages
					$value1['id'] = $key1;
					$message['tender_item'][] = $value1;
					// create total
					$message['total'] += $value1['price'];
				}
			}
		}
		// check for mandate email
		if($this->awarder['mandate'] < $message['total']) { 
			// send message to admin as well
			$message['mandate_exceeded'] = TRUE;	
			$message['adminname'] = $this->awarder['adminname'];
			$message['adminemail'] = $this->awarder['adminemail'];
			$message['adminsurname'] = $this->awarder['adminsurname'];
			$message['mandatevalue'] = $this->awarder['mandate'];
			$message['adminid']  = $purchase_order['administrator'] = $this->awarder['adminid'];
		}
		// send the purchase order to agents and set supplier message
		$purchase_order['agent_message'] = $this->send_purchase_order_agent($message,$this->agent['id'],$user['id'],$cfg,$conn);
		// purchase order info
		$purchase_order['authentication'] =  $this->user['authentication'];
		$purchase_order['tender'] =  $this->tender['id'];
		if($this->client['message']) {
			$message['client_message'] = $this->client['message'];
			// send message the client
			if($this->client['preference'] == "m") {
				$purchase_order['client_message'] = $this->send_client_email($message,$this->awarder['id'],$user['id'],$cfg,$conn);
			} elseif ($this->client['preference'] == "s") {
				$purchase_order['client_message'] = $this->send_client_sms($message,$this->awarder['id'],$user['id'],$cfg,$conn);
			} elseif ($this->client['preference'] == "ms") {
				$purchase_order['client_message'] = $this->send_client_sms($message,$this->awarder['id'],$user['id'],$cfg,$conn);
				$purchase_order['client_message'] = $this->send_client_email($message,$this->awarder['id'],$user['id'],$cfg,$conn);
			}
		}
		//check to send sms to agent
		if($this->agent['preference'] == "n") {
			$message['reference'] = $message['subject'] = "RFQ:".$message['rfqnumber'];
			$message['phone_mobile'] = $this->agent['phone_mobile'];
			$message['phone_prefix'] = $this->agent['phone_prefix'];
			$message['classification'] = "supplier_sms";
			require($cfg['file'].'modules/procure/language/'.$this->agent['language'].'/award.php');
			$message['body'] = $lang['smspurchaseorder']." ".$message['rfqnumber'];
			$new_message = new message;
			$new_message->send_sms_message($message,$this->agent['id'],$user['id'],$cfg,$conn);
		}
		// set purchase order supplier info
		$purchase_order['agent'] =  $this->agent['id'];
		$purchase_order['user_id'] = $this->awarder['id'];
		// set purchase order excess
		if($message['excess']) {
			$purchase_order['client_excess'] = $message['excess'];
		} else {
			$purchase_order['client_excess'] = "0.00";
		}
		$purchase_order['created_by'] = $user['id'];
		$purchase_order['status'] = "1";
		$purchase_order['id'] = $this->create_purchase_order($purchase_order,$cfg,$conn);
		// add rfq number
		$purchase_order['rfq_number'] = $message['rfqnumber'];
		// add item count
		$purchase_order['count'] = count($message['tender_item']);
		// add items
		$purchase_order['tender_item'] = $message['tender_item'];
		// return purchase order info
		return $purchase_order;
	}
	
		/**
	 * Send email message to client
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function send_client_email($params,$usersid,$creatorsid,$cfg,$conn) {
		// set paramaters
		$this->user = $params;
		// check if params exist 
		if(!$this->user['language']) {
			// Missing language
			$this->error[] = "101";
		}
		if(!$this->user['id']) {
			// Missing user id
			$this->error[] = "209";
		}
		// errors 
		if(!empty($this->error)) {
			$this->error[] = "317";
			// reponse
			return FALSE;
		}
		// include language file
		require($cfg['file'].'modules/procure/language/'.$this->user['language'].'/award.php');
		$html = $subject = FALSE;
		// include email body template
		require($cfg['file'].'modules/procure/templates/client_message.php');
		// set message paramaters
		$message['reference'] = $message['subject'] = $subject;
		$message['body'] = $html;
		$message['name'] = $this->user['client_title']." ".$this->user['client_surname'];
		$message['email'] = $this->user['client_email'];
		$message['classification'] = "client_message";
		// instantiate object
		$new_message = new message;
		// send the email
		$this->user['message_id'] = $new_message->send_email_message($message,$usersid,$creatorsid,$cfg,$conn);
		// response
		return $this->user['message_id'];
	}

	/**
	 * Send sms message to client
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function send_client_sms($params,$usersid,$creatorsid,$cfg,$conn) {
		$this->client['sms'] = FALSE;
		// set paramaters
		$this->user = $params;
		if(!$this->client['done'][$this->user['rfqnumber']]) {
			// check if params exist 
			if(!$this->user['language']) {
				// Missing language
				$this->error[] = "101";
			}
			if(!$this->user['id']) {
				// Missing user id
				$this->error[] = "209";
			}
			// errors 
			if(!empty($this->error)) {
				$this->error[] = "317";
				// reponse
				return FALSE;
			}
			// include language file
			require($cfg['file'].'modules/procure/language/'.$this->user['language'].'/award.php');
			// set message paramaters
			$message['reference'] = $message['subject'] = $lang['rfq'].":".$this->user['rfqnumber']."(".$this->user['rfqreference'].") ".$lang['authorised'];
			$message['body'] = $this->user['client_message'];
			if($cfg['tender']['excess'] && $this->user['excess'] && $this->user['excess'] > 0.009) {
				$message['body'] = $lang['dear']." ".$this->user['client_title']." ".$this->user['client_surname'].", ".$message['body']." ".$lang['pleasenote']." ".$cfg['local']['precurrency'].sprintf("%.2f",$this->user['excess']).$cfg['local']['postcurrency']." ".$lang['payable'].".";
			}
			$message['phone_mobile'] = $this->user['client_phone_mobile'];
			$message['classification'] = "client_sms";
			// instantiate object
			$new_message = new message;
			// send the email
			$this->user['message_id'] = $new_message->send_sms_message($message,$usersid,$creatorsid,$cfg,$conn);
			$this->client['done'][$this->user['rfqnumber']] = $this->user['message_id'];
			$this->client['sms'] = TRUE;
		} else {
			$this->user['message_id'] = $this->client['done'][$this->user['rfqnumber']];
		}
		// response
		return $this->user['message_id'];
	}
	
	/**
	 * Create a purchase Order
	 * 
	 * @param array params Purchase Order Information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed Purchase Order ID on Success or FALSE on error  
	 */
	function create_purchase_order($params,$cfg,$conn){
		// Check if main parameters exist 
		if (!$params['user_id']){
			// Missing user id
			$this->error[] = "209";
		}
		if (!$params['agent']){
			// Missing user id
			$this->error[] = "209";
		}
		if (!$params['tender']){
			// missing tender id
			$this->error[] = "259";
		}
		if (!$params['authentication']){
			// Missing authentication
			$this->error[] = "210";
		}
		if (!$params['created_by']) {
			// missing created by
			$this->error[] = "239";
		}
		// errors 
		if (!empty($this->error)) {
			$this->error[] = "260";
			return FALSE;
		}
		// the table name
		$new_database = new database;
		$table_name = "~purchase_order";
		// no id
		if(!$params['id']) {
			// generate an id 
			$params['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		}
		$new_database->setTime("created",$params,"",$cfg);
		$new_database->parse_sql($table_name,$cfg);
		// execute
		$conn->AutoExecute($table_name,$params,"INSERT");
	    if ($conn->ErrorMsg()) {
	    	// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while inserting into database 
			$this->error[] = "1064";
			// response
			return FALSE;
      	}
      	// response
		return $params['id'];
	}
	
	/**
	 * create a valid item
	 * 
	 * @param integer supplier the supplier id
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed item id on success or FALSE otherwise
	 *   
	 */
	function create_valid_item($supplier,$item,$cfg,$conn) {
		// get the next id 
		$new_database = new database;
		$table_name = "~item";
		$table_id = $new_database->get_next_id($table_name,$cfg,$conn);
		if (!$table_id) {
			// set the errors
			$this->error = $new_database->error;
			// response
			return FALSE;
		}// set the time
		$timestamp = ts_time($cfg);
		// insert the items in the database
		$insert = array(
			'id'			=> $table_id,
			'supplier'		=> $supplier,
			'category_sub'	=> $item['subcat'],
			'brand'			=> $item['brand'],
			'model'			=> $item['model'],
			'description'	=> $item['description'],
			'stock'			=> $item['stock'],
			'price'			=> $item['price'],
			'status'		=> "1",
			'created_by'	=> $this->tender['user']['id']
		);
		if($item['attachment']) {
			$insert['attachment'];
		}
		if($item['valid_until']) {
			$insert['valid_until'] = $item['valid_until'];
		}
		if($item['valid']) {
			$insert['valid_until'] = date("Y-m-d",$timestamp + $item['valid']*86400);
		}
		$new_database->setTime("created",$insert,"",$cfg);
		$new_database->parse_sql($table_name,$cfg);
		// execute the query
 		$conn->AutoExecute($table_name,$insert,"INSERT");
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	}
		// response
		return $table_id;
	}
	
	function check_tender_complete(&$xml_params,$lock_tender,$cfg,$conn) {
		// make sure is an array
		if(is_numeric($lock_tender)) {
			$lock_tender = array($lock_tender);
		}
		// check if tender completed
		$info['searchinfo']['tender_id'] = array_unique($lock_tender);
		$item_count = $this->get_tender_complete_info($info,$cfg,$conn);
		// check for complete tenders
		foreach($item_count as $key => $value) {
			// check if it has a close on time and add if missing
			$timestamp = ts_time($cfg);
			$updatetender['update']['close_date'] = date("Y-m-d",$timestamp);
			$updatetender['update']['close_time'] = date("H:i:s",$timestamp);
			$updatetender['where'] = " id = ".$key." AND close_date is NULL ";
			$this->update_tender($updatetender['update'],$updatetender['where'],$cfg,$conn);
			unset($updatetender['update']);
			// check if completed
			if($value['status_avg'] != "6") {
				$updatetender['update']['status'] = "4";
			} else {
				// set complete time
				$timestamp = ts_time($cfg);
				$updatetender['update']['status'] = "6";
				$updatetender['update']['complete_date'] = date("Y-m-d",$timestamp);
				$updatetender['update']['complete_time'] = date("H:i:s",$timestamp);
			}
			$updatetender['where'] = " id = ".$key." ";
			$this->update_tender($updatetender['update'],$updatetender['where'],$cfg,$conn);
		}
	}
	
	/**
	 * Get tender complete information
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function get_tender_complete_info($params,$cfg,$conn) {
		$this->tender = $params;
		$sqlstr = "SELECT ~tender.id, avg(~tender_item.status) AS status_avg  ";
		// FROM
		$sqlstr.= "FROM ~tender, ~tender_item ";
		// WHERE
		$sqlstr.= "WHERE ~tender.status = 5 ";
		$sqlstr.= "AND ~tender.id = ~tender_item.tender ";
		$sqlstr.= "AND ~tender_item.classification = 1 ";
		$sqlstr.= "AND ~tender_item.status > 1 ";
		if(is_array($this->tender['searchinfo']['tender_id'])) {
			$notfirst = FALSE;
			foreach($this->tender['searchinfo']['tender_id'] as $key => $value) {
				if($value) {
					if($notfirst) {
						$sqlstr.= "OR ~tender.id = ".$value." ";	
					} else {
						$sqlstr.= "AND ( ~tender.id = ".$value." ";
						$notfirst = TRUE;
					}
				}
			}
			if($notfirst) {
				$sqlstr.= ") ";
			}
		}
		// GROUP BY
		$sqlstr.= "GROUP BY ~tender.id ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$all = $conn->GetAssoc($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL: ".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		return $all;
	}
	
	/**
	 * Set tender status to 5
	 * 
	 * @param integer id Tender ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function lock_tender($id,$cfg,$conn) {
		// Check if main parameters exist 
		if (!$id){
			// missing tender id
			$this->error[] = "259";
		}
		// errors 
		if(!empty($this->error)){
			// Error in Tender Class
			$this->error[] = "317";
			return FALSE;
		}
		// the table name
		$table_name = "~tender";
		$where = " id = ".$id." ";
		$where.= " AND status = 4 ";
		$update['status'] = "5";
		$new_database = new database;
		$new_database->parse_sql($table_name,$cfg);
		// execute
 		$conn->AutoExecute($table_name,$update,"UPDATE",$where);
	    if ($conn->ErrorMsg()) {
	    	// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while updating information on database
			$this->error[] = "1066";
			// response
			return FALSE;
      	}
      	return TRUE;
	}
	
	function area_available($organisation,$cfg,$conn) {
		if ($cfg['procure']['supplier']['required']) {
			// Query database to find out provinces and areas
	      	$sqlstr = "SELECT DISTINCT ~area.id AS areaid, ~area.name AS areaname, ~area.name, ";
	      	$sqlstr.= "state.id AS stateid ";
			$sqlstr.= "FROM ~area_state state, ~area, ~area_supplier, ";
			$sqlstr.= "~organisation_supplier, ~organisation supplier ";
			$sqlstr.= "WHERE state.status = '1' ";
			$sqlstr.= "AND state.id = ~area.state ";
			$sqlstr.= "AND ~area.status = '1' ";
			$sqlstr.= "AND ~area.id = ~area_supplier.area ";
			$sqlstr.= "AND ~area_supplier.status = '1' ";
			$sqlstr.= "AND ~area_supplier.supplier = supplier.id ";
			$sqlstr.= "AND supplier.status = '1' ";
			$sqlstr.= "AND supplier.id = ~organisation_supplier.supplier "; 
			$sqlstr.= "AND ~organisation_supplier.status = '1' ";
			$sqlstr.= "AND ~organisation_supplier.organisation = '".$organisation."' ";
			$sqlstr.= "ORDER BY ~area.name ASC, ~area.id ASC ";
			$new_database = new database;
			$new_database->parse_sql($sqlstr,$cfg);
			$all = $conn->GetAll($sqlstr);
	        if ($conn->ErrorMsg()) {
				// instantiate the error class and log
				$new_error = new error;
				$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
				$new_error->log("SQL","critical",$error_text,$cfg);
				// set the response error
				$this->error[] = "1065";
				// response
				return FALSE;
	        } 
		} else {
			// instantiate object
			$new_area = new area;
			$all = $new_area->search(array(),$cfg,$conn);
		}
	    return $all;
	}
	
	function state_available($organisation,$cfg,$conn) {
		if ($cfg['procure']['supplier']['required']) {
			// Query database to find out provinces and areas
	      	$sqlstr = "SELECT DISTINCT state.id AS stateid, state.name AS statename ";
			$sqlstr.= "FROM ~area_state state, ~area, ~area_supplier, ";
			$sqlstr.= "~organisation_supplier, ~organisation supplier ";
			$sqlstr.= "WHERE state.status = '1' ";
			$sqlstr.= "AND state.id = ~area.state ";
			$sqlstr.= "AND ~area.status = '1' ";
			$sqlstr.= "AND ~area.id = ~area_supplier.area ";
			$sqlstr.= "AND ~area_supplier.status = '1' ";
			$sqlstr.= "AND ~area_supplier.supplier = supplier.id ";
			$sqlstr.= "AND supplier.status = '1' ";
			$sqlstr.= "AND supplier.id = ~organisation_supplier.supplier "; 
			$sqlstr.= "AND ~organisation_supplier.status = '1' ";
			$sqlstr.= "AND ~organisation_supplier.organisation = '".$organisation."' ";
			$sqlstr.= "ORDER BY state.name ASC, state.id ASC ";
			$new_database = new database;
			$new_database->parse_sql($sqlstr,$cfg);
			$all = $conn->GetAll($sqlstr);
	        if ($conn->ErrorMsg()) {
				// instantiate the error class and log
				$new_error = new error;
				$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
				$new_error->log("SQL","critical",$error_text,$cfg);
				// set the response error
				$this->error[] = "1065";
				// response
				return FALSE;
	        } 
		} else {
			// instantiate object
			$new_area = new area;
			$all = $new_area->search_state(array(),$cfg,$conn);
		}
	    return $all;
	}
	
	/**
	 * get all the quotes associated with a item
	 * 
	 * @param integer item_id tender item ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function remove_duplicates($item_id,$cfg,$conn) {
		// check if all quotes must be kept
		if($cfg['procure']['quote']['duplicate']['keep'] == 'a') {
			return TRUE;
		}
		// get all the items associated with the tender item
		$sqlstr = "SELECT DISTINCT ~tender_quote.id, ~tender_quote.user_id, ~tender_quote.price, ";
		$sqlstr.= "~tender_quote.brand, ~tender_quote.model, ~tender_quote.description ";
		$sqlstr.= "FROM ~tender_quote ";
		$sqlstr.= "WHERE ~tender_quote.tender_item = '".$item_id."' ";
		$sqlstr.= "AND ~tender_quote.status != '0' ";
		$sqlstr.= "ORDER BY ~tender_quote.user_id ASC ";
		if($cfg['procure']['quote']['duplicate']['keep'] == 'f') {
			$sqlstr.= ", ~tender_quote.id ASC ";
		} elseif($cfg['procure']['quote']['duplicate']['keep'] == 'l') {
			$sqlstr.= ", ~tender_quote.id DESC ";
		} elseif($cfg['procure']['quote']['duplicate']['keep'] == 'i') {
			$sqlstr.= ", ~tender_quote.price ASC ";
		} elseif($cfg['procure']['quote']['duplicate']['keep'] == 'e') {
			$sqlstr.= ", ~tender_quote.price DESC ";
		}
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		$all = $conn->GetAll($sqlstr);
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	} elseif (!$all) {
			// no quotes
			return FALSE;
       	} 
       	$check_id = array();
       	$update['status'] = "0";
		$update['error'] = $this->default_lang['duplicate'];
		// go through all quotes
       	foreach($all as $key => $value) {
       		// create check id
       		if($cfg['procure']['quote']['duplicate']['compare'] == '1') {
       			$check_id = md5($value['user_id'].$value['brand'].$value['model']);
       		} elseif($cfg['procure']['quote']['duplicate']['compare'] == '2') {
       			$check_id = md5($value['user_id'].$value['brand'].$value['model'].$value['price']);
       		} elseif($cfg['procure']['quote']['duplicate']['compare'] == '3') {
       			$check_id = md5($value['user_id'].$value['brand'].$value['model'].$value['description']);
       		} elseif($cfg['procure']['quote']['duplicate']['compare'] == '4') {
       			$check_id = md5($value['user_id'].$value['brand'].$value['model'].$value['description'].$value['price']);
       		}
       		if($exist[$check_id]) {
				// delete quote
				$update_quote = $this->update_quote($value['id'],$update,$cfg,$conn);
       		} else {
       			// quote exists
				$exist[$check_id] = TRUE;
       		}
       	}
		return TRUE;
	}
	
	/**
	 * get all the quotes associated with a item
	 * 
	 * @param integer item_id tender item ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender_information or FALSE on error  
	 */
	function calculate_position($item_id,$cfg,$conn) {
		// get all the items associated with the tender item
		$sqlstr = "SELECT DISTINCT ~tender_quote.id, ~tender_quote.user_id, ~tender_quote.price, ";
		$sqlstr.= "~tender_quote.brand, ~tender_quote.model, ~tender_quote.description, ";
		$sqlstr.= "~tender_quote.stock, ~tender_quote.valid_until ";
		$sqlstr.= "FROM ~tender_quote ";
		$sqlstr.= "WHERE ~tender_quote.tender_item = '".$item_id."' ";
		$sqlstr.= "AND ~tender_quote.status != '0' ";
		$sqlstr.= "AND ~tender_quote.status != '1' ";
		if($cfg['procure']['quote']['position']['primary'] == 'p') {
			$sqlstr.= "ORDER BY ~tender_quote.price ASC ";
		} elseif($cfg['procure']['quote']['position']['primary'] == 't') {
			$sqlstr.= "ORDER BY ~tender_quote.id ASC ";
		} elseif($cfg['procure']['quote']['position']['primary'] == 's') {
			$sqlstr.= "ORDER BY ~tender_quote.stock ASC ";
		} elseif($cfg['procure']['quote']['position']['primary'] == 'v') {
			$sqlstr.= "ORDER BY ~tender_quote.valid_until DESC ";
		}
		if($cfg['procure']['quote']['position']['secondary'] == 'p') {
			$sqlstr.= ", ~tender_quote.price ASC ";
		} elseif($cfg['procure']['quote']['position']['secondary'] == 't') {
			$sqlstr.= ", ~tender_quote.id ASC ";
		} elseif($cfg['procure']['quote']['position']['secondary'] == 's') {
			$sqlstr.= ", ~tender_quote.stock ASC ";
		} elseif($cfg['procure']['quote']['position']['secondary'] == 'v') {
			$sqlstr.= ", ~tender_quote.valid_until DESC ";
		}
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		$all = $conn->GetAll($sqlstr);
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1065";
			// response
			return FALSE;
       	} elseif (!$all) {
			// no quotes
			return FALSE;
       	}
		// go through all quotes
       	foreach($all as $key => $value) {
			// set position
			$update['quote_position']++;
			$where = "id = ".$value['id'];
			$update_quote = $this->update_tender_quote($update,$where,$cfg,$conn);
       	}
		return TRUE;
	}
}
?>