<?php
/*
 * shopping/order/step/Execute.class.php
 * 
 * CopyRight(C) 2010 MDS.Co.,Ltd. All Right Reserved
 * URL: http://www.mds-tools.com/
 * Address: 311, 25 Sankyo Building, Toshima-ku Higashi Ikebukuro 1-48-10, Tokyo, Japan.
 * Telephone: 03-5950-0525
 * Mail: info@md-systems.net
 * Auther: Masanori Nakashima
 * Last Update: 2010-10-04
 */
require_once(dirname(dirname(dirname(__FILE__)))
.DIRECTORY_SEPARATOR.'PackageConfig.class.php' );
require_once( dirname(dirname(dirname(__FILE__)))
.DIRECTORY_SEPARATOR.'DaoShoppingOrder.class.php' );
class shopping_order_step_Execute extends system_login_ModuleBase {
	/**
	 * コンストラクタ
	 */
	function shopping_order_step_Execute() {
		array_push($this->require_module_array,'shopping.LoadConfig');
		array_push($this->require_module_array,'database2.Transaction');
		array_push($this->require_module_array,'shopping.order.option.LoadList');
		array_push($this->require_module_array,'shopping.order.settlement.LoadListExists');
		array_push($this->require_module_array,'shopping.order.settlement.LoadList');
		if( isset($_GET['shpoi']) && strlen(trim($_GET['shpoi'])) > 0 ) {
			array_push($this->require_module_array,'shopping.order.CartAdmin');
		} else {
			array_push($this->require_module_array,'shopping.order.Cart');
		}
		array_push($this->require_module_array,'shopping.order.step.ConfirmStock');
		array_push($this->require_module_array,'shopping.order.step.ConfirmAll');
		array_push($this->require_module_array,'shopping.order.Optimize');
	}
	/**
	 * executeメソッド
	 */
	function execute( & $request ) {
		$dbo					= $request->getAttribute( 'dbo' );
		$loginUserObject		= $this->getLoginUserObject( $request );
		// カートオブジェクトの取得
		$shoppingOrderObject	= $request->getAttribute('shopping.order.orderObject');
		
		// 利用可能な決済方法の読み込み
		$settleMethodObject			= 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;
			}
		}
		if( is_null($settleMethodObject) ) {
			$request->addLocaledError('shopping.error.order.failtoloadplugin',SPIDER_LOG_LEVEL_ERROR,array());
			return;
		}

		// メンバーテーブル操作
		$this->saveMemberObject( $request, $shoppingOrderObject );
		
		// 申し込み情報をデータベースに登録する
		if( !$request->isError() ) {
			if( strlen($shoppingOrderObject->order_number) == 0 ) {
				// データベースにインサートされていない場合はインサート
				$shoppingOrderObject->member_id		= $shoppingOrderObject->memberObject->member_id;
				$shoppingOrderObject->order_id	= '';
				if( is_object($loginUserObject)
				&& SYSTEM_LOGIN_USER_ADMINISTRATORS == $loginUserObject->getLoginGroupLevel() ) {
					// 管理者購入の場合は管理者IDをオーナーに入れる
					$shoppingOrderObject->owner_id		= $loginUserObject->getUniqueId();
					$shoppingOrderObject->modifier_id	= $loginUserObject->getUniqueId();
				} else {
					// ユーザー購入の場合は顧客IDをオーナーに入れる
					$shoppingOrderObject->owner_id		= $shoppingOrderObject->member_id;
					$shoppingOrderObject->modifier_id	= $shoppingOrderObject->member_id;
				} 
				$orderIdFormat	= 'SPODRA{num:6}';
				if( defined('SHOPPING_ORDER_ID_FORMAT')
					&& strlen(SHOPPING_ORDER_ID_FORMAT) > 0
					&& preg_match('/^[0-9A-Z]*(|\\{[yYmn]\\})*[0-9A-Z]*\\{num\\:[3-6]\\}$/',SHOPPING_ORDER_ID_FORMAT) > 0 ) {
					$orderIdFormat	= SHOPPING_ORDER_ID_FORMAT;
					$orderIdFormat	= str_replace('{Y}',date('Y'),$orderIdFormat);
					$orderIdFormat	= str_replace('{y}',date('y'),$orderIdFormat);
					$orderIdFormat	= str_replace('{m}',date('m'),$orderIdFormat);
				}
				if( $dbo->setNextId( $shoppingOrderObject, $orderIdFormat ) ) {
					$shoppingOrderObject->updated_date		= date('Y-m-d H:i:s');
					if( strlen($shoppingOrderObject->order_date) == 0 ) {
						$shoppingOrderObject->order_date	= date('Y-m-d H:i:s');
					}
					$shoppingOrderObject->registered_date	= date('Y-m-d H:i:s');
					if( $dbo->insert($shoppingOrderObject) ) {
						$sql	= 'SELECT order_number FROM '.TABLE_NAME_SHOPPING_ORDER
						.' WHERE order_id='.$dbo->quote($shoppingOrderObject->order_id);
						$shoppingOrderObject->order_number	= $dbo->queryOne($sql);
					} else {
						$request->addLocaledError('shopping.error.order.save',SPIDER_LOG_LEVEL_ERROR,array());
					}
				} else {
					$request->addLocaledError('shopping.error.order.createid',SPIDER_LOG_LEVEL_ERROR,array());
				}
			} else {
				// データベースにインサート済みの場合はアップデート
				$shoppingOrderObject->member_id		= $shoppingOrderObject->memberObject->member_id;
				$shoppingOrderObject->updated_date		= date('Y-m-d H:i:s');
				if( strlen($shoppingOrderObject->order_date) == 0 ) {
					$shoppingOrderObject->order_date	= date('Y-m-d H:i:s');
				}
				if( is_object($loginUserObject)
				&& SYSTEM_LOGIN_USER_ADMINISTRATORS == $loginUserObject->getLoginGroupLevel() ) {
					// 管理者購入の場合は管理者IDを更新者に入れる
					$shoppingOrderObject->modifier_id	= $loginUserObject->getUniqueId();
				} else {
					// ユーザー購入の場合は顧客IDを更新者に入れる
					$shoppingOrderObject->modifier_id	= $shoppingOrderObject->member_id;
				} 
				// ORDER番号は戻ってきていた場合に都度捨て番にして再発行
				$shoppingOrderObject->order_id			= '';
				$orderIdFormat	= 'SPODRA{num:6}';
				if( defined('SHOPPING_ORDER_ID_FORMAT')
					&& strlen(SHOPPING_ORDER_ID_FORMAT) > 0
					&& preg_match('/^[0-9A-Z]*(|\\{[yYmn]\\})*[0-9A-Z]*\\{num\\:[3-6]\\}$/',SHOPPING_ORDER_ID_FORMAT) > 0 ) {
					$orderIdFormat	= SHOPPING_ORDER_ID_FORMAT;
					$orderIdFormat	= str_replace('{Y}',date('Y'),$orderIdFormat);
					$orderIdFormat	= str_replace('{y}',date('y'),$orderIdFormat);
					$orderIdFormat	= str_replace('{m}',date('m'),$orderIdFormat);
				}
				if( $dbo->setNextId( $shoppingOrderObject, $orderIdFormat ) ) {
					if( $dbo->update($shoppingOrderObject) ) {
					} else {
						$request->addLocaledError('shopping.error.order.save',SPIDER_LOG_LEVEL_ERROR,array());
					}
				} else {
					$request->addLocaledError('shopping.error.order.renewid',SPIDER_LOG_LEVEL_ERROR,array());
				}
			}
			if( $request->isError() ) {
				// ORDER情報の保存に失敗したら継続しない
				return false;
			}
		} else {
			// member情報保存で失敗していたら終了
			return false;
		}
		
		// 決済プラグインで状態制御をおこなう
		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->statusReady;
				$shoppingOrderObject->status_settle	= 0;
				$sql	= 'UPDATE '.TABLE_NAME_SHOPPING_ORDER
					.' SET status_flag='.$settleMethodObject->statusReady
					.' ,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( !$settleMethodObject->needComplete() ) {
			// complete画面が必要ない場合
			// 成果処理と在庫・ポイント処理を行う
			if( !$request->isError() ) {
				shopping_order_step_Execute::processComplete( $request, $shoppingOrderObject );
			}
			// 状態に応じてメール送信
			if( !$request->isError() ) {
				shopping_order_step_Execute::sendCompleteMail( $request, $shoppingOrderObject );
			}
		} else {
			// complete画面を必要とする決済の場合はセッションに登録を継続
			$shoppingOrderObject->columnErrorHash	= array();
			$request->setSession(SHOPPING_SESSION_NAME_ORDER_OBJECT,$shoppingOrderObject,SPIDER_SESSION_SCOPE_GLOBAL);
			// 必要な画面表示登録
			$executeHTML	= $settleMethodObject->getViewExecuteHtml($shoppingOrderObject);
			$request->setAttribute('shopping.order.executeHTML',	$executeHTML );
		}
		
		$needComplete	= $settleMethodObject->needComplete();
		if( $request->isError() ) {
		} else {
			$request->setAttribute('shopping.order.orderObject',	$shoppingOrderObject );
			$removeCart = true;
		}
		$request->setAttribute('shopping.order.removeCart',$removeCart);
		$request->setAttribute('shopping.order.needComplete',	$needComplete );
	}
	/**
	 * 申し込み時のmemberオブジェクト操作をおこなう
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderオブジェクト参照
	 */
	function saveMemberObject( & $request, & $shoppingOrderObject ) {
		$dbo						= $request->getAttribute('dbo');
		$loginUserObject			= $this->getLoginUserObject( $request );
		$memberObject				= & $shoppingOrderObject->memberObject;
		$memberObject->modifier_id	= $memberObject->member_id;
		if( $this->isLogin($request)
		&& SYSTEM_LOGIN_USER_ADMINISTRATORS == $loginUserObject->getLoginGroupLevel() ) {
			$memberObject->modifier_id	= $loginUserObject->getUniqueId();
		}
		// 共通カラム設定
		$memberObject->updated_date		= date('Y-m-d H:i:s');
		$memberObject->optimize();
		// 登録振り分け
		if( $this->isLogin( $request )
		&& SYSTEM_LOGIN_USER_ADMINISTRATORS != $loginUserObject->getLoginGroupLevel()
		&& $memberObject->getUniqueId() == $loginUserObject->getUniqueId() ) {
			// ログイン情報と会員情報が一致する場合は
			$dbo->update($memberObject,false);
		} else if( preg_match('/^[0-9]+$/',$memberObject->member_number) == 0 ) {
			// 個人情報がレコードにないようなら挿入する
			$memberObject->registered_date	= date('Y-m-d H:i:s');
			// 登録者情報
			$memberObject->owner_id		= $memberObject->modifier_id;
			if( $dbo->setNextId( $memberObject, 'MBSA{num:4}' ) ) {
				if( $memberObject->member_class == 0
				|| strlen($memberObject->login_id) == 0 ) {
					// 会員登録しないならログインIDを強制的に会員IDにする
					$memberObject->login_id	= $memberObject->member_id;
				}
				// 状態フラグを0でインサートする
				$memberObject->status_flag	= 0;
				if( $dbo->insert($memberObject, $request) ) {
				} else {
					$request->addLocaledError('shopping.error.order.savemember',SPIDER_LOG_LEVEL_ERROR,array());
				}
			} else {
				$request->addLocaledError('database2.error.setnextid',SPIDER_LOG_LEVEL_ERROR,array());
			}
		} else if( $memberObject->member_class > 0 ) {
			// ログインではなく会員登録する場合
			$memberObject->status_flag	= 0;
			if( $dbo->update($memberObject, true) ) {
			} else {
				$request->addLocaledError('shopping.error.order.savemember',SPIDER_LOG_LEVEL_ERROR,array());
			}
			// ポイントを0に戻す
			$currentPoint	= $memberObject->pointCurrent( $request );
			if( $currentPoint > 0 ) {
				$memberObject->pointChange(
				$request, - $currentPoint, 'レコード再利用：ポイントを一度0に調整',null, $memberObject );
			}
			// 初期ポイントを与える
			if( defined('MEMBER_INITIAL_POINT')
			&& preg_match('/^[0-9]{1,7}$/',MEMBER_INITIAL_POINT) > 0 ) {
				$memberObject->pointChange(
				$request, MEMBER_INITIAL_POINT, '会員登録初期ポイント付与',null, $memberObject );
			}
		} else {
			// 会員登録をしない場合
			$memberObject->login_id	= $memberObject->member_id;
			if( $dbo->update($memberObject, true) ) {
			} else {
				$request->addLocaledError('shopping.error.order.savemember',SPIDER_LOG_LEVEL_ERROR,array());
			}
			// ポイントを0に戻す
			$currentPoint	= $memberObject->pointCurrent( $request );
			if( $currentPoint > 0 ) {
				$memberObject->pointChange(
				$request, - $currentPoint, '会員登録なしの為ポイントを0にします',null, $memberObject );
			}
		}
	}
	/**
	 * 確定時の処理をおこなう静的メソッド
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderオブジェクト参照
	 */
	function processComplete( & $request, & $shoppingOrderObject ) {
		$dbo							= $request->getAttribute('dbo');
		$loginUserObject	= $this->getLoginUserObject( $request );
		$memberObject			= & $shoppingOrderObject->memberObject;
		// 必要に応じてプロモーション成果報告の処理:結果は取得しない
		$shoppingOrderObject->sendRelatedPromotionReportRequest( $request );
		// プロモーションコードの処理
		$promotionTag	= $shoppingOrderObject->getRelatedPromotionComplateHtmlTag( $request );
		$request->setAttribute('shopping.order.promotionTag',	$promotionTag );
		// 在庫を消化する
		$shoppingOrderObject->useUnitStock( $request );
		// ポイントの減算処理
		if( $shoppingOrderObject->point_use > 0 ) {
			$usePoint	= '-'.$shoppingOrderObject->point_use;
			if( $shoppingOrderObject->memberObject->pointChange( $request,
				$usePoint, 'ショッピング利用:'.$shoppingOrderObject->order_id.':'.$shoppingOrderObject->payment_total.'円') ){
			} else {
				$request->addLocaledError('shopping.error.point.failtosave',SPIDER_LOG_LEVEL_ERROR,array());
			}
		}
		// ポイント加算処理は支払済みの場合のみ
		if( $memberObject->member_class > 0
		&& $shoppingOrderObject->point_total > 0
		&& $shoppingOrderObject->status_settle == 101 ) {
			$addPoint	= '+'.$shoppingOrderObject->point_total;
			if( $memberObject->pointChange( $request,
				$addPoint,$GLOBALS['SHOPPING_LABEL_ORDER'].':'.$shoppingOrderObject->order_id.':'.$shoppingOrderObject->payment_total.'円') ){
			} else {
				$request->addLocaledError('shopping.error.point.failtosave',SPIDER_LOG_LEVEL_ERROR,array());
			}
		}
		if( $memberObject->member_class > 0 && $memberObject->status_flag != 101){
			// 状態が承認済みになっていないなら承認済みに変更しパスワードを暗号化する
			$sql	= 'UPDATE '.TABLE_NAME_MEMBER.' SET status_flag=101 '
			.',login_password='.$dbo->quote($memberObject->encodePassword( $request, $memberObject->login_password ))
			.' WHERE member_id='.$dbo->quote($memberObject->member_id);
			if($dbo->query($sql)) {
			} else {
				$request->addLocaledError('shopping.error.order.savemember',SPIDER_LOG_LEVEL_ERROR,array());
			}
		}
		if( $this->isLogin($request) && SYSTEM_LOGIN_USER_ADMINISTRATORS == $loginUserObject->getLoginGroupLevel()){
			// 管理者のログインの場合はなにもしない
		} else if( $memberObject->member_class > 0 ){
			// 管理者でない正規会員以上の場合は状態を承認済みにしログイン状態にする
			$memberObject->setLoginUserAgent($_SERVER['HTTP_USER_AGENT']);
			$memberObject->setLoginRemoteAddress($_SERVER['REMOTE_ADDR']);
			$memberObject->setLastLoginDate(date('Y-m-d H:i:s'));
			$memberObject->registLoginHistory( $request, '0' );
			$memberObject->save( $request );
			$this->setLoginUserObject( $request, $memberObject );
			$request->setAttribute('system.login.logininformation', $memberObject );
			$isLogin	= true;
			$request->setAttribute('system.login.is_login', $isLogin );
		}
		// 完了したらカートオブジェクトを削除する
		$nullObject	= null;
		$request->setAttribute('shopping.order.orderObject',$nullObject);
	}
	/**
	 * 完了時のメール送信する静的メソッド
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderオブジェクト参照
	 */
	function sendCompleteMail( & $request, & $shoppingOrderObject ) {
		$dbo	= $request->getAttribute('dbo');
		spider_Controller::loadClassDefinition('util_Mail');
		// 発生通知先にメール通知する
		if( defined('SHOPPING_MAIL_ADDRESS_NOTIFY') && strlen(SHOPPING_MAIL_ADDRESS_NOTIFY) > 0 ) {
			$mailAddressArray	= util_Mail::divideCsvEmail( SHOPPING_MAIL_ADDRESS_NOTIFY );
			foreach( $mailAddressArray as $addNum => $address ) {
				if( $shoppingOrderObject->sendInformationMail( $request, $address, 'SHOPMAILNOTIFYNW', null, '', array(), null ) ) {
				} else {
					$request->addLocaledError('shopping.error.order.failtoadminmail',SPIDER_LOG_LEVEL_FATAL,array(''));
					break;
				}
			}
		}
		// 商品の所有者が会員なら通知メールを通知
		if( !$request->isError() ) {
			$ownerMemberObjectArray	= $shoppingOrderObject->getProducerMemberObjectArray( $request );
			foreach( $ownerMemberObjectArray as $ownerObject ) {
				// オーナーへのメールはＰＣを優先
				$email	= $ownerObject->pc_mail;
				if( strlen($email) == 0 && strlen($ownerObject->mb_mail) > 0 ) {
					$email	= $ownerObject->mb_mail;
				}
				if( strlen($email) > 0 ) {
					if($shoppingOrderObject->sendInformationMail( $request, $email, 'SHOPMAILNOTIFYNW', null, '', array(), null ) ) {
					} else {
						$request->addLocaledError('shopping.error.order.failtoownermail',SPIDER_LOG_LEVEL_FATAL,array(''));
						break;
					}
				}
			}
		}
		// 購入者宛ての完了メールを送信
		if( $shoppingOrderObject->mail_flag > 0 ) {
			if( strlen($shoppingOrderObject->email) > 0 ) {
				if( $shoppingOrderObject->sendInformationMail( $request, $shoppingOrderObject->email, 'SHOPMAILTHANKSNW', null, '', array(), null ) ) {
				} else {
					$request->addLocaledError('shopping.error.order.failtonotifymail',SPIDER_LOG_LEVEL_FATAL,array(''));
				}
			} else {
				$request->addLocaledError('shopping.error.order.invalidmail',SPIDER_LOG_LEVEL_FATAL,array(''));
			}
		}
		// 会員登録完了通知が必要なら送信
		if( $shoppingOrderObject->mail_flag >= 10 ) {
			if( strlen($shoppingOrderObject->email) > 0 ) {
				$mailTemplateObject	= spider_Controller::createObject('member_DaoMemberMailTemplate');
				if( $dbo->loadById($mailTemplateObject,'MEMBERJOINCMP')) {
					$memberObject	= & $shoppingOrderObject->memberObject;
					$replaceWordHash					= array();
					$replaceWordHash['member']			= $memberObject;
					$replaceWordHash['url_complete']	= '';
					$replaceWordHash['complete_url']	= '';
					$deliveryStatus	= $mailTemplateObject->sendMail( $request, $shoppingOrderObject->email, $replaceWordHash );
					if( 1 != $deliveryStatus ) {
						$request->addLocaledError('shopping.error.order.failtonotifymail',SPIDER_LOG_LEVEL_FATAL,array(''));
					}
				} else {
					$request->addLocaledError('member.error.mail.template.notfound',SPIDER_LOG_LEVEL_FATAL,array('MEMBERJOINCMP'));
				}
			} else {
				$request->addLocaledError('shopping.error.order.invalidmail',SPIDER_LOG_LEVEL_FATAL,array(''));
			}
		}
	}
	/**
	 * カンマ区切りに分割されたメールアドレスを配列で取得します
	 */
	function _divideEmail2Hash( $mailCsvString ) {
		$addressArray	= array();
		if( strpos($mailCsvString,',') !== false ) {
			$tmpArray	= explode(',',trim($mailCsvString));
			foreach( $tmpArray as $address ) {
				$address	= trim($address);
				if( strlen($address) > 0 ) {
					array_push($addressArray,$address);
				}
			}
		} else if( strlen(trim($mailCsvString)) > 0 ) {
			array_push($addressArray,trim($mailCsvString));
		}
		return $addressArray;
	}
	/**
	 * モジュールの後処理を行います。
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function post_process( & $request ) {
		$shoppingOrderObject	= null;
		$request->setAttribute('shopping.order.orderObject',$shoppingOrderObject);
	}
}
?>