<?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_request extends procure {
	
	function procure_request() {
		// 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_subscriber_info($params,$user,$cfg,$conn) {
		// instantiate object
		$new_user = new user;
		// find out for whom the tender is being requested
		if($user['classification'] == "3" || ($params['procure']['userid'] && $params['procure']['userid'] != $user['id'])) {
			// get the details on who's behalf tender requested
			$this->subscriber = $new_user->get_info($params['procure']['userid'],$cfg,$conn);
		} elseif($user['classification'] == "1" || ($params['procure']['userid'] && $params['procure']['userid'] != $user['id'])) {
			$new_organisation = new supplier;
			// get all company on company panel
			$panel = $new_organisation->search_panel($user['organisation'],$cfg,$conn);
			// get the details on who's behalf tender requested
			$this->subscriber = $new_user->get_info($params['procure']['userid'],$cfg,$conn);
			// check if subscriber is on panel
			foreach($panel as $key => $value) {
				
				if($value['organisationid'] == $this->subscriber['organisation']) {
					$onpanel = TRUE;
					break;
				}
			}
			// if not on panel
			if(!$onpanel) {
				$this->subscriber['classification'] = FALSE;
			}
		} else {
			// set that normal user requesting tender
			$this->subscriber = $user;
		}
		if($this->subscriber['classification'] == "2") {
			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->subscriber['id']." (".$this->subscriber['name']." ".$this->subscriber['surname'].") ";
			$new_error->log("Tender","mild",$error_text,$cfg);
			// not authorised to perform request
			$this->error[] = "52";
			return FALSE;
		}
	}
	
	/**
	 * 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_subscriber_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['procure']['userid'] && $params['procure']['userid'] != $user['id'])) {
			// get the details on who's behalf tender requested
			$this->subscriber = $new_user->get_profile($params['procure']['userid'],$cfg,$conn);
		} elseif($user['classification'] == "1" || ($params['procure']['userid'] && $params['procure']['userid'] != $user['id'])) {
			$new_organisation = new supplier;
			// get all company on company panel
			$panel = $new_organisation->search_panel($user['organisation'],$cfg,$conn);
			// get the details on who's behalf tender requested
			$this->subscriber = $new_user->get_profile($params['procure']['userid'],$cfg,$conn);
			// check if subscriber is on panel
			foreach($panel as $key => $value) {
				if($value['organisationid'] == $this->subscriber['organisation']) {
					$onpanel = TRUE;
					break;
				}
			}
			// if not on panel
			if(!$onpanel) {
				$this->subscriber['classification'] = FALSE;
			}
		} else {
			// set that normal user requesting tender
			$this->subscriber = $new_user->get_profile($user['id'],$cfg,$conn);
		}
		if($this->subscriber['classification'] == "2") {
			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->subscriber['id']." (".$this->subscriber['name']." ".$this->subscriber['surname'].") ";
			$new_error->log("Tender","mild",$error_text,$cfg);
			// not authorised to perform request
			$this->error[] = "52";
			return FALSE;
		}
	}
	
	/**
	 * 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_attachment(&$params,$user,$cfg,$conn) {
		// determine if file is present
		if (is_array($params['procure']['attachment']) && $params['procure']['attachment']['name'] && $params['procure']['attachment']['content']) {
			// set file paramaters
			$upload['name'] = $params['procure']['attachment']['name'];
			$upload['content'] = $params['procure']['attachment']['content'];
			unset($params['procure']['attachment']);
			// upload the file to the database	
			$new_file = new file;
			$this->attachment = $new_file->file_upload($upload,$user['id'],$cfg,$conn);
		}
	}
	
	function get_commodity_template($user,$cfg) {
		// set variables
		$xml_array = array();
		$index = array();
		$commodity = array();
		// set the filename
		$filename = $cfg['file']."/modules/tender/language/".$user['language']."/commodity.xml";
		if (file_exists($filename)) {
			$xml_content = file_get_contents($filename);
			// create parser
			$xml_parser = xml_parser_create();
			// parse xml into $xml_array
			$good_parse = xml_parse_into_struct($xml_parser, $xml_content, $xml_array);
			// free parser
			xml_parser_free($xml_parser);
			if($good_parse) {
				// set counter
				$counter = 0;
				// loop through the structures
				foreach ($xml_array as $key=>$val) {
					if ($val['tag'] == "NAME" && $val['type'] == "complete") {
						$commodity['item'][$counter]['name'] = $val['value'];
					}
					if ($val['tag'] == "VALUE" && $val['type'] == "complete") {
						$commodity['item'][$counter]['value'] = $val['value'];
					}
					if ($val['tag'] == "ITEM" && $val['type'] == "close") {
						// increment counter
						$counter++;
					}
				}
				return $commodity;
			} else {
				return FALSE;
			}
		} else {
			return FALSE;
		}
	}
	
	function get_product_template($filename,&$xml_params,$user,$cfg,$conn,$xml_array=array(),$index=array()) {
		$xml_content = file_get_contents($filename);
		// create parser
		$xml_parser = xml_parser_create();
		// parse xml into $xml_array
		$good_parse = xml_parse_into_struct($xml_parser, $xml_content, $xml_array, $index);
		// free parser
		xml_parser_free($xml_parser);
		$count = 0;
		if($good_parse) {
			$xml_params['product_name'] = $xml_array[$index['NAME'][0]]['value'];
			// determine if it is a commodity product
			if ($xml_array[$index['COMMODITY'][0]]['value'] == "TRUE") {
				$xml_params['commodity'][0] = $this->get_commodity_template($user,$cfg);
			}
			$template = $xml_array[$index['TEMPLATE'][0]]['value'];
			// category sub
			if($xml_array[$index['CATEGORY_SUB'][0]]['type'] == "complete") {
				$xml_params['category_sub_hidden'] = $xml_array[$index['CATEGORY_SUB'][0]]['value'];
			} else {
				// find the options
				for($i = $index['CATEGORY_SUB'][0]; $i < end($index['CATEGORY_SUB']); $i++) {
					if($xml_array[$i]['tag'] == "NAME") {
						$category_sub['subcategoryname'] = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "ID") {
						$category_sub['subcategoryid'] = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "OPTION" && $xml_array[$i]['type'] == "close") {
						$category_sub_available = $this->category_sub_available($category_sub['id'],$params['area'],"1",$cfg,$conn);
						if(!empty($category_sub_available) || !$cfg['procure']['supplier']['required']) {
							$xml_params['category_sub'][] = $category_sub;
						}
						unset($category_sub);
					}
				}
			}
			// additional description
			if($index['ADDITIONAL_DESCRIPTION']) {
				for($i = $index['ADDITIONAL_DESCRIPTION'][0]; $i <= end($index['ADDITIONAL_DESCRIPTION']); $i++) {
					if($xml_array[$i]['tag'] == "ADDITIONAL_DESCRIPTION" && $xml_array[$i]['type'] == "open") {
						$add_des['count'] = ++$count;
						$add_des['type'] = strtolower($xml_array[$i]['attributes']['TYPE']);
					}
					if($xml_array[$i]['tag'] == "QUESTION") {
						$add_des['question'] = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "VALUE") {
						$add_des['value'] = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "PREPEND") {
						$add_des['prepend'] = $prepend = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "DEFAULT") {
						$option['default'] = "1";
					}
					if($xml_array[$i]['tag'] == "OPTVALUE") {
						if($xml_array[$i]['value']) {
							$option['value'] = $prepend.$xml_array[$i]['value'];
						}
					}
					if($xml_array[$i]['tag'] == "NAME") {
						$option['name'] = $xml_array[$i]['value'];
					}
					if($xml_array[$i]['tag'] == "OPTION" && $xml_array[$i]['type'] == "close") {
						$add_des['option'][] = $option;
						unset($option);
					}
					if($xml_array[$i]['tag'] == "ADDITIONAL_DESCRIPTION" && $xml_array[$i]['type'] == "close") {
						$xml_params['add_des'][] = $add_des;
						unset($add_des);
					}
				}
			}
			$xml_params['category_hidden'] = $xml_array[$index['CATEGORY'][0]]['value'];
			$xml_params['product'] = $params['product'];
			// look for quick products
			if(is_array($index['QUICK_PRODUCTS'])) {
				foreach($index['QUICK_PRODUCTS'] as $value) {
					if($xml_array[$value]['type'] == "open") {
						$quick_product['name'] = $xml_array[$value]['attributes']['NAME'];
						$open_index = $value;
					}
					if($xml_array[$value]['type'] == "close") {
						$close_index = $value;
						for($i = $open_index + 1; $i < $close_index - 1; $i++) {
							if($xml_array[$i]['tag'] == "BRAND") {
								$item['brand'] = $xml_array[$i]['value'];
							}
							if($xml_array[$i]['tag'] == "MODEL") {
								$item['model'] = $xml_array[$i]['value'];
							}
							if($xml_array[$i]['tag'] == "DESCRIPTION") {
								$item['description'] = $xml_array[$i]['value'];
							}
							if($xml_array[$i]['type'] == "close" && $xml_array[$i]['tag'] == "ITEM") {
								$quick_product['item'][] = $item;
								unset($item);
							}
						}
						$xml_params['quick_product'][] = $quick_product;
						unset($quick_product);
					}
				}
			}
		} else {
			return FALSE;	
		}
		$sinfo['searchinfo']['categoryid'] = $xml_params['category'];
		$new_category = new category;
		$xml_params['brand'] = $new_category->search_brand($sinfo,$cfg,$conn);
		return TRUE;
	}
	
	/**
	 * creates a new tender
	 * 
	 * @param array tender The Tender infromation
	 * @param array user The subscriber information
	 * @param array request The requestors information
	 * @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 prepare_procure_request($classification,$cfg,$conn) {
		if($cfg['procure']['auto']['rfq']['enable'] && $cfg['procure']['auto']['rfq']['setting']) {
			$new_user = new user;
			$user_info = $new_user->get_info($user['id'],$cfg,$conn);
			$this->tender['rfq_number'] = $this->generate_rfq_number($cfg,$conn);
		}
		//set to default
		$this->tender['classification'] = $classification;
		if (!$this->tender['rfq_number']) {
			// RFQ Number is missing
			$this->error[] = "1003";
		}
		if (!$this->tender['rfq_reference']) {
			// RFQ Reference is missing
			$this->error[] = "1004";
		}
		if (!$this->tender['area']) {
			// Area ID is missing
			$this->error[] = "1005";
		}
		if(!is_array($this->tender['item'])) {
			// Missing Items 
			$this->error[] = "1027";
		}
		if (!empty($this->error)) {
			// Error in procure_request class
			$this->error[] = "1028";
			// response
			return FALSE;
		} 
		//set reponse fields
		$this->response = $this->tender;
		// no items
		unset($this->response['item']);
		if ($this->subscriber['id'] != $this->requester['id']) {
			// set required response fields
			$this->response['subscriber'][0]['id'] = $this->subscriber['id'];
			$this->response['subscriber'][0]['name'] = $this->subscriber['name'];
			$this->response['subscriber'][0]['surname'] = $this->subscriber['surname'];
			$this->response['subscriber'][0]['organisationname'] = $this->subscriber['organisationname'];
			$this->response['subscriber'][0]['branchname'] = $this->subscriber['branchname'];
		}
		// calculate closing time
		$this->calculate_closure($cfg);
		// get the state and area
		$this->get_area_info($cfg,$conn);
		// create the tender
		if (!$this->create_tender($cfg,$conn)) {
			// Error in procure_request class
			$this->error[] = "1028";
			$conn->CompleteTrans(FALSE);
			// response
			return FALSE;
		}
		// initiate the items
		if (!$this->initiate_items($cfg,$conn)) {
			// Error in procure_request class
			$this->error[] = "1028";
			// response
			return FALSE;
		}
		if (!empty($this->error)) {
			// response
			return FALSE;
		} 
		// response
		return TRUE;
	}
	
	function set_language($module,$cfg) {
		// include the language file
		$lang = array();
		require($cfg['file'].'modules/procure/language/'.$this->requester['language'].'/request.php');
		if($module) {
			require($cfg['file'].'modules/'.$module.'/language/'.$this->requester['language'].'/request.php');
		}
		// set the language
		$this->lang = $lang;
		// include the default language file
		$lang = array();
		require($cfg['file'].'modules/procure/language/'.$cfg['language'].'/request.php');
		if($module) {
			require($cfg['file'].'modules/'.$module.'/language/'.$cfg['language'].'/request.php');
		}
		// set the language
		$this->default_lang = $lang;
	}
	
	/**
	 * update an tender item
	 *
	 * @param array item update information Tender ID
 	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of generic products on success or FALSE on error
	 */
	function generate_rfq_number($cfg,$conn) {
		$rfq_number = $cfg['procure']['auto']['rfq']['setting'];
		$search = array("[u]","[ui]","[b]","[bi]","[o]","[oi]","[d]","[di]","[uu]","[ti]","[bb]","[ii]","[oo]","[ts]");
		// username
		$replace[] = $this->subscriber['username'];
		// Tender User Increment
		$sqlstr = "SELECT COUNT(~tender.id) as tender_count ";
		$sqlstr.= "FROM ~tender ";
		$sqlstr.= "WHERE ~tender.user_id = ".$this->subscriber['id']." ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// branch name
		$new_branch = new branch;
		$branch_info = $new_branch->get_info($this->subscriber['branch'],$cfg,$conn);
		if(!empty($new_branch->error)) {
			$this->error = array_merge($this->error,$new_branch->error);
		}
		$replace[] = $branch_info['name'];
		// Tender Branch Increment
		$sqlstr = "SELECT COUNT(~tender.id) as tender_count ";
		$sqlstr.= "FROM ~tender, ~users ";
		$sqlstr.= "WHERE ~tender.user_id = ~users.id ";
		$sqlstr.= "AND ~users.branch = ".$this->subscriber['branch'];
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// Organisation name
		$new_organisation = new branch;
		$organisation_info = $new_organisation->get_info($this->subscriber['organisation'],$cfg,$conn);
		if(!empty($new_organisation->error)) {
			$this->error = array_merge($this->error,$new_organisation->error);
		}
		$replace[] = $organisation_info['name'];
		// Tender Organisation Increment
		$sqlstr = "SELECT COUNT(~tender.id) as tender_count ";
		$sqlstr.= "FROM ~tender, ~users ";
		$sqlstr.= "WHERE ~tender.user_id = ~users.id ";
		$sqlstr.= "AND ~users.organisation = ".$this->subscriber['organisation'];
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// Date
		$stamp = ts_time($cfg);
		$replace[] = date($cfg['date']['format'],$stamp);
		// Tender Date Increment
		$sqlstr = "SELECT COUNT(~tender.id) as tender_count ";
		$sqlstr.= "FROM ~tender ";
		$sqlstr.= "WHERE ~tender.created_date = '".date("Y-m-d",$stamp)."' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// user id
		$replace[] = $this->subscriber['id'];
		// Tender ID
		$sqlstr = "SELECT MAX(~tender.id) as tender_max ";
		$sqlstr.= "FROM ~tender ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// branch id
		$replace[] = $this->subscriber['branch'];
		// Tender Item ID
		$sqlstr = "SELECT MAX(~tender_item.id) as tender_max ";
		$sqlstr.= "FROM ~tender_item ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$replace[] = $conn->GetOne($sqlstr) + 1;
		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";
		}
		// organisation id
		$replace[] = $this->subscriber['organisation'];
		// unix time stamp
		$replace[] = $stamp;
		// do zero padding and replacing
		return $this->zeropad(str_replace($search,$replace,$rfq_number));
	}
	
	function zeropad($value) {
		$start_pos = strpos($value,"zeropad(");
		if($start_pos !== FALSE)  {
			if($start_pos > 0) {
				$value_start = substr($value,0,$start_pos);
			} else {
				$value_start = "";
			}
			$value_pad = substr($value,$start_pos+8);
			// do internal zero padding
			$mid_pos = strpos($value_pad,")length(");
			$end_pos = strpos($value_pad,")",$mid_pos+7);
			if($mid_pos !== FALSE || $end_pos !== FALSE) {
				$value_end = substr($value_pad,$end_pos + 1);
				$pad_value = substr($value_pad,0,$mid_pos);
				$pad_length = substr($value_pad,$mid_pos+8,$end_pos - $mid_pos - 8);
				return $this->zeropad($value_start.str_pad($pad_value,$pad_length,"0",STR_PAD_LEFT).$value_end);
			} else {
				return $value_start."zeropad(".$value_pad;
			}
		} else {
			return $value;
		}
	}
	
	/**
	 * get the state and area names
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *  
	 */
	function get_area_info($cfg,$conn) {
		$new_area = new area;
		$this->response['area'] = $this->tender['areaname'] = $new_area->get_area_name($this->tender['area'],$cfg,$conn);
		$this->response['state'] = $this->tender['statename'] = $new_area->get_state_name_by_area($this->tender['area'],$cfg,$conn);
	}
	
	/**
	 * create Tender
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed tender id on success or FALSE on error  
	 */
	function create_tender($cfg,$conn) {
		// get the next id 
		$new_database = new database;
		$table_name = "~tender";
		$insert['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		if (!$insert['id']) {
			// set the errors
			$this->error = $new_database->error;
			// response
			return FALSE;
		}
		// set insert values
		$insert['classification'] = $this->tender['classification'];
		$insert['user_id'] = $this->subscriber['id'];
		$insert['rfq_number'] = $this->tender['rfq_number'];
		$insert['rfq_reference'] = $this->tender['rfq_reference'];
		$insert['area'] = $this->tender['area'];
		if($this->tender['transport']) {
			$insert['transport'] = $this->tender['transport'];
		} else {
			$insert['transport'] = "0";
		}
		$insert['created_by'] = $this->requester['id'];
		$new_database->setTime("created",$insert,"",$cfg);
		if($this->attachment) {
			$insert['attachment'] = $this->attachment;
		}
		if (!empty($this->error)) {
			foreach ($this->error as $value) {
				$error_text.= $value." ";
			};
			$insert['status'] = "0";
			$insert['error'] = $error_text;
			$new_database->setTime("close",$insert,"",$cfg);
		} else {
			$insert['error'] = "";
			$insert['status'] = "1";
			$insert['close_date'] = $this->tender['closing']['date'];
			$insert['close_time'] = $this->tender['closing']['time'];
		}
		// execute the query
		$new_database->parse_sql($table_name,$cfg);
 		$recordSet = $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;
       	}
		// set the tender id
		$this->response['id'] = $this->tender['id'] = $insert['id'];
		// response
		return TRUE;
	}
	
	/**
	 * proses the tender information
	 *
	 * @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 process_tender($cfg,$conn) {
		// get the state and area
		if(!$this->response['area']) {
			$this->get_area_info($cfg,$conn);
		}
		if($cfg['procure']['approve']['enable']) {
			// create a tender for approval
			if($cfg['procure']['approve']['email']) {
				// get all the items that must be approved
				$this->response['item'] = $this->get_items($this->tender['id'],"1",$cfg,$conn);
				if(!$this->response['item']) {
					return FALSE;
				}
				// get agent info
				if(!$this->get_admin_info($cfg,$conn)) {
					return FALSE;
				}
				// send aprrove email
				if(!$this->send_approve_emails($cfg,$conn)) {
					return FALSE;
				}
			}
			$this->response['awaiting_approval'] = "1";
		} else {
			// do the actually request
			if(!$this->do_request($cfg,$conn)) {
				// response
				return FALSE;	
			}
		}
		// response
		return TRUE;
	}
	
	/**
	 * get agent information
	 *
	 * @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 get_agent_info($cfg,$conn) {
		$this->agent = $this->get_tender_agents($this->tender['area'],$this->subscriber['organisationid'],$cfg,$conn);
		if($new_agent->error) {
			return FALSE;	
		}
		return TRUE;
	}
	
	/**
	 * Get all agents that quote in a certain area and for a certain company
	 * 
	 * @param integer area AREA ID
	 * @param integer company Company's Organisation ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param array   
	 */
	function get_tender_agents($area,$company,$cfg,$conn) {
		// determine if area id is present
		if (!$area) {
			// no area could be found
			$this->error[] = "36";
			// Error in Agent class 
			$this->error[] = "311";
			return FALSE;
		}
		$sqlstr = "SELECT DISTINCT ~users.id, ~users.name, ~users.surname, ";
		$sqlstr.= "~users.phone_mobile, ~users.email, ~users.preference, ";
		$sqlstr.= "~users.language, ~users.status, ~users.organisation AS supplierid ";
		$sqlstr.= "FROM ~users, ~organisation, ~organisation_branch, ~area_supplier, ~organisation_supplier ";
		$sqlstr.= "WHERE ~users.status > 0 ";
		$sqlstr.= "AND ~users.classification = '1' ";
		$sqlstr.= "AND ~users.organisation = ~organisation.id ";
		$sqlstr.= "AND ~organisation.status = '1' ";
		$sqlstr.= "AND ~users.branch = ~organisation_branch.id ";
		$sqlstr.= "AND ~organisation_branch.status = '1' ";
		$sqlstr.= "AND ~organisation.id = ~area_supplier.supplier ";
		$sqlstr.= "AND ~organisation.id = ~organisation_supplier.supplier ";
		$sqlstr.= "AND ~organisation_supplier.organisation = '".$company."' ";
		$sqlstr.= "AND ~area_supplier.status = '1' ";
		$sqlstr.= "AND ~organisation_supplier.status = '1' ";
		$sqlstr.= "AND ~area_supplier.area = '".$area."' ";
		$sqlstr.= "ORDER BY ~users.id ASC ";
		$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;
       	}
		// return user info
		return $all;
	}
	
	/**
	 * get all administrators
	 *
	 * @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 get_admin_info($cfg,$conn) {
		$new_user = new user;
		$info['searchinfo']['classification'] = "3";
		$this->admin = $new_user->search($info,$cfg,$conn);
		if(!empty($new_user->error)) {
			return FALSE;	
		}
		return TRUE;
	}
	
	/**
	 * update an tender
	 *
	 * @param integer tender_id  Tender ID
	 * @param string/integer status tender status 
	 * @param string error_text Errors
 	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of generic products on success 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);
		} else {
			$update['status'] = $status;
		}
		// if tender status 
		$where.= " id = '".$tender_id."'";
		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_request class
			$this->error[] = "1028";
			return FALSE;
		}
		return TRUE;
	}
	
	/**
	 * finds the items thats needs approval
	 *
	 * @param array tender Tender ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed message id on success or FALSE on error  
	 */
	function get_items($tender,$status,$cfg,$conn) {
		$sqlstr = "SELECT DISTINCT ~tender_item.id, ~tender_item.brand, ~tender_item.model, ";
		$sqlstr.= "~tender_item.description, ~tender_item.classification, ~tender_item.quote,   ";
		$sqlstr.= "~tender_item.budget,   ";
		$sqlstr.= "~category_sub.name AS category_sub, ~category.id AS categoryid, ";
		$sqlstr.= "~category.name AS category, ~category_sub.id AS category_subid  ";
		$sqlstr.= "FROM ~tender_item, ~category, ~category_sub ";
		if($status) {
			$sqlstr.= "WHERE ~tender_item.status = '".$status."' ";
		} else {
			$sqlstr.= "WHERE ~tender_item.status != '0' ";
		}
		$sqlstr.= "AND ~tender_item.category_sub = ~category_sub.id ";
		$sqlstr.= "AND ~category_sub.category = ~category.id ";
		$sqlstr.= "AND ~tender_item.tender = '".$tender."' ";
		$sqlstr.= "ORDER BY ~tender_item.classification ASC, ~category.name ASC, ~category_sub.name ASC ";
		$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()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// An SQL error occurred while querying the database
			$this->error[] = "1030";
			// Error in Procure class 
			$this->error[] = "1029";
			// response
			return FALSE;
       	}
       	if(count($all) > 1) {
       		foreach($all as $key => $value) {
       			$all[$key]['description'] = wordwrap($value['description']);
       		}	
       	}
		// return user info
		return $all;
	}
	
	function get_item_count($tender,$status,$cfg,$conn) {
		$sqlstr = "SELECT COUNT(~tender_item.id) ";
		$sqlstr.= "FROM ~tender_item ";
		if($status) {
			$sqlstr.= "WHERE ~tender_item.status = '".$status."' ";
		} else {
			$sqlstr.= "WHERE ~tender_item.status != '0' ";
		}
		$sqlstr.= "AND ~tender_item.tender = '".$tender."' ";
		$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()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// An SQL error occurred while querying the database
			$this->error[] = "1030";
			// response
			return FALSE;
       	}
       	return $one;
	}
	
	/**
	 * set status of items and tender to open
	 *
	 * @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 ready_items($cfg,$conn) {
		$update['status'] = '2';
		$where = "status = '1' AND tender = ".$this->tender['id'];
		// set item status
		if(!$this->update_tender_item($update,$where,$cfg,$conn)) {
			// Error in tender_request Class
			$this->error[] = "e53";
			return FALSE;	
		}
		$item_count = $this->get_item_count($this->tender['id'],"2",$cfg,$conn);
		
		if($item_count > 0) {
			// set tender status
			if(!$this->update_tender_status($this->tender['id'],"2","",$cfg,$conn)) {
				return FALSE;	
			}
		} else {
			// delete tender because there are not items
			if(!$this->update_tender_status($this->tender['id'],"0",$this->default_lang['notenderitems'],$cfg,$conn)) {
				return FALSE;	
			}	
		}
		return $item_count;
	}
	
	/**
	 * calculates the closure of a tender
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 *
	 * @param mixed TRUE on success or FALSE on error  
	 */
	function calculate_closure($cfg) {
		// set the closing date and time
		$this->tender['closing']['time'] = "";
		$this->tender['closing']['date'] = "";
	}
	
	/**
	 * create all the items for the tender
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed message id on success or FALSE on error  
	 */
	function initiate_items($cfg,$conn) {
		// loop through every item and validate and upload
		foreach ($this->tender['item'] as $key => $value) {
			// determine if type is present
			if (!$value['classification']) {
				// set to default i.e. RFQ
				$value['classification'] = "1";
			}
			// validate fields
			if (!$value['category_sub']) {
				// set response error text
				$value['error'].= $this->lang['nosubcat'];
			}
			if (!$value['brand']) {
				// set response error text
				$value['error'].= $this->lang['nobrand'];
			}
			if (!$value['model']) {
				// set response error text
				$value['error'].= $this->lang['nomodel'];
			}
			if (!$value['description']) {
				// set response error text
				$value['error'].= $this->lang['nodes'];
			}
			// set the status
			if ($value['error']) {
				// invalid item
				$value['status'] = "0";
			} else {
				// valid item
				$value['status'] = "1";
			}
			// set db array
			$item['tender'] = $this->tender['id'];
			$item['classification'] = $value['classification'];
			$item['category_sub'] = $value['category_sub'];
			$item['brand'] = $value['brand'];
			$item['model'] = $value['model'];
			$item['description'] = $value['description'];
			$item['quote'] = $value['quote'];
			$item['budget'] = $value['budget'];
			if($value['error']) {
				$item['error'] = $value['error'];
			}
			$item['status'] = $value['status'];
			$item['created_by'] = $this->requester['id'];
			// create item
			$value['id'] = $this->create_tender_item($item,$cfg,$conn);
			$this->tender['item'][$key] = $value;
		}
		// response
		return TRUE;
	}
	
	/**
	 * send sms notification to agent
	 *
	 * @param array agent agent information
	 * @param array items the tender items
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed message id on success or FALSE on error  
	 */
	function send_sms_notification($agent,$items,$sms_message,$cfg,$conn) {
		// include email body template
		$subject = "";
		$html = "";
		// set message paramaters
		$message['reference'] = $this->tender['rfq_number'];
		$message['classification'] = "tender";
		$message['body'] = $this->lang['newtendersms']." (".$this->tender['rfq_number'].")";
		if ($sms_message) {
	 		// load sms notification settings
	 		require($cfg['file'].'/modules/tender/config.inc.php');
	 		// set message paramaters
			//remove comma at end of sms message and add full stop
			$sms_message = substr($sms_message, 0, strlen($sms_message)-2).".";
			$message['body'] .= " ".$this->lang['for']." ".$sms_message;
			// find position of last comma
			$pos = strrpos($message['body'], ", ");
			// insert and
			$message['body'] = substr($message['body'], 0, $pos)." and ".substr($message['body'], $pos + 2);
			// determine the body length
			$message_units = strlen($message['body'])/156;
			// check to determine if longer than allowed
			if ($message_units > $cfg['tender']['smslimit']) {
				// set allowable length
				$allowable_length = ($cfg['tender']['smslimit'] * 156)-2;
				// truncate if longer than allowed 
				$message['body'] = substr($message['body'], 0, $allowable_length)."..";
			}	
		}
		$message['name'] = $agent['name']." ".$agent['surname'];
		$message['phone_mobile'] = $agent['phone_mobile'];
		$message['phone_prefix'] = $agent['phone_prefix'];
		// send the email
		$new_message = new message;
		$id = $new_message->send_sms_message($message,$agent['id'],$this->requester['id'],$cfg,$conn);
		if(!$id) {
			$this->email_error = $new_message->error_text;
			return FALSE;
		}
		return $id;
	}
	
	/**
	 * create a tender request
	 *
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of items or FALSE on error  
	 */
	function create_request($request,$cfg,$conn) {
		// get the next id
		$new_database = new database;
		$table_name = "~tender_request";
		$request['id'] = $new_database->get_next_id($table_name,$cfg,$conn);
		if (!$request['id']) {
			// set the errors
			$this->error = $new_database->error;
			// response
			return FALSE;
		}
		// insert the items in the database
		$new_database->setTime("created",$request,"",$cfg);
		// execute the query
		$new_database->parse_sql($table_name,$cfg);
 		$conn->AutoExecute($table_name,$request,"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 TRUE;
	}
	
	/**
	 * sends approval emails to administrators
	 *
	 * @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 send_approve_emails($cfg,$conn) {
		// go throught each administrator
		foreach($this->admin as $key => $value) {
			if($value['preference'] == "n" || $value['preference'] == "m") {
				$message_id = $this->send_email_approve($value,$this->response['item'],$cfg,$conn);
			}
		}
		// finnish
		return TRUE;
	}
}
?>