<?php
/*********************************************************************************
 * The contents of this file are subject to the TimeTrex Public License Version
 * 1.1.0 ("License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.TimeTrex.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 on each user interface screen:
 *    (i) the "Powered by TimeTrex" logo and
 *    (ii) the TimeTrex copyright notice
 * in the same form as they appear in the distribution.  See full license for
 * requirements.
 *
 * The Original Code is: TimeTrex Open Source
 * The Initial Developer of the Original Code is TimeTrex Payroll Services
 * Portions created by TimeTrex are Copyright (C) 2004-2007 TimeTrex Payroll Services;
 * All Rights Reserved.
 *
 ********************************************************************************/
/*
 * $Revision: 2237 $
 * $Id: ExceptionFactory.class.php 2237 2008-11-11 18:18:20Z ipso $
 * $Date: 2008-11-11 10:18:20 -0800 (Tue, 11 Nov 2008) $
 */

/**
 * @package Core
 */
class ExceptionFactory extends Factory {
	protected $table = 'exception';
	protected $pk_sequence_name = 'exception_id_seq'; //PK Sequence name

	protected $user_date_obj = NULL;
	protected $exception_policy_obj = NULL;

	function _getFactoryOptions( $name ) {

		$retval = NULL;
		switch( $name ) {
			case 'type':
				//Exception life-cycle
				//
				// - Exception occurs, such as missed out punch, in late.
				//   - If the exception is pre-mature, we wait 16-24hrs for it to become a full-blown exception
				// - If the exception requires authorization, it sits in a pending state waiting for supervsior intervention.
				// - Supervisor authorizes the exception, or makes a correction, leaves a note or something.
				//	 - Exception no longer appears on timesheet/exception list.
				$retval = array(
										5  => TTi18n::gettext('Pre-Mature'),
										30 => TTi18n::gettext('PENDING AUTHORIZATION'),
										40 => TTi18n::gettext('AUTHORIZATION OPEN'),
										50 => TTi18n::gettext('ACTIVE'),
										55 => TTi18n::gettext('AUTHORIZATION DECLINED'),
										60 => TTi18n::gettext('DISABLED'),
										70 => TTi18n::gettext('Corrected')
									);
				break;
		}

		return $retval;
	}


	function getUserDateObject() {
		if ( is_object($this->user_date_obj) ) {
			return $this->user_date_obj;
		} else {
			$udlf = new UserDateListFactory();
			$this->user_date_obj = $udlf->getById( $this->getUserDateID() )->getCurrent();

			return $this->user_date_obj;
		}
	}

	function getExceptionPolicyObject() {
		if ( is_object($this->exception_policy_obj) ) {
			return $this->exception_policy_obj;
		} else {
			$eplf = new ExceptionPolicyListFactory();
			$this->exception_policy_obj = $eplf->getById( $this->getExceptionPolicyID() )->getCurrent();

			return $this->exception_policy_obj;
		}
	}

	function getUserDateID() {
		if ( isset($this->data['user_date_id']) ) {
			return $this->data['user_date_id'];
		}

		return FALSE;
	}
	function setUserDateID($id = NULL) {
		$id = trim($id);

		$udlf = new UserDateListFactory();

		if (  $this->Validator->isResultSetWithRows(	'user_date',
														$udlf->getByID($id),
														TTi18n::gettext('Invalid User Date ID')
														) ) {
			$this->data['user_date_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getExceptionPolicyID() {
		if ( isset($this->data['exception_policy_id']) ) {
			return $this->data['exception_policy_id'];
		}

		return FALSE;
	}
	function setExceptionPolicyID($id) {
		$id = trim($id);

		if ( $id == '' OR empty($id) ) {
			$id = NULL;
		}

		$eplf = new ExceptionPolicyListFactory();

		if (	$id == NULL
				OR
				$this->Validator->isResultSetWithRows(	'exception_policy',
														$eplf->getByID($id),
														TTi18n::gettext('Invalid Exception Policy ID')
														) ) {
			$this->data['exception_policy_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getPunchControlID() {
		if ( isset($this->data['punch_control_id']) ) {
			return $this->data['punch_control_id'];
		}

		return FALSE;
	}
	function setPunchControlID($id) {
		$id = trim($id);

		if ( $id == '' OR empty($id) ) {
			$id = NULL;
		}

		$pclf = new PunchControlListFactory();

		if (
				$id == NULL
				OR
				$this->Validator->isResultSetWithRows(	'punch_control',
														$pclf->getByID($id),
														TTi18n::gettext('Invalid Punch Control ID')
														) ) {
			$this->data['punch_control_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getPunchID() {
		if ( isset($this->data['punch_id']) ) {
			return $this->data['punch_id'];
		}

		return FALSE;
	}
	function setPunchID($id) {
		$id = trim($id);

		if ( $id == '' OR empty($id) ) {
			$id = NULL;
		}

		$plf = new PunchListFactory();

		if (	$id == NULL
				OR
				$this->Validator->isResultSetWithRows(	'punch',
														$plf->getByID($id),
														TTi18n::gettext('Invalid Punch ID')
														) ) {
			$this->data['punch_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getType() {
		if ( isset($this->data['type_id']) ) {
			return $this->data['type_id'];
		}

		return FALSE;
	}
	function setType($value) {
		$value = trim($value);

		$key = Option::getByValue($value, $this->getOptions('type') );
		if ($key !== FALSE) {
			$value = $key;
		}

		if ( $this->Validator->inArrayKey(	'type',
											$value,
											TTi18n::gettext('Incorrect Type'),
											$this->getOptions('type')) ) {

			$this->data['type_id'] = $value;

			return FALSE;
		}

		return FALSE;
	}

	function getEnableDemerits() {
		if ( isset($this->data['enable_demerit']) ) {
			return $this->data['enable_demerit'];
		}

		return FALSE;
	}
	function setEnableDemerits($bool) {
		$this->data['enable_demerit'] = $bool;

		return TRUE;
	}

	function getColor() {
		$retval = FALSE;

		if (  $this->getType() == 5 ) {
			$retval = "gray";
		} else {
			if ( $this->getColumn('severity_id') != '' ) {
				switch ( $this->getColumn('severity_id') ) {
					case 10:
						$retval = 'black';
						break;
					case 20:
						$retval = 'blue';
						break;
					case 30:
						$retval = 'red';
						break;
				}
			}
		}

		return $retval;
	}

	function getEmailExceptionAddresses( $u_obj = NULL, $ep_obj = NULL ) {
		Debug::text(' Attempting to Email Notification...', __FILE__, __LINE__, __METHOD__,10);

		//Make sure type is not pre-mature.
		if ( $this->getType() > 5 ) {
			if ( !is_object($ep_obj) ) {
				$ep_obj = $this->getExceptionPolicyObject();
			}

			//Make sure exception policy email notifications are enabled.
			if ( $ep_obj->getEmailNotification() > 0 ) {
				if ( !is_object($u_obj) ) {
					$u_obj = $this->getUserDateObject()->getUserObject();
				}

				$up_obj = $this->getUserDateObject()->getUserObject()->getUserPreferenceObject();

				//Make sure user email notifications are enabled.
				if ( ( $ep_obj->getEmailNotification() == 10 OR $ep_obj->getEmailNotification() == 100 ) AND $up_obj->getEnableEmailNotificationException() == TRUE ) {
					Debug::Text(' Emailing exception to user!', __FILE__, __LINE__, __METHOD__,10);
					if ( $u_obj->getWorkEmail() != '' ) {
						$retarr[] = $u_obj->getWorkEmail();
					}
					if ( $up_obj->getEnableEmailNotificationHome() == TRUE AND $u_obj->getHomeEmail() != '' ) {
						$retarr[] = $u_obj->getHomeEmail();
					}
				} else {
					Debug::Text(' Skipping email to user.', __FILE__, __LINE__, __METHOD__,10);
				}

				//Make sure supervisor email notifcations are enabled
				if ( $ep_obj->getEmailNotification() == 20 OR $ep_obj->getEmailNotification() == 100 ) {
					//Find supervisor

					//Find proper hierarchy to use for this object
					$hotlf = new HierarchyObjectTypeListFactory();
					$control_id = $hotlf->getByCompanyIdAndObjectTypeId( $u_obj->getCompany(), 80 )->getCurrent()->getHierarchyControl();
					Debug::Text(' Hierarchy Control ID: '. $control_id , __FILE__, __LINE__, __METHOD__,10);

					if ( is_numeric( $control_id ) ) {
						$hlf = new HierarchyListFactory();
						$node_data = $hlf->getByHierarchyControlIdAndUserId( $control_id, $u_obj->getId() );
						$parent_user_id = $node_data['parent_id'];

						$ulf = new UserListFactory();
						$ulf->getById( $parent_user_id );
						if ( $ulf->getRecordCount() > 0 ) {
							$parent_user_obj = $ulf->getCurrent();

							if ( is_object( $parent_user_obj->getUserPreferenceObject() ) AND $parent_user_obj->getUserPreferenceObject()->getEnableEmailNotificationException() == TRUE ) {
								Debug::Text(' Emailing exception to supervisor!', __FILE__, __LINE__, __METHOD__,10);
								if ( $parent_user_obj->getWorkEmail() != '' ) {
									$retarr[] = $parent_user_obj->getWorkEmail();
								}

								if ( $up_obj->getEnableEmailNotificationHome() == TRUE AND $parent_user_obj->getHomeEmail() != '' ) {
									$retarr[] = $parent_user_obj->getHomeEmail();
								}
							} else {
								Debug::Text(' Skipping email to supervisor.', __FILE__, __LINE__, __METHOD__,10);
							}
						}
					} else {
						Debug::Text(' No Hierarchy Control Found, skipping email to supervisor.', __FILE__, __LINE__, __METHOD__,10);
					}
				}

				if ( isset($retarr) AND is_array($retarr) ) {
					return $retarr;
				} else {
					Debug::text(' No user objects to email too...', __FILE__, __LINE__, __METHOD__,10);
				}
			} else {
				Debug::text(' Exception Policy Email Exceptions are disabled, skipping email...', __FILE__, __LINE__, __METHOD__,10);
			}
		} else {
			Debug::text(' Pre-Mature exception, or not in production mode, skipping email...', __FILE__, __LINE__, __METHOD__,10);
		}

		return FALSE;
	}


	/*

		What do we pass the emailException function?
			To address, CC address (home email) and Bcc (supervisor) address?

	*/
	function emailException( $u_obj, $user_date_obj, $ep_obj = NULL ) {

		if ( !is_object( $u_obj ) ) {
			return FALSE;
		}

		if ( !is_object( $user_date_obj ) ) {
			return FALSE;
		}

		if ( !is_object($ep_obj) ) {
			$ep_obj = $this->getExceptionPolicyObject();
		}

		//Only email on active exceptions.
		if ( $this->getType() != 50 ) {
			return FALSE;
		}

		$email_to_arr = $this->getEmailExceptionAddresses( $u_obj, $ep_obj );
		if ( $email_to_arr == FALSE ) {
			return FALSE;
		}

		$from = 'DoNotReply@'.Misc::getHostName();

		$to = array_shift( $email_to_arr );
		Debug::Text('To: '. $to, __FILE__, __LINE__, __METHOD__,10);
		if ( is_array($email_to_arr) AND count($email_to_arr) > 0 ) {
			$bcc = implode(',', $email_to_arr);
		} else {
			$bcc = NULL;
		}

		$exception_email_subject = ' #exception_name# (#exception_code#) '. TTi18n::gettext('exception for') .' #employee_first_name# #employee_last_name# '. TTi18n::gettext('on') .' #date#';
		$exception_email_body  = TTi18n::gettext('Employee:').' #employee_first_name# #employee_last_name#'."\n";
		$exception_email_body .= TTi18n::gettext('Date:').' #date#'."\n";
		$exception_email_body .= TTi18n::gettext('Exception:').' #exception_name# (#exception_code#)'."\n";
		$exception_email_body .= TTi18n::gettext('Severity:').' #exception_severity#'."\n";
		$exception_email_body .= TTi18n::gettext('Link:').' <a href="http://'. Misc::getHostName().Environment::getBaseURL().'">'.APPLICATION_NAME.' '. TTi18n::gettext('Login') .'</a>';

		//Define subject/body variables here.
		$search_arr = array(
							'#employee_first_name#',
							'#employee_last_name#',
							'#exception_code#',
							'#exception_name#',
							'#exception_severity#',
							'#date#',
							'#link#',
							);

		$replace_arr = array(
							$u_obj->getFirstName(),
							$u_obj->getLastName(),
							$ep_obj->getType(),
							Option::getByKey( $ep_obj->getType(), $ep_obj->getOptions('type') ),
							Option::getByKey( $ep_obj->getSeverity(), $ep_obj->getOptions('severity') ),
							TTDate::getDate('DATE', $user_date_obj->getDateStamp() ),
							NULL,
							);

		//For some reason the EOL defaults to \r\n, which seems to screw with Amavis
		if ( !defined('MAIL_MIMEPART_CRLF') ) {
			define('MAIL_MIMEPART_CRLF', "\n");
		}

		$subject = str_replace( $search_arr, $replace_arr, $exception_email_subject );
		Debug::Text('Subject: '. $subject, __FILE__, __LINE__, __METHOD__,10);

		$headers = array(
							'From'    => $from,
							'Subject' => $subject,
							'Bcc'	  => $bcc,
							'Reply-To' => $to,
							'Return-Path' => $to,
							'Errors-To' => $to,
						 );
		Debug::Arr($headers, 'Headers: ', __FILE__, __LINE__, __METHOD__,10);

		$body = '<pre>'.str_replace( $search_arr, $replace_arr, $exception_email_body ).'</pre>';
		Debug::Text('Body: '. $body, __FILE__, __LINE__, __METHOD__,10);

		require_once('Mail.php');
		require_once('Mail/mime.php');

		$mime = @new Mail_Mime();
		@$mime->setHTMLBody($body);

		@$body = $mime->get();
		@$headers = $mime->headers($headers);

		$mail = &Mail::factory('mail');
		if ( PRODUCTION == TRUE AND DEMO_MODE == FALSE ) {
			if ( $mail->send($to, $headers, $body) == TRUE ) {
				TTLog::addEntry( $this->getId(), 500,  TTi18n::getText('Email Exception to').': '. $to .' Bcc: '. $headers['Bcc'], NULL, $this->getTable() );
				return TRUE;
			}
		} else {
			Debug::Text(' Not sending email, production mode not enabled...', __FILE__, __LINE__, __METHOD__,10);
		}

		return TRUE;
	}

	function Validate() {
		return TRUE;
	}

	function preSave() {
		return TRUE;
	}

	function postSave() {
		return TRUE;
	}

}
?>
