<?php
/*
 * shopping/order/step/Save.class.php
 * 
 * CopyRight(C) 2010 Shopformer Development Team. All Right Reserved
 * URL: http://sourceforge.jp/projects/shopformer/
 * 
 * 
 * Mail: m_nakashima@users.sourceforge.jp
 * Auther: Masanori Nakashima
 * Last Update: 2010-10-07
 */
require_once(dirname(dirname(dirname(__FILE__)))
.DIRECTORY_SEPARATOR.'PackageConfig.class.php' );
require_once( dirname(dirname(dirname(__FILE__)))
.DIRECTORY_SEPARATOR.'DaoShoppingOrder.class.php' );
require_once( dirname(dirname(__FILE__))
.DIRECTORY_SEPARATOR.'Optimize.class.php' );
require_once( dirname(__FILE__)
.DIRECTORY_SEPARATOR.'Execute.class.php' );
/**
 * shopping_order_step_Save
 * @author m.nakashima
 */
class shopping_order_step_Save extends system_login_ModuleBase {
	/**
	 * コンストラクタ
	 */
	function shopping_order_step_Save() {
		array_push($this->require_module_array,'system.login.Require');
		array_push($this->require_module_array,'shopping.order.settlement.LoadListExists');
		array_push($this->require_module_array,'database2.Transaction');
		array_push($this->require_module_array,'shopping.order.CartAdmin');
	}
	/**
	 * executeメソッド
	 */
	function execute( & $request ) {
		$dbo					= $request->getAttribute( 'dbo' );
		$orderId				= $request->getParam('shpoi','get');
		$isNotify				= $request->getParam('is_notify','post');
		$loginUserObject		= $this->getLoginUserObject( $request );
		$sessionObjectName		= SHOPPING_SESSION_NAME_ORDER_OBJECT.'.'.$orderId;
		// カートオブジェクトの取得
		$shoppingOrderObject	= $request->getAttribute('shopping.order.orderObject');
		// 古い情報をデータベースから取得
		$oldOrderObject			= spider_Controller::createObject('shopping_DaoShoppingOrder');
		if( $dbo->loadById( $oldOrderObject, $shoppingOrderObject->order_id, true ) ) {
			$oldOrderObject->optimize();
		} else {
			$request->addLocaledError('shopping.error.order.notfound',SPIDER_LOG_LEVEL_FATAL,array(''));
			return;
		}
		// 決済方法読み込み
		$settleMethodObject			= null;
		$oldSettleMethodObject		= null;
		$settleMethodObjectArray	= $request->getAttribute('shopping.order.settlement.methodExistsObjectArray');
		foreach( $settleMethodObjectArray as $settleObject ) {
			if( $shoppingOrderObject->payment_total == 0 && $settleObject->getMethodNumber() == 16 ) {
				// 合計金額が0円の場合はポイント決済とみなす
				$settleObject->load( $request );
				$settleMethodObject	= $settleObject;
			} else if( $settleObject->getMethodNumber() == $shoppingOrderObject->settle_method ) {
				$settleObject->load( $request );
				$settleMethodObject	= $settleObject;
			} else if( $settleObject->getMethodNumber() == $oldOrderObject->settle_method ) {
				$settleObject->load( $request );
				$oldSettleMethodObject	= $settleObject;
			}
		}
		// 操作ユーザーの判断
		$operationType	= $shoppingOrderObject->confirmModifyPermittion( $request, $loginUserObject );
		// 変更者が管理者またはオーナーでない場合は状態を変更申請中にする
		if( isset($GLOBALS['SHOPPING_ORDER_MODIFY_STATUS'])
		&& is_array($GLOBALS['SHOPPING_ORDER_MODIFY_STATUS'])
		&& isset($GLOBALS['SHOPPING_ORDER_MODIFY_STATUS'][$operationType])
		&& isset($GLOBALS['SHOPPING_ORDER_STATUS_HASH'][$GLOBALS['SHOPPING_ORDER_MODIFY_STATUS'][$operationType]]) ) {
			$shoppingOrderObject->status_flag	= $GLOBALS['SHOPPING_ORDER_MODIFY_STATUS'][$operationType];
		} else if( 2 == $operationType ){
			$shoppingOrderObject->status_flag	= 5;
		}
		if( 2 == $operationType && $oldOrderObject->status_flag > 5 ){
			// 変更前が仮予約・申請中以外の場合は記録を残す
			$oldOrderObject->saveSerialized( $request );
		}
		// データベースのORDERテーブルを更新する
		if( $dbo->update($shoppingOrderObject) ) {
			// 紐づく宛先とORDER商品、オプションを更新する
			if( $shoppingOrderObject->updateOrderTable( $request ) ) {
				// member
				$dbo->update($shoppingOrderObject->memberObject,false);
				// 履歴メモを追記する
				// 新旧の差分をハッシュで取得
				$differenceHash	= $shoppingOrderObject->getDifference( $request, $oldOrderObject );
				$historyNote	= str_replace('Array','',print_r($differenceHash,true));
				$historyNote	= str_replace("\r\n",' ',$historyNote);
				$historyNote	= str_replace("\r",' ',$historyNote);
				$historyNote	= str_replace("\n",' ',$historyNote);
				while(strpos($historyNote,'  ') !== false){
					$historyNote	= str_replace('  ',' ',$historyNote);
				}
				if(!$shoppingOrderObject->writeHistoryNote( $request, '内容変更][変更前の差分', $historyNote, '', $loginUserObject )){
					$request->addLocaledError('shopping.error.order.failtohistory',SPIDER_LOG_LEVEL_FATAL,array(''));
				}
			} else {
				$request->addLocaledError('database2.error.update',SPIDER_LOG_LEVEL_ERROR,array(''));
			}
		} else {
			$request->addLocaledError('database2.error.update',SPIDER_LOG_LEVEL_FATAL,array(''));
		}
		// エラーがない場合の決済処理
		if( !$request->isError() ) {
			if( $shoppingOrderObject->settle_method == $oldOrderObject->settle_method ) {
				// 決済方法が変更されていない場合
				if( $shoppingOrderObject->payment_total == $oldOrderObject->payment_total ) {
					// 金額が変更されていないなら決済に関する処理はおこなわない
				} else if( $settleMethodObject->enableChangeAmount( $shoppingOrderObject ) ){
					// 金額変更されていてプラグインが金額変更に対応しているなら変更
					$settleMethodObject->settleChangeAmount( $request, $shoppingOrderObject );
				} else {
					// 金額が変更されていてプラグインが金額変更未対応ならキャンセルして再決済
					if( $shoppingOrderObject->settleCancel( $request, $shoppingOrderObject ) ) {
						$this->newSettleExecute( $request, $shoppingOrderObject , $settleMethodObject );
					}
				}
			} else {
				// 古い決済方法でキャンセルする
				if( $oldSettleMethodObject->settleCancel( $request, $shoppingOrderObject ) ) {
					// 新しい決済方法で新規決済をおこなう
					$this->newSettleExecute( $request, $shoppingOrderObject , $settleMethodObject );
				}
			}
		}
		if( !$request->isError() ) {
			// 1.1.x互換
			shopping_order_Optimize::_setEnvironmentFor11x( $request, $shoppingOrderObject );
			// セッションを削除する
			$request->removeSession($sessionObjectName,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_OBJECT,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_PURCHASER,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_ADDRESS,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_ADDRESS_OPTION,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_SETTLEMENT,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_OPTIONS,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_ITEMOPTIONS,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_COMMENT,SPIDER_SESSION_SCOPE_GLOBAL);
			$request->removeSession(SHOPPING_SESSION_NAME_ORDER_CONFIRM_DELIVERY_OLD,SPIDER_SESSION_SCOPE_GLOBAL);
			// メール通知の判断
			$needSendMail	= false;
			if( 2 == $operationType ) {
				$needSendMail	= true;
			} else if( preg_match('/^([tT](|[rR][uU][eE])|[yY](|[eE][sS]))$/',$isNotify) > 0 ){
				$needSendMail	= true;
			}
			// 送信情報の整形
			require_once(dirname(dirname(__FILE__)).'/Optimize.class.php');
			shopping_order_Optimize::_setEnvironmentFor11x( $request, $shoppingOrderObject );
			shopping_order_Optimize::_setEnvironmentFor11x( $request, $oldOrderObject );
			// メール通知
			if( $needSendMail ) {
				// 申し込み者へのメール通知
				$memberObject	= & $shoppingOrderObject->memberObject;
				$targetMail		= null;
				if( ( $shoppingOrderObject->mail_flag == 2 || $shoppingOrderObject->mail_flag == 12 )
				&& strlen($memberObject->mb_mail) > 0 ) {
					$targetMail	= $memberObject->mb_mail;
				} else if( strlen($memberObject->pc_mail) > 0 ) {
					$targetMail	= $memberObject->pc_mail;
				}
				if( is_null($targetMail) ) {
					$request->addLocaledError('shopping.error.order.invalidmail',SPIDER_LOG_LEVEL_FATAL,array(''));
				} else {
					// 変更前の情報の文章を作成
					$orgTemplateInfo	= $oldOrderObject->getMailTemplateInformation( $request,'SHOPMAILODRINFO',$targetMail);
					$replaceHash			= array();
					$replaceHash['old_order_information']	= $orgTemplateInfo['body'];
					$mailTemplateId	= 'SHOPMAILTHANKSMD';
					if( 2 == $operationType ){
						// 申込者変更の場合のメールテンプレート
					} else {
						// オーナー側変更の場合のメールテンプレート
						$mailTemplateId	= 'SHOPMAILTHANKSMA';
					}
					if( $shoppingOrderObject->sendInformationMail( $request, $targetMail, $mailTemplateId, null, '', $replaceHash, $loginUserObject ) ) {
					} else {
						$request->addLocaledError('shopping.error.order.failtonotifymail',SPIDER_LOG_LEVEL_FATAL,array(''));
					}
				}
			}
			// 管理者・オーナーへのメールテンプレート
			$mailTemplateId	= 'SHOPMAILNOTIFYMD';
			if( 2 == $operationType ){
				// 申込者変更の場合のメールテンプレート
			} else {
				// オーナー側変更の場合のメールテンプレート
				$mailTemplateId	= 'SHOPMAILNOTIFYMA';
			}
			// オーナーへのメール通知
			if( !$request->isError() ) {
				$ownerMemberObjectArray	= $shoppingOrderObject->getProducerMemberObjectArray( $request );
				foreach( $ownerMemberObjectArray as $ownerMemberObject ) {
					// オーナーへのメールはＰＣを優先
					$email	= $ownerMemberObject->pc_mail;
					if( strlen($email) == 0 && strlen($ownerMemberObject->mb_mail) > 0 ) {
						$email	= $ownerMemberObject->mb_mail;
					}
					if( strlen($email) > 0 ) {
						$orgTemplateInfo	= $oldOrderObject->getMailTemplateInformation( $request,'SHOPMAILODRINFO',$email);
						$replaceHash			= array();
						$replaceHash['old_order_information']	= $orgTemplateInfo['body'];
						if($shoppingOrderObject->sendInformationMail( $request, $email, $mailTemplateId, null, '', $replaceHash, $loginUserObject ) ) {
						} else {
							$request->addLocaledError('shopping.error.order.failtoownermail',SPIDER_LOG_LEVEL_FATAL,array(''));
						}
					}
				}
			}
			// 管理者に通知メール
			if( !$request->isError() ) {
				spider_Controller::loadClassDefinition('util_Mail');
				$mailAddressArray	= util_Mail::divideCsvEmail( SHOPPING_MAIL_ADDRESS_NOTIFY );
				foreach( $mailAddressArray as $addNum => $address ) {
					$orgTemplateInfo	= $oldOrderObject->getMailTemplateInformation( $request,'SHOPMAILODRINFO',SHOPPING_MAIL_ADDRESS_NOTIFY);
					$replaceHash			= array();
					$replaceHash['old_order_information']	= $orgTemplateInfo['body'];
					if( $shoppingOrderObject->sendInformationMail( $request, $address, $mailTemplateId, null, '', $replaceHash, $loginUserObject ) ) {
					} else {
						$request->addLocaledError('shopping.error.order.failtoadminmail',SPIDER_LOG_LEVEL_FATAL,array(''));
						break;
					}
				}
			}
		}
		$request->setAttribute('shopping.order.orderObject',	$shoppingOrderObject );
		$removeCart = true;
		$request->setAttribute('shopping.order.removeCart',$removeCart);
	}
	/**
	 * 新規決済をおこなう
	 */
	function newSettleExecute( & $request, & $shoppingOrderObject , & $settleMethodObject ) {
		$dbo	= $request->getAttribute( 'dbo' );
		// 新しい決済方法で決済する
		if( $settleMethodObject->execute( $request, $shoppingOrderObject ) ) {
			if( !$settleMethodObject->needComplete() ) {
				// 決済処理完了ステータスにする
				$shoppingOrderObject->status_flag	= $settleMethodObject->statusNomal;
				$shoppingOrderObject->status_settle	= $settleMethodObject->statusSettle;
				$sql	= 'UPDATE '.TABLE_NAME_SHOPPING_ORDER
					.' SET status_flag='.$settleMethodObject->statusNomal
					.' ,status_settle='.$settleMethodObject->statusSettle
					.' WHERE order_id='.$dbo->quote($shoppingOrderObject->order_id);
				$dbo->query($sql);
			} else {
				// 決済処理前はエラーステータスにする（編集で無効にしてしまわないため）
				$shoppingOrderObject->status_flag	= $settleMethodObject->statusError;
				$shoppingOrderObject->status_settle	= 0;
				$sql	= 'UPDATE '.TABLE_NAME_SHOPPING_ORDER
					.' SET status_flag='.$settleMethodObject->statusError
					.' ,status_settle=0'
					.' WHERE order_id='.$dbo->quote($shoppingOrderObject->order_id);
				$dbo->query($sql);
			}
		} else {
			// プラグイン処理異常時
			$shoppingOrderObject->status_flag	= $settleMethodObject->statusError;
			$shoppingOrderObject->status_settle	= 201;
			$sql	= 'UPDATE '.TABLE_NAME_SHOPPING_ORDER
				.' SET status_flag='.$settleMethodObject->statusError
				.' ,status_settle=201'
				.' WHERE order_id='.$dbo->quote($shoppingOrderObject->order_id);
			$dbo->query($sql);
			$request->addLocaledError('shopping.error.order.failtosettle',SPIDER_LOG_LEVEL_FATAL,array($sql));
		}
		if( $request->isError() ) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * モジュールの後処理を行います。
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function post_process( & $request ) {
		$shoppingOrderObject	= null;
		$request->setAttribute('shopping.order.orderObject',$shoppingOrderObject);
	}
}
?>