<?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 request 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_response extends procure {
	
	function procure_response() {
		// allow php5 to work
		$this->error = array();	
	}
	
	/**
	 * checks if tender can be closed
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE if yes or FALSE if no  
	 */
	function check_agent_profile($params,$user,$cfg,$conn) {
		// instantiate object
		$new_user = new user;
		// find out for whom the tender is being requested
		if($user['classification'] == "3" || ($params['usersid'] && $params['usersid'] != $user['id'])) {
			// get the details on who's behalf tender requested
			$this->agent = $new_user->get_profile($params['usersid'],$cfg,$conn);
		} else {
			// set that normal user requesting tender
			$this->agent = $new_user->get_profile($user['id'],$cfg,$conn);
		}
		if($this->agent['classification'] == "1") {
			return TRUE;
		} else {
			// instantiate error object
			$new_error = new error;
			include($cfg['file']."modules/procure/language/".$cfg['language']."/procure_error.php");
			// log error
			$error_text = $lang['unauthorisedrequest'].$user['id']." (".$user['name']." ".$user['surname'].") ";
			$error_text.= $lang['foruserid'].$this->agent['id']." (".$this->agent['name']." ".$this->agent['surname'].") ";
			$new_error->log("Procure","mild",$error_text,$cfg);
			// not authorised to perform request
			$this->error[] = "52";
			return FALSE;
		}
	}
	
	/**
	 * search for tender request
	 * 
	 * @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_request($params,$cfg,$conn) {
		$this->tender = $params;
		$sqlstr = "SELECT ~tender.id AS tenderid, ~tender.rfq_number, ~tender.status, ";
		$sqlstr.= "~tender.close_date, ~tender.close_time, ~tender.created_date, ";
		$sqlstr.= "~tender.created_time, ";
		$sqlstr.= "~users.id AS usersid,  ";
		$sqlstr.= "~area.name AS areaname, ";
		$sqlstr.= "state.name AS statename, ";
		$sqlstr.= "COUNT(~tender_item.id) AS itemcount ";
		// FROM
		$sqlstr.= "FROM ~tender_request, ~tender, ~tender_item, ~users, ~area, ~area_state state ";
		// WHERE
		$sqlstr.= "WHERE ~tender_request.status = '1' ";
		$sqlstr.= "AND ~tender_request.tender_item = ~tender_item.id ";
		$sqlstr.= "AND ~tender_item.tender = ~tender.id ";
		$sqlstr.= "AND ~tender.user_id = ~users.id ";
		$sqlstr.= "AND (~users.status = '1' OR  ~users.status = '2') ";
		$sqlstr.= "AND ~tender.area = ~area.id ";
		$sqlstr.= "AND ~area.state = state.id ";
		if($this->tender['searchinfo']['agentid']) {
			$sqlstr.= "AND ~tender_request.user_id = '".$this->tender['searchinfo']['agentid']."' ";
		}
		if($this->tender['searchinfo']['tenderitemid']) {
			$sqlstr.= "AND ~tender_request.tender_item = '".$this->tender['searchinfo']['tenderitemid']."' ";
		}
		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']['tenderclassification']) {
			$sqlstr.= "AND ~tender.classification = '".$this->tender['searchinfo']['tenderclassification']."' ";
		}
		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']."' ";
		}
		// GROUP BY
		$sqlstr.= "GROUP BY ~tender.id, ~users.id, ~area.name, ";
		$sqlstr.= "~tender.status, ~tender.rfq_number, ~tender.close_date, ";
		$sqlstr.= "~tender.close_time, ~tender.created_date, ~tender.created_time,";
		$sqlstr.= "state.name ";
		// ORDER BY
		$sqlstr.= "ORDER BY ~tender.close_date ASC, ~tender.close_time ASC, ~tender.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;
		}
		// change time to proper format
		$new_database->convertTime($all,$cfg);
		// response
		$new_users = new user;
		foreach($all as $key => $value) {
			$users_info = $new_users->get_info($value['usersid'],$cfg,$conn);
			$all[$key]['name'] = $users_info['name'];
			$all[$key]['surname'] = $users_info['surname'];
			$all[$key]['phone_prefix'] = $users_info['phone_prefix'];
			$all[$key]['email'] = $users_info['email'];
			$all[$key]['phone_work'] = $users_info['phone_work'];
		}
		return $all;
	}
	
	function find_tender_items(&$xml_params,$params,$classification,$cfg,$conn) {
		// check for a tender id
		$info['searchinfo']['tenderid'] = $params['id'];
		$info['searchinfo']['tenderitemid'] = $params['tenderitem'];
		$info['searchinfo']['rfqnumber'] = $params['rfqnumber'];
		if(!$params['tenderitem']) {
			$info['searchinfo']['tenderstatus'] = "2";
		} 
		$info['searchinfo']['tenderclassification'] = $classification;
		$info['searchinfo']['agentid'] = $this->agent['id'];
		$tenders = $this->search_request($info,$cfg,$conn);
		$tenderitems = $this->search_tender_item($info,$cfg,$conn);
		if(!$params['tenderitem']) {
			$tenderquotes = $this->search_quote($info,$cfg,$conn);
		} else {
			$tenderquotes = array();
		}
		// go through each item and check if already quoted for
		foreach($tenderitems as $item) {
			$done = FALSE;
			// check if there is already a quote for it
			foreach($tenderquotes as $quote) {
				if($item['id'] == $quote['tender_item']) {
				    // found a quote
					$done = TRUE;
					// break out of it
					break;
				}
			}
			if(!$done) {
				$needtender[] = $item['tender'];
				$xml_params['tenderitems'][] = $item;
			}
		}
		if(is_array($needtender)) {
			array_unique($needtender);
			foreach($tenders as $tender) {
				if(in_array($tender['tenderid'],$needtender)) {
					$xml_params['tenders'][] = $tender;
				}
			}
		}
		$xml_params['usersid'] = $this->agent['id'];
	}
	
	function load_tender_quotes(&$xml_params,$params,$classification,$user,$cfg,$conn) {
		$new_file = new file;
		foreach($params['item'] as $key => $value) {
			if(!$params['file'][$value['id']]['error'] && isset($params['file'][$value['id']])) {
				// set file paramaters
				$upload['name'] = $params['file'][$value['id']]['name'];
				$upload['content'] = $params['file'][$value['id']]['content'];
				// upload the file to the database	
				$params['item'][$key]['attachment'] = $new_file->file_upload($upload,$user['id'],$cfg,$conn);
			}
		}
		
		$response['item'] = $params['item'];
		$response['user'] = $this->agent;
		$response['submitter']['id'] = $user['id'];
		$response['method'] = "internet";
		$tender_quotes = $this->proses_response($response,$cfg,$conn);
		foreach($tender_quotes['item'] as $quote) {
			if($quote['status'] == "0") {
				$xml_params['tenderitems'][] =  $quote;
				$needtender[] = $quote['tender'];
			} else {
				$xml_params['quoted'][] = $quote;
			}
		}
		if(is_array($needtender)) {
			array_unique($needtender);
			// check for a tender id
			$info['searchinfo']['tenderstatus'] = "2";
			$info['searchinfo']['tenderclassification'] = $classification;
			$info['searchinfo']['agentid'] = $this->agent['id'];
			$tenders = $this->search_request($info,$cfg,$conn);
			foreach($tenders as $tender) {
				if(in_array($tender['tenderid'],$needtender)) {
					$xml_params['tenders'][] = $tender;
				}
			}
		}
		$xml_params['usersid'] = $this->agent['id'];
	}
	
	function add_tender_quotes(&$xml_params,$params,$classification,$user,$cfg,$conn) {
		$new_file = new file;
		foreach($params['item'] as $key => $value) {
			if(!$params['file'][$value['id']]['error'] && isset($params['file'][$value['id']])) {
				// set file paramaters
				$upload['name'] = $params['file'][$value['id']]['name'];
				$upload['content'] = $params['file'][$value['id']]['content'];
				// upload the file to the database	
				$params['item'][$key]['attachment'] = $new_file->file_upload($upload,$user['id'],$cfg,$conn);
			}
		}
		$timestamp = ts_time($cfg);
		foreach($params['item'] as $key => $value) {
			$tender_item = $this->get_tender_item($value['id'],$cfg,$conn);
			$tender_quote['tender_item'] = $value['id'];
			$tender_quote['classification'] = "1";
			$tender_quote['user_id'] = $params['usersid'];
			$tender_quote['method'] = "internet";
			$tender_quote['brand'] = $value['brand'];
			$tender_quote['model'] = $value['model'];
			$tender_quote['description'] = $value['description'];
			$tender_quote['attachment'] = $value['attachment'];
			$tender_quote['stock'] = $value['stock'];
			$tender_quote['valid_until'] = date("Y-m-d",$timestamp + $value['valid_until']*86400);
			$tender_quote['price'] = $value['price'];
			$tender_quote['status'] = $tender_item['status'];
			$tender_quote['id'] = $this->create_tender_quote($tender_quote,$cfg,$conn);
			if($tender_quote['id']) {
				$xml_params['quoted'][] = $tender_quote;
			}
			if($tender_item['status'] == "4") {
				//remove duplicates
				$this->remove_duplicates($tender_item['id'],$cfg,$conn);	
				// calculate quote positions
				$this->calculate_position($tender_item['id'],$cfg,$conn);
			}
		}
		$xml_params['usersid'] = $this->agent['id'];
	}
	
	function set_language($module,$language,$cfg,$conn) {
		// include the language file
		$lang = array();
		require($cfg['file'].'modules/procure/language/'.$language.'/response.php');
		if($module) {
			require($cfg['file'].'modules/'.$module.'/language/'.$language.'/response.php');
		}
		// set the language
		$this->lang = $lang;
	}
	
	/**
	 * get status of tender item
	 * 
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE on success and FALSE on failure
	 *   
	 */
	function determine_status($tender_item,$cfg,$conn) {
		// query db to find out if closing date has been reached
		$sqlstr = "SELECT ~tender.id AS tender_id, ~tender.user_id, ~tender.rfq_number, ";
		$sqlstr.= "~tender.area, ~tender.attachment, ~tender.status AS tender_status, ";
		$sqlstr.= "~tender.close_date, ~tender.close_time, ~tender.rfq_reference ";
		$sqlstr.= "FROM ~tender_item, ~tender ";
		$sqlstr.= "WHERE ~tender_item.id = '".$tender_item."' ";
		$sqlstr.= "AND ~tender_item.tender = ~tender.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;
       	} elseif (!$row) {
			// no RFQ could be found
			$this->error_text.= $this->lang['norfq'];
			// response
			return FALSE;
       	} else {
			// set repsonse
			
			$this->tender['id'] = $row['tender_id'];
			$this->tender['rfq_number'] = $row['rfq_number'];
			$this->tender['rfq_reference'] = $row['rfq_reference'];
			$tender_status = $row['tender_status'];
			// determine if the tender is still open
			if ($tender_status != "2") {
				// response
				return FALSE;
			} else {
				// NOTE: Quote can be submitted untill RFQ has been processed even if close time has been reached
				// This may cause an error if RFQ is processed while quote is processed as no table locking is done.
				// RFQ process should however only be triggered after quote has been submitted.
				$this->tender['tender_check'][] = $row['tender_id'];
				return TRUE;			
			}
		}
	}
	
	/**
	 * get sub category of an tender item
	 * 
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE if all quoted or FALSE otherwise
	 *   
	 */
	function get_subcategory($tender_item,$cfg,$conn) {
		// query db to find out if closing date has been reached
		$sqlstr = "SELECT category_sub ";
		$sqlstr.= "FROM ~tender_item ";
		$sqlstr.= "WHERE  id = '".$tender_item."' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		$one = $conn->GetOne($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;
       	} 
       	// response
		return $one;
	}
	
	/**
	 * checks if all suppliers have quoted
	 * 
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param boolean TRUE if all quoted or FALSE otherwise
	 *   
	 */
	function all_quoted($cfg,$conn) {
		// SELECT
		$sqlstr = "SELECT ~tender_item.id, ";
		$sqlstr.= "COUNT(DISTINCT supplier.id) AS request_count  ";
		// FROM
		$sqlstr.= "FROM ~tender_request, ~organisation supplier, ~users agent,  ";
		$sqlstr.= "~tender_item  ";
		// WHERE
		$sqlstr.= "WHERE ~tender_item.tender = '".$this->tender['id']."' ";
		$sqlstr.= "AND ~tender_request.tender_item = ~tender_item.id ";
		$sqlstr.= "AND ~tender_item.status = 2 ";
		$sqlstr.= "AND ~tender_request.status = 1 ";
		$sqlstr.= "AND ~tender_request.user_id = agent.id ";
		$sqlstr.= "AND agent.status != 0 ";
		$sqlstr.= "AND agent.organisation = supplier.id ";
		$sqlstr.= "AND supplier.status != 0 ";
		// GROUP BY
		$sqlstr.= "GROUP BY ~tender_item.id ";
		// ORDER BY
		$sqlstr.= "ORDER BY ~tender_item.id ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$request_assoc = $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;
		}
		// SELECT
		$sqlstr = "SELECT ~tender_item.id, ";
		$sqlstr.= "COUNT(DISTINCT supplier.id) AS quote_count  ";
		// FROM
		$sqlstr.= "FROM ~tender_quote, ~organisation supplier, ~users agent,  ";
		$sqlstr.= "~tender_item  ";
		// WHERE
		$sqlstr.= "WHERE ~tender_item.tender = '".$this->tender['id']."' ";
		$sqlstr.= "AND ~tender_quote.tender_item = ~tender_item.id ";
		$sqlstr.= "AND ~tender_item.status = 2 ";
		$sqlstr.= "AND ~tender_quote.status = 2 ";
		$sqlstr.= "AND ~tender_quote.user_id = agent.id ";
		$sqlstr.= "AND agent.status != 0 ";
		$sqlstr.= "AND agent.organisation = supplier.id ";
		$sqlstr.= "AND supplier.status != 0 ";
		// GROUP BY
		$sqlstr.= "GROUP BY ~tender_item.id ";
		// ORDER BY
		$sqlstr.= "ORDER BY ~tender_item.id ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$quote_assoc = $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;
		}
		// check if all item complete
		foreach($request_assoc as $key => $value) {
			if($request_assoc[$key]['request_count'] != $quote_assoc[$key]['quote_count']) {
				// quoting not done
				return FALSE;	
			}
		}
		// all quoted
		return TRUE;
	}
	
		/**
	 * update tender status
	 * 
	 * @param integer tender_id Tender ID
	 * @param string/integer status tender status
	 * @param string error_text Error Text
	 * @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 update_tender_status($tender_id,$status,$error_text,$cfg,$conn) {
		$new_database = new database();
		// update the database
		if ($status == "0") {
			$update = array(
				'status'		=> "0",
				'error'			=> $error_text
			);
			$new_database->setTime("close",$update,"",$cfg);
		} elseif ($status == "close") {
			$update = array(
				'status'		=> "2",
			);
			$new_database->setTime("close",$update,ts_time($cfg) + $cfg['tender']['close']['time'],$cfg);
		} elseif ($status == "quote") {
			$update = array(
				'status'		=> "2",
			);
			$close_time = $this->get_closing_time($cfg.$conn);
			$time_setting = str_replace(array("!","^","#"),"",$cfg['tender']['quote']['close']);
			if(strpos($cfg['tender']['quote']['close'],"!") && $close_time) { // increase time
				$new_database->setTime("close",$update,$close_time + $time_setting,$cfg);	
			} elseif(strpos($cfg['tender']['quote']['close'],"^" && $close_time)) { // decrease time
				if($close_time - $cfg['tender']['close']['time'] > ts_time($cfg)) {
					$new_database->setTime("close",$update,$close_time - $cfg['tender']['close']['time'],$cfg);
				} else {
					$new_database->setTime("close",$update,ts_time($cfg),$cfg);
				}
			} elseif(strpos($cfg['tender']['quote']['close'],"#")) { // set time left
				$new_database->setTime("close",$update,ts_time($cfg) + $cfg['tender']['close']['time'],$cfg);
			} else {
				return TRUE;
			}
		} else {
			$update['status'] = $status;
		}
		// if tender status 
		$where.= " id = '".$tender_id."'";
		if($this->update_tender($update,$where,$cfg,$conn)) {
			return TRUE;
		} else {
			// error in Request Class
			$this->error[] = "314";
			return FALSE;
		}
	}
	
	function get_closing_time($cfg,$conn) {
		// SELECT
		$sqlstr = "SELECT close_date, close_time ";
		// FROM
		$sqlstr.= "FROM ~tender ";
		// WHERE
		$sqlstr.= "WHERE ~tenderid = '".$this->tender['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;
		}elseif(!$row) {
			return FALSE;
		}
		list($year,$month,$day) = sscanf(str_replace(array("-"," "),"",$row['close_date']),'%4s%2s%2s');
		list($hour,$minute,$second) = sscanf(str_replace(array(":"," "),"",$row['close_time']),'%2s%2s%2s');
		return mktime($hour,$minute,$second,$month,$day,$year);
	}
}
?>