<?php
/**
 * Order import
 *
 * @package 	CSVIVirtueMart
 * @subpackage 	Import
 * @author 		Roland Dalmulder
 * @link 		http://www.csvimproved.com
 * @copyright 	Copyright (C) 2006 - 2012 RolandD Cyber Produksi
 * @license 	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 * @version 	$Id: orderimport.php 1892 2012-02-11 11:01:09Z RolandD $
 */

defined( '_JEXEC' ) or die( 'Direct Access to this location is not allowed.' );

/**
 * Processor for order import
 *
 * @package CSVIVirtueMart
 */
class CsvivirtuemartModelOrderimport extends CsvivirtuemartModelImportfile {

	// Private tables
	/** @var object contains the vm_orders table */
	private $_vm_orders = null;
	/** @var object contains the vm_orders table */
	private $_vm_order_user_info = null;
	/** @var object contains the vm_orders table */
	private $_vm_order_payment = null;
	/** @var object contains the vm_orders table */
	private $_vm_order_item = null;
	/** @var object contains the vm_orders table */
	private $_vm_order_history = null;

	// Public variables
	/** @var string type of address */
	public $address_type = 'BT';
	/** @var int the ID of the order */
	public $order_id = null;
	/** @var int creation date of the order */
	public $cdate = null;
	/** @var int modification date of the order */
	public $mdate = null;
	/** @var string unique identifier of the order */
	public $order_number = null;
	/** @var string currency used in the order */
	public $order_currency = null;
	/** @var string shipping costs for the order */
	public $order_shipping = null;
	/** @var string tax on shipping costs for the order */
	public $order_shipping_tax = null;
	/** @var string coupon code used for the order */
	public $coupon_code = null;
	/** @var int method id of the shipping method of the order */
	public $ship_method_id = null;
	/** @var int the user ID of the user placed the order */
	public $user_id = null;
	/** @var string unique identifier of the user */
	public $user_info_id = null;
	/** @var int unique identifier of the order user */
	public $order_info_id = null;
	/** @var object details of the order user */
	public $userdetails = null;
	public $address_type_name = null;
	public $company = null;
	public $title = null;
	public $last_name = null;
	public $first_name = null;
	public $middle_name = null;
	public $phone_1 = null;
	public $phone_2 = null;
	public $fax = null;
	public $address_1 = null;
	public $address_2 = null;
	public $city = null;
	public $state = null;
	public $country = null;
	public $zip = null;
	public $extra_field_1 = null;
	public $extra_field_2 = null;
	public $extra_field_3 = null;
	public $extra_field_4 = null;
	public $extra_field_5 = null;
	public $bank_account_nr = null;
	public $bank_name = null;
	public $bank_sort_code = null;
	public $bank_iban = null;
	public $bank_account_holder = null;
	public $bank_account_type = null;
	public $user_email = null;

	// Private variables
	/** @var mixed contains the data of the current field being processed */
	private $_datafield = null;
	/** @var object contains general import functions */
	private $_importmodel = null;
	/** @var bool set whether user data is added/updated or not */
	private $_updateuser = false;

	/**
	 * Constructor
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return
	 * @since 		3.4
	 */
	public function __construct() {
		parent::__construct();
		// Load the tables that will contain the data
		$this->_loadTables();
		$this->loadSettings();
    }

    /**
     * Refresh the settings for XML nodes
     *
     * @copyright
     * @author 		RolandD
     * @todo
     * @see
     * @access 		protected
     * @param
     * @return
     * @since 		3.8.2
     */
	protected function refresh() {
		$this->loadSettings();
	}

	/**
	 * Here starts the processing
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return
	 * @since 		3.0
	 */
	public function getStart() {
		// Load the data
		$this->loadData();

		// Get the logger
		$csvilog = JRequest::getVar('csvilog');

		// Load some basic info
		$this->vendor_id = $this->getVendorId();

		// Process data
		foreach ($this->_csvifields as $name => $details) {
			if ($details['published']) {
				$this->_datafield = $this->validateInput($name);
				if ($this->_datafield !== false) {
					// Check if we are dealing with the last field
					if ($details == $this->_lastfield) $details['combine'] = false;

					// See if we are combining the field
					if ($details['combine']) $this->setCombineField($this->_datafield, $name);
					else {
						// Check if there are any fields to be combined
						if (!empty($this->combine_fields)) {
							// Get the fieldname the combine is for
							$name = $this->combine_settings['fieldname'];
							// Add the current data
							$this->setCombineField($this->_datafield);
							// Get the combined data
							$this->_datafield = $this->getCombineField();
						}
						// Check if the field needs extra treatment
						switch ($name) {
							case 'order_payment_expire':
								$this->$name = $this->convertDate($this->_datafield);
								break;
							case 'order_date':
								$this->cdate = $this->convertDate($this->_datafield);
								break;
							case 'date_added':
								$this->$name = $this->_getMysqlDate();
								break;
							case 'customer_notified':
								$this->$name = (strtoupper($this->_datafield) == 'N') ? 0 : 1;
								break;
							case 'order_status':
								$this->$name = $this->_datafield;
								$this->order_status_code = $this->_datafield;
								break;
							case 'order_status_name':
								$this->order_status = $this->_getOrderStatus($this->_datafield);
								$this->order_status_code = $this->order_status;
								break;
							case 'order_discount':
							case 'order_shipping':
							case 'order_shipping_tax':
							case 'order_subtotal':
							case 'order_total':
							case 'product_final_price':
							case 'order_tax':
							case 'coupon_discount':
								$this->$name = $this->cleanPrice($this->_datafield);
								break;
							default:
								$this->$name = $this->_datafield;
								break;
						}
					}
				}
				else return false;
			}
		}
		return true;
	}

	/**
	 * Process each record and store it in the database
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return
	 * @since 		3.0
	 */
	public function getProcessRecord() {
		$db = JFactory::getDBO();
		$csvilog = JRequest::getVar('csvilog');

		// Load the order user details
		if (!isset($this->user_id) && isset($this->user_email)) {
			$q = "SELECT id FROM #__users WHERE email = ".$db->Quote($this->user_email);
			$db->setQuery($q);
			$this->user_id = $db->loadResult();
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_RETRIEVE_USER_ID'), true);
		}

		if (isset($this->user_id)) {
			$q = "SELECT *
				FROM #__vm_user_info
				WHERE address_type = 'BT'
				AND user_id = ".$this->user_id;
			$db->setQuery($q);
			$userdetails = $db->loadObject();
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_LOAD_USER_DETAILS'), true);
		}
		else {
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_NOT_PROCESS_USER'));
			$csvilog->AddStats('incorrect', JText::_('COM_CSVIVIRTUEMART_NOT_PROCESS_USER'));
			return false;
		}

		// Load the order if there is an order_id
		if (isset($this->order_id)) {
			$this->_vm_orders->order_id = $this->order_id;
			if ($this->_vm_orders->check()) {
				$this->_vm_orders->load($this->order_id);
			}
			else {
				// Add the creation date
				if (!isset($this->cdate)) $this->cdate = time();

				// Create an order number if it is empty
				if (empty($this->order_number)) {
					$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_CREATE_ORDER_NUMBER'));
					$str = session_id();
					$str .= (string)$this->cdate;

					$order_number = $this->user_id.'_'. md5($str);
					$this->order_number = substr($order_number, 0, 32);
				}
				else {
					$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_NOT_CREATE_ORDER_NUMBER'));
				}

				// Check the order tax details
				/** @todo Find out if this is really needed */
				if (empty($this->order_tax_details)) {
					$this->order_tax_details = 'a:0:{}';
				}

				// Check the order currency
				if (!isset($this->order_currency)) {
					$q = "SELECT vendor_currency
						FROM #__vm_vendor
						WHERE vendor_id = ".$this->vendor_id;
					$db->setQuery($q);
					$this->order_currency = $db->loadResult();
				}

				// Check the user info id
				if (empty($this->user_info_id)) $this->user_info_id = $userdetails->user_info_id;

				// Check the order_shipping
				if (!isset($this->order_shipping)) $this->order_shipping = 0;

				// Check the order_shipping_tax
				if (!isset($this->order_shipping_tax)) $this->order_shipping_tax = 0;

				// Check the coupon_code
				if (!isset($this->coupon_code)) $this->coupon_code = '';

				// Check the ship_method_id
				if (!isset($this->ship_method_id)) $this->ship_method_id = '';
			}
		}

		// Add the modification date
		if (!isset($this->mdate)) $this->mdate = time();

		// Bind order data
		$this->_vm_orders->bind($this);

		// Store the order
		if ($this->_vm_orders->store()) {
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_ORDER_QUERY'), true);
			if ($this->queryResult() == 'UPDATE') $csvilog->AddStats('updated', JText::_('COM_CSVIVIRTUEMART_UPDATE_ORDER'));
			else $csvilog->AddStats('added', JText::_('COM_CSVIVIRTUEMART_ADD_ORDER'));
			$this->order_id = $this->_vm_orders->order_id;
		}
		else {
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_ORDER_QUERY'), true);
			$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_ORDER_NOT_ADDED', $this->_vm_orders->getError()));

			// Clean the tables
			$this->cleanTables();
			return false;
		}

		//* Store the user info
		if (!isset($this->order_info_id)) {
			// Check if there is the requested address in the database
			$q = "SELECT order_info_id
				FROM #__vm_order_user_info
				WHERE address_type = ".$db->Quote($this->address_type)."
				AND order_id = ".$this->order_id;
			$db->setQuery($q);
			$this->order_info_id = $db->loadResult();
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_LOAD_ORDER_INFO_ID'), true);
		}

		// Load the order info
		if ($this->order_info_id) {
			$this->_vm_order_user_info->load($this->order_info_id);
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_LOAD_ORDER_INFO'), true);
		}

		if (!$this->order_info_id || $this->_vm_order_user_info->user_id != $this->user_id) {
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_DEBUG_LOAD_USER_ORDER_INFO'));
			// Address type name
			if (!isset($this->address_type_name)) $this->address_type_name = $userdetails->address_type_name;

			// Company
			if (!isset($this->company)) $this->company = $userdetails->company;

			// Title
			if (!isset($this->title)) $this->title = $userdetails->title;

			// Last name
			if (!isset($this->last_name)) $this->last_name = $userdetails->last_name;

			// First name
			if (!isset($this->first_name)) $this->first_name = $userdetails->first_name;

			// Middle name
			if (!isset($this->middle_name)) $this->middle_name = $userdetails->middle_name;

			// Phone 1
			if (!isset($this->phone_1)) $this->phone_1 = $userdetails->phone_1;

			// Phone 2
			if (!isset($this->phone_2)) $this->phone_2 = $userdetails->phone_2;

			// Fax
			if (!isset($this->fax)) $this->fax = $userdetails->fax;

			// Address 1
			if (!isset($this->address_1)) $this->address_1 = $userdetails->address_1;

			// Address 2
			if (!isset($this->address_2)) $this->address_2 = $userdetails->address_2;

			// City
			if (!isset($this->city)) $this->city = $userdetails->city;

			// State
			if (!isset($this->state)) $this->state = $userdetails->state;

			// Country
			if (!isset($this->country)) $this->country = $userdetails->country;

			// Zip
			if (!isset($this->zip)) $this->zip = $userdetails->zip;

			// Extra field 1
			if (!isset($this->extra_field_1)) $this->extra_field_1 = $userdetails->extra_field_1;

			// Extra field 2
			if (!isset($this->extra_field_2)) $this->extra_field_2 = $userdetails->extra_field_2;

			// Extra field 3
			if (!isset($this->extra_field_3)) $this->extra_field_3 = $userdetails->extra_field_3;

			// Extra field 4
			if (!isset($this->extra_field_4)) $this->extra_field_4 = $userdetails->extra_field_4;

			// Extra field 5
			if (!isset($this->extra_field_5)) $this->extra_field_5 = $userdetails->extra_field_5;

			// Bank account nr
			if (!isset($this->bank_account_nr)) $this->bank_account_nr = $userdetails->bank_account_nr;

			// Bank name
			if (!isset($this->bank_name)) $this->bank_name = $userdetails->bank_name;

			// Bank sort code
			if (!isset($this->bank_sort_code)) $this->bank_sort_code = $userdetails->bank_sort_code;

			// Bank IBAN
			if (!isset($this->bank_iban)) $this->bank_iban = $userdetails->bank_iban;

			// Bank account holder
			if (!isset($this->bank_account_holder)) $this->bank_account_holder = $userdetails->bank_account_holder;

			// Bank account type
			if (!isset($this->bank_account_type)) $this->bank_account_type = $userdetails->bank_account_type;

			// User email
			if (!isset($this->user_email)) $this->user_email = $userdetails->user_email;
		}

		// Bind the user uploaded data
		$this->_vm_order_user_info->bind($this);

		// Store the order user info
		if ($this->_vm_order_user_info->store($this)) {
			if ($this->queryResult() == 'UPDATE') $csvilog->AddStats('updated', JText::_('COM_CSVIVIRTUEMART_UPDATE_ORDERUSER'));
			else $csvilog->AddStats('added', JText::_('COM_CSVIVIRTUEMART_ADD_ORDERUSER'));
		}
		else $csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_ORDERUSER_NOT_ADDED', $this->_vm_order_user_info->getError()));

		// Store the debug message
		$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_ORDERUSER_QUERY'), true);

		// Check if the order has at least a billing address
		if ($this->address_type == 'ST') {
			// Check if there is the requested address in the database
			$q = "SELECT order_info_id
				FROM #__vm_order_user_info
				WHERE address_type = 'BT'
				AND order_id = ".$this->order_id;
			$db->setQuery($q);
			$bt_order_info_id = $db->loadResult();

			// There is no BT address let's add one
			if (!$bt_order_info_id) {
				// Get all the fields from the user info table
				$q = "SHOW COLUMNS FROM #__vm_user_info";
				$db->setQuery($q);
				$user_fields_raw = $db->loadAssocList();

				$user_fields = array();
				foreach($user_fields_raw as $user_field) {
					$user_fields[] = $user_field['Field'];
				}

				$q = "SHOW COLUMNS FROM #__vm_order_user_info";
				$db->setQuery($q);
				$order_user_fields_raw = $db->loadAssocList();

				$order_user_fields = array();
				foreach($order_user_fields_raw as $user_field) {
					$order_user_fields[] = $user_field['Field'];
				}

				$copy_fields = array_intersect($order_user_fields, $user_fields);

				// Create the billing address entry
				$q = "INSERT INTO #__vm_order_user_info (".implode(',', $copy_fields).", order_id) (SELECT ".implode(',', $copy_fields).", ".$this->order_id." AS order_id FROM #__vm_user_info WHERE user_id = ".$this->user_id." AND address_type = 'BT')";
				$db->setQuery($q);
				$db->query();
				$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_CREATE_BILLING_QUERY'), true);
			}
		}

		// Store the order payment info
		// Load the payment info
		$this->_vm_order_payment->load($this->order_id);

		// Check if we need to create a new payment entry
		if (empty($this->_vm_order_payment->order_id)) {
			// Create a pseudo entry for updating
			$q = "INSERT INTO #__vm_order_payment (order_id) VALUES (".$this->order_id.")";
			$db->setQuery($q);
			$db->query();
		}

		// Handle the encrypted order_payment_number
		if (isset($this->order_payment_number)) {
			$config = JFactory::getConfig();
			$secret =  md5($config->getValue('config.secret'));
			$this->order_payment_number = "AES_ENCRYPT('".$this->order_payment_number."','".$secret."')";
		}

		// Handle the payment method ID
		if (isset($this->payment_method_code)) {
			$q = "SELECT payment_method_id
				FROM #__vm_payment_method
				WHERE payment_method_code = ".$db->Quote($this->payment_method_code);
			$db->setQuery($q);
			$this->payment_method_id = $db->loadResult();
		}

		// Bind the payment data
		$this->_vm_order_payment->bind($this);

		// Store the order payment info
		if ($this->_vm_order_payment->store($this)) {
			if ($this->queryResult() == 'UPDATE') $csvilog->AddStats('updated', JText::_('COM_CSVIVIRTUEMART_UPDATE_ORDER_PAYMENT'));
			else $csvilog->AddStats('added', JText::_('COM_CSVIVIRTUEMART_ADD_ORDER_PAYMENT'));
		}
		else $csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_ORDER_PAYMNET_NOT_ADDED', $this->_vm_order_payment->getError()));

		// Store the debug message
		$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_ORDER_PAYMENT_QUERY'), true);

		// Create an order history entry
		// Load the payment info
		if (isset($this->order_status_history_id)) {
			$this->_vm_order_history->load($this->order_status_history_id);
		}
		else {
			if (!isset($this->date_added)) $this->date_added = date('Y-m-d H:i:s', time());
			if (!isset($this->customer_notified)) $this->customer_notified = 0;
		}

		// Bind the payment data
		$this->_vm_order_history->bind($this);

		// Store the order history info
		if ($this->_vm_order_history->store($this)) {
			if ($this->queryResult() == 'UPDATE') $csvilog->AddStats('updated', JText::_('COM_CSVIVIRTUEMART_UPDATE_ORDER_HISTORY'));
			else $csvilog->AddStats('added', JText::_('COM_CSVIVIRTUEMART_ADD_ORDER_HISTORY'));
		}
		else $csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_ORDER_PAYMNET_NOT_ADDED', $this->_vm_order_history->getError()));

		// Store the debug message
		$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_ORDER_HISTORY_QUERY'), true);

		// Clean the tables
		$this->cleanTables();
	}

	/**
	 * Load the order import related tables
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return
	 * @since 		3.0
	 */
	private function _loadTables() {
		$this->_vm_orders = $this->getTable('vm_orders');
		$this->_vm_order_user_info = $this->getTable('vm_order_user_info');
		$this->_vm_order_payment = $this->getTable('vm_order_payment');
		$this->_vm_order_item = $this->getTable('vm_order_item');
		$this->_vm_order_history = $this->getTable('vm_order_history');
	}

	/**
	 * Cleaning the order import related tables
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param
	 * @return
	 * @since 		3.0
	 */
	protected function cleanTables() {
		$this->_vm_orders->reset();
		$this->_vm_order_user_info->reset();
		$this->_vm_order_payment->reset();
		$this->_vm_order_item->reset();
		$this->_vm_order_history->reset();

		// Clean local variables
		$class_vars = get_class_vars(get_class($this));
		foreach ($class_vars as $name => $value) {
			if (substr($name, 0, 1) != '_') {
				$this->$name = $value;
			}
		}
	}

	/**
	 * Formate a date to MySQL timestamp
	 *
	 * Format of the date is day/month/year or day-month-year.
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo 		use JDate
	 * @todo 		move to general function
	 * @see
	 * @access 		private
	 * @param
	 * @return 		string 	MySQL timestamp
	 * @since 		3.0
	 */
	private function _getMysqlDate() {
		$new_date = preg_replace('/-|\./', '/', $this->_datafield);
		$date_parts = explode('/', $new_date);
		if ((count($date_parts) == 3) && ($date_parts[0] > 0 && $date_parts[0] < 32 && $date_parts[1] > 0 && $date_parts[1] < 13 && (strlen($date_parts[2]) == 4))) {
			$old_date = $date_parts[2].'-'.$date_parts[1].'-'.$date_parts[0];
		}
		else $old_date = date('Y-m-d H:i:s', time());
		return $old_date;
	}

	/**
	 * Load the order status code
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		pivate
	 * @param 		string	$order_status_name	the name of the order status
	 * @return 		string 	the order status code
	 * @since 		2.3.11
	 */
	private function _getOrderStatus($order_status_name) {
		$db = JFactory::getDBO();
		$q = "SELECT order_status_code
			FROM #__vm_order_status
			WHERE order_status_name = ".$db->Quote($order_status_name);
		$db->setQuery($q);
		return $db->loadResult();
	}
}
?>
