<?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): __________________.                                                   |
// +---------------------------------------------------------------------------------------+

/**
* Response class
* @package TenderSystem
* @subpackage tender
* @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 tender_response extends procure_response {
	// set the paramaters
	var $email;
	var $tender;
	var $response;
	var $error;
	
	function tender_response() {
		// allow php5 to work
		$this->error = array();	
	}
	
	/**
	 * proses email responses
	 * 
	 * @param array the quote responses
	 * @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 proses_response($response,$cfg,$conn) {
		// set the paramater
		$this->tender = $response;
		// determine if required fields present
		if (!$this->tender['user']['id']) {
			// set error text and error 
			$error_text = "User ID not present for response. ";
			$this->error[] = "209";
		}
		// submitter id
		if (!$this->tender['submitter']['id']) {
			// set error text and error 
			$error_text.= "Submitter ID not present for response. ";
			$this->error[] = "209";
		}
		// determine method
		if (!$this->tender['method']) {
			$error_text.= "No tender method provided.";
			$this->error[] = "294";
		}
		if ($error_text) {
			// if any items are present submit
			if (is_array($this->tender['item'])) {
				// loop through 
				foreach($this->tender['item'] as $key => $value) {
					$error_text.= "Tender ID:".$value['id']."(";
					$error_text.= "Brand:".$value['brand'];
					$error_text.= ", Model:".$value['model'];
					$error_text.= ", Des:".$value['description'];
					$error_text.= ", Valid:".$value['valid'];
					$error_text.= ", Stock:".$value['stock'];
					$error_text.= ", Price:".$value['price'];
					$error_text.= ") ";
				}			
			}
			// log the error
			$new_error = new error;
			$new_error->log("Response","critical",$error_text,$cfg);
			// response
			return FALSE;
		}
		// include the language file
		$this->set_language("tender",$this->tender['user']['language'],$cfg,$conn);
		// if any attachments upload
		if ($this->tender['attachment']) {
			// loop through
			$new_file = new file;
			foreach ($this->tender['attachment'] as $key => $value) {
				if(is_numeric($key) && $this->tender['item'][$key]) {
					// set file paramaters
					$upload['name'] = $value['name'];
					$upload['content'] = $value['body'];
					// upload the file to the database	
					$this->tender['item'][$key]['attachment'] = $new_file->file_upload($upload,$this->tender['submitter']['id'],$cfg,$conn);
					
				}
			}
		}
		// loop through every item filter and then insert
		for ($i = 0; $i < count($this->tender['item']); $i++) {
			// item must be numeric
 			$this->tender['item'][$i]['id'] = preg_replace('/[^0-9]/','',$this->tender['item'][$i]['id']);
 			if (!$this->tender['item'][$i]['id']) {
 				// error message
 				$this->tender['item'][$i]['error'][] = $this->lang['noitem'];
 				// set status
 				$this->tender['item'][$i]['status'] = "0";
 			} else {
				// determine if tender is still open
				$this->tender['open'] = $this->determine_status($this->tender['item'][$i]['id'],$cfg,$conn);
				// get the sub category - used to determine and upload valid items
				$this->tender['item'][$i]['subcat'] = $this->get_subcategory($this->tender['item'][$i]['id'],$cfg,$conn);
				// set the error that the tender is already closed
				if (!$this->tender['open']) {
					// error message
					$this->tender['item'][$i]['error'][] = $this->lang['rfq']." ".$this->tender['rfq_number']." ".$this->lang['rfqclosed'];
					// set status
					$this->tender['item'][$i]['status'] = "2";
					$this->tender['item'][$i]['quoteclass'] = "5";
				}
			}
			// classification must be numeric
			$this->tender['item'][$i]['classification'] = preg_replace('/[^0-9]/','',$this->tender['item'][$i]['classification']);
			if (!$this->tender['item'][$i]['classification']) {
				// set type to default
				$this->tender['item'][$i]['classification'] = "1";
			}
			// convert brand || BRAND -> Brand
			$this->tender['item'][$i]['brand'] = ucfirst(strtolower($this->tender['item'][$i]['brand']));
			if (!$this->tender['item'][$i]['brand']) {
				// set error brand
				$this->tender['item'][$i]['brand'] = $this->lang['nobrand'];
				// error message
				$this->tender['item'][$i]['error'][] = $this->lang['nobrand'];
				// set status
				$this->tender['item'][$i]['status'] = "0";
			}
			// uppercase model
			$this->tender['item'][$i]['model'] = strtoupper($this->tender['item'][$i]['model']);
			if (!$this->tender['item'][$i]['model']) {
				// set the model
				$this->tender['item'][$i]['model'] = $this->lang['nomodel'];
				// error message
				$this->tender['item'][$i]['error'][] = $this->lang['nomodel'];
				// set status
				$this->tender['item'][$i]['status'] = "0";
			} elseif ($this->tender['item'][$i]['model'] == "ENTRY") {
				// set the model
				$this->tender['item'][$i]['model'] = $this->lang['invalidmodel'];
				// error message
				$this->tender['item'][$i]['error'][] = $this->lang['invalidmodel'];
				// set status
				$this->tender['item'][$i]['status'] = "0";		
			}
			// description - no changes
			if (!$this->tender['item'][$i]['description']) {
				// set the description
				$this->tender['item'][$i]['description'] = $this->lang['nodes'];
				// error message
				$this->tender['item'][$i]['error'][] = $this->lang['nodes'];
				// set status
				$this->tender['item'][$i]['status'] = "0";
			}
			// valid must be numeric
			$this->tender['item'][$i]['valid'] = preg_replace('/[^0-9]/','',$this->tender['item'][$i]['valid']);
			if (!$this->tender['item'][$i]['valid'] || $this->tender['item'][$i]['valid'] < $cfg['tender']['validity']['minimum']) {
				// set to minimum allowable period
				$this->tender['item'][$i]['valid'] = $cfg['tender']['validity']['minimum'];
			}
			// stock may be IM for immediate
			if ($this->tender['item'][$i]['stock'] == "IM") {
				$this->tender['item'][$i]['stock'] = "0";
			} else {
				// stock must be numeric
				$this->tender['item'][$i]['stock'] = preg_replace('/[^0-9]/','',$this->tender['item'][$i]['stock']);
				if (!$this->tender['item'][$i]['stock'] && $this->tender['item'][$i]['stock'] !== "0") {
					// error message
					$this->tender['item'][$i]['error'][] = $this->lang['nostock'];
					// set status
					$this->tender['item'][$i]['status'] = "0";
				}
			}
			// price can contain nq for no quote
			$this->tender['item'][$i]['price'] = strtolower($this->tender['item'][$i]['price']);
			// replace o with 0 - error that occurs many times
			$this->tender['item'][$i]['price'] = str_replace(array("o","O"),"0",$this->tender['item'][$i]['price']);
			// change .. || - || , to .
			$dots_to_replace = array("..","-",",");
			$this->tender['item'][$i]['price'] = str_replace($dots_to_replace,".",$this->tender['item'][$i]['price']);
			$this->tender['item'][$i]['price'] = str_replace(" ","",$this->tender['item'][$i]['price']);
			// determine if it is a no quote - sometimes suppliers also insert n/q
			if (strpos($this->tender['item'][$i]['price'],"nq") === FALSE && strpos($this->tender['item'][$i]['price'],"n/q") === FALSE) {
				// strip all text
				$this->tender['item'][$i]['price'] = preg_replace('/[^0-9,.]/','',$this->tender['item'][$i]['price']);
				// determine if stock 0.00 when normal RFQ
				if ($this->tender['item'][$i]['classification'] == "1") {
					if ($this->tender['item'][$i]['price'] == "0.00" || $this->tender['item'][$i]['price'] == "0.0" || $this->tender['item'][$i]['price'] == "0") {
						// set the price
						$this->tender['item'][$i]['price'] = "0.00";
						// error message
						$this->tender['item'][$i]['error'][] = $this->lang['quotemaybe']." ".$cfg['local']['precurrency']."0.00".$cfg['local']['postcurrency']." ".$this->lang['exceptfortransport'];
						// set status
						$this->tender['item'][$i]['status'] = "0";
					} elseif (!$this->tender['item'][$i]['price']) {
						// set the price
						$this->tender['item'][$i]['price'] = "0.00";
						// error message
						$this->tender['item'][$i]['error'][] = $this->lang['noprice'];
						// set status
						$this->tender['item'][$i]['status'] = "0";
					} else {
						// format the price t #.##
						$this->tender['item'][$i]['price'] = sprintf("%.2f",$this->tender['item'][$i]['price']);
					}
				} else {
					// type 3 = deliver || type 4 = install
					if (!$this->tender['item'][$i]['price']) {
						// set the price
						$this->tender['item'][$i]['price'] = "0.00";
						// error message
						$this->tender['item'][$i]['error'][] = $this->lang['noprice'];
						// set status
						$this->tender['item'][$i]['status'] = "0";
					}
				}
			} else {
				// no quote
				$this->tender['item'][$i]['error'][] = $this->lang['noquote'];
				$this->tender['item'][$i]['price'] = "0.00";
				// check if it was a late quote
				if($this->tender['item'][$i]['quoteclass'] == "5") {
					// ignore no quote
					unset($this->tender['item'][$i]['error']);
					continue;
				} 
				// no quote
				$this->tender['item'][$i]['quoteclass'] = "4";
			}
			// set the status
			if (isset($this->tender['item'][$i]['status']) && $this->tender['item'][$i]['status'] !== "1") {
				// log the errors
				$error_text = "Response error from ".$this->tender['user']['name']." ".$this->tender['user']['surname']." for ".$this->tender['rfq_number'];
				$error_text.= "Reason: ".$this->tender['logtext'];
				foreach ($this->tender['item'][$i]['error'] as $value) {
					$error_text.= $value;
				}
				$error_text.= "Tender ID:".$this->tender['item'][$i]['id']."(";
				$error_text.= "Brand:".$this->tender['item'][$i]['brand'];
				$error_text.= ", Model:".$this->tender['item'][$i]['model'];
				$error_text.= ", Des:".$this->tender['item'][$i]['description'];
				$error_text.= ", Valid:".$this->tender['item'][$i]['valid'];
				$error_text.= ", Stock:".$this->tender['item'][$i]['stock'];
				$error_text.= ", Price:".$cfg['local']['precurrency'].$this->tender['item'][$i]['price'].$cfg['local']['postcurrency'];
				$error_text.= ") ";
				$new_error = new error;
				$new_error->log("Response","serious",$error_text,$cfg);
				// if response was received by email
				if ($this->tender['method'] == "email") {
					// set variables
					$row_item = $this->tender['item'][$i];
					// include row template
					$html = FALSE;
					require($cfg['file'].'modules/tender/templates/error_row.php');
					// set paramater
					$this->tender['user']['row'].= $html;
				} else {
					$this->tender['user']['row'] = TRUE;
				}
			} else {
				// check if no quote
				if($this->tender['item'][$i]['status'] !== "1") {
					// set to successfull 
					$this->tender['item'][$i]['status'] = "2";
				}
				// if valid item insert active
				if ($cfg['tender']['validity']['status'] && $this->tender['item'][$i]['quoteclass'] != "4") {
					// insert valid item
					$create_item = $this->create_valid_item($this->tender['user']['organisationid'],$this->tender['item'][$i],$cfg,$conn);
				}
			}
			// set insert paramaters
			$timestamp = ts_time($cfg);
			$insert = array (
				'id'			=> $this->tender['item'][$i]['id'],
				'user_id'		=> $this->tender['user']['id'],
				'method'		=> $this->tender['method'],
				'quote_message'	=> $this->tender['messageid'],
				'brand'			=> $this->tender['item'][$i]['brand'],
				'model'			=> $this->tender['item'][$i]['model'],
				'description'	=> $this->tender['item'][$i]['description'],
				'stock'			=> $this->tender['item'][$i]['stock'],
				'price'			=> $this->tender['item'][$i]['price'],
				'valid_until'	=> date("Y-m-d",$timestamp + $this->tender['item'][$i]['valid']*86400),
				'created_by'	=> $this->tender['submitter']['id'],
				'status'		=> $this->tender['item'][$i]['status']
			);
			if($this->tender['item'][$i]['quoteclass']) {
				$insert['classification'] = $this->tender['item'][$i]['quoteclass'];
			}
			if ($this->tender['item'][$i]['error']) {
				foreach ($this->tender['item'][$i]['error'] as $value) {
					$insert['error'].= $value."\n";
				}
			}
			// attachments
			if ($this->tender['item'][$i]['attachment']) {
				// attachment
				$insert['attachment'] = $this->tender['item'][$i]['attachment'];			
			}
			// no id present so log the quote
			if (!$this->tender['item'][$i]['id']) {
				// log the error - should however never occur
				$new_error = new error;
				$error_text = "Tender item ID not present for response from ".$this->tender['user']['name']." ".$this->tender['user']['surname'].". ";
				// set all values
				foreach ($insert as $key => $value) {
					$error_text.= $key."=".$value." ";
				}
				// $error_text.= var_export($this->tender['item'][$i]);
				$new_error->log("Response","critical",$error_text,$cfg);
			} else {
				// insert the quote
				$insert['tender_item'] = $this->tender['item'][$i]['id'];
				$create_quote = $this->create_tender_quote($insert,$cfg,$conn);
			}
		}
		// send error email if error occurred
		if ($this->tender['user']['row'] && $this->tender['method'] == "email") {
			// send the error email
			$this->error_email($cfg,$conn);
		} else {
			// determine if all suppliers quoted
			// check if should close if all quoted
			if($cfg['tender']['close']['auto']) {
				// check all tenders
				foreach($this->tender['tender_check'] as $value) {
					$this->tender['id'] = $value;
					$close_claim = $this->all_quoted($cfg,$conn);
					if ($close_claim) {
						// set the closing time to now
						$set_closing = $this->update_tender_status($this->tender['id'],"close","",$cfg,$conn);
					} elseif(is_numeric(str_replace(array("!","^","#"),"",$cfg['tender']['quote']['close']))) {
						// set the closing time to now
						$set_closing = $this->update_tender_status($this->tender['id'],"quote","",$cfg,$conn);
					}
				}
			}
		}
		// response
		return $this->tender;
	}
	
	/**
	 * sends an error email to agent
	 * 
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *   
	 */
	function error_email($cfg,$conn) {
		// query db to find out if tender info
		$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.= "~users.id, ";
		$sqlstr.= "~organisation.id, ";
		$sqlstr.= "~organisation_branch.id, ";
		$sqlstr.= "~area.id, ~area.state, ~area.name AS area_name, ";
		$sqlstr.= "~area_state.id, ~area_state.name AS state_name ";
		$sqlstr.= "FROM ~tender_item, ~tender, ~users, ~organisation, ~organisation_branch, ~area, ~area_state ";
		$sqlstr.= "WHERE ~tender_item.tender = '".$this->tender['id']."' ";
		$sqlstr.= "AND ~tender_item.tender = ~tender.id ";
		$sqlstr.= "AND ~tender.user_id = ~users.id ";
		$sqlstr.= "AND ~users.organisation = ~organisation.id ";
		$sqlstr.= "AND ~users.branch = ~organisation_branch.id ";
		$sqlstr.= "AND ~tender.area = ~area.id ";
		$sqlstr.= "AND ~area.state = ~area_state.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) {
			// response
			return FALSE;
       	} else {
			// set repsonse
			$attachment = $row['attachment'];
			// get the closing date and time and process
			$close_date = $row['close_date'];
			$close_time = $row['close_time'];
			list($year,$month,$day) = sscanf(str_replace(array("-"," "),"",$close_date),'%4s%2s%2s');
			list($hour,$minute,$second) = sscanf(str_replace(array(":"," "),"",$close_time),'%2s%2s%2s');
			$this->tender['close_date'] = date($cfg['date']['format']." ".$cfg['time']['format'], mktime($hour,$minute,$second,$month,$day,$year))." ".$cfg['local']['display'];
			$this->tender['areaname'] = $row['area_name'];
			$this->tender['statename'] = $row['state_name'];
			// get user info
			$new_users = new user;
			$users_info = $new_users->get_profile($row['user_id'],$cfg,$conn);
			$this->tender['requester']['name'] = $users_info['name'];
			$this->tender['requester']['surname'] = $users_info['surname'];
			$this->tender['requester']['phone_prefix'] = $users_info['phone_prefix'];
			$this->tender['requester']['phone_work'] = $users_info['phone_work'];
			$this->tender['requester']['email'] = $users_info['email'];
			$this->tender['requester']['organisationname'] = $users_info['organisationname'];
			$this->tender['requester']['branchname'] = $users_info['branchname'];
			// determine if rfq attachment present and if it is get the authentication string
			if ($attachment) {
				$this->tender['rfq_attachment'] = $this->attachment_details($attachment,$cfg,$conn);
			}
		}
		// include email body template
		$html = $subject = FALSE;
		require($cfg['file'].'modules/tender/templates/error.php');
		// set message paramaters
		$message['reference'] = "Error:".$this->tender['rfq_number'];
		$message['classification'] = "response_return";
		$message['subject'] = $subject;
		$message['body'] = $html;
		$message['name'] = $this->email['user']['name']." ".$this->email['user']['surname'];
		$message['email'] = $this->email['user']['email'];
		// send the email
		$new_message = new message;
		$message_id = $new_message->send_email_message($message,$this->tender['user']['id'],$this->tender['submitter']['id'],$cfg,$conn);
		if (!$message_id) {
			// error handling
			$error_text = $this->lang['emailerror'];
			$error_text.= " Reason: ".$new_message->error_text;
			$this->response['errortext'].= $error_text."&#10;";
		}
	}
	
	/**
	 * get attachment information
	 * 
	 * @param integer attachment_id attachment ID
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed attachment information on success or FALSE otherwise
	 *   
	 */
	function attachment_details($attachment_id,$cfg,$conn) {
		// query db to find out if closing date has been reached
		$sqlstr = "SELECT  id, name AS name,  authentication AS authentication, ";
		$sqlstr.= " status ";
		$sqlstr.= "FROM ~attachment ";
		$sqlstr.= "WHERE  id = '".$attachment_id."' ";
		$sqlstr.= "AND  status = '1' ";
		$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) {
			// response
			return FALSE;
       	}
		// set repsonse
		$response['id'] = $attachment_id;
		$response['name'] = $row['name'];
		$response['authentication'] = $row['authentication'];
		// return attachment information
		return $response;
	}
	
	/**
	 * parse email information
	 * 
	 * @param array info Email information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed attachment information on success or FALSE otherwise
	 *   
	 */
	function parse_email_info($info,$cfg,$conn) {
		// set the method
		$this->email['method'] = "email";
		// get the user information
		$new_user = new user;
		$this->email['user'] = $new_user->get_profile($info['user'][0],$cfg,$conn);
		$this->email['requester'] = $new_user->get_profile($info['requester'][0],$cfg,$conn);
		$this->email['id'] = $info['id'][0];
		$this->email['submitter']['id'] = $info['user'][0];
		$this->email['messageid'] = $info['messageid'];
		$this->email['attachment'] = $info['attachment'];
		// find out how many tenders are included in the email
		$this->email['itemsize'] = count($info['item']);	
		if ($this->email['itemsize'] == 0) {
			$lang = array();
			require($cfg['file'].'modules/generic/language/'.$cfg['language'].'/error.php');
			// No Item Info could be found in email, Message ID :
			$this->response['error'] = $lang['1031']." ".$info['messageid'];
			return FALSE;
		} else {
			// loop through every item and set the fields
			for ($i = 0; $i < $this->email['itemsize']; $i++) {
				$this->email['item'][$i]['id'] = $info['item'][$i];
				$this->email['item'][$i]['classification'] = $info['classification'][$i];
				$this->email['item'][$i]['brand'] = $info['brand'][$i];
				$this->email['item'][$i]['model'] = $info['model'][$i];
				$this->email['item'][$i]['description'] = $info['description'][$i];
				$this->email['item'][$i]['valid'] = $info['valid'][$i];
				$this->email['item'][$i]['stock'] = $info['stock'][$i];
				$this->email['item'][$i]['price'] = $info['price'][$i];
			}
			// proses the tender
			$proses_tender = $this->proses_response($this->email,$cfg,$conn);
			if ($proses_tender) {
				// set that processed correctly
				return TRUE;
			} else {
				// set that an error occurred
				// errors set in proses_response
				return FALSE;
			}
		}
	}
}
?>