<?php
/*
 * shopping/DaoShoppingOrderAddress.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-09-17
 */
require_once( dirname(__FILE__)
.DIRECTORY_SEPARATOR.'PackageConfig.class.php' );
require_once( dirname(dirname( __FILE__ ))
.DIRECTORY_SEPARATOR.'database2'
.DIRECTORY_SEPARATOR.'AbstractData.class.php' );
require_once( dirname(dirname( __FILE__ ))
.DIRECTORY_SEPARATOR.'system'
.DIRECTORY_SEPARATOR.'DataFileWriter.class.php' );
require_once( dirname(__FILE__)
.DIRECTORY_SEPARATOR.'DaoShoppingOrderItem.class.php' );
/**
 * shopping_DaoShoppingOrderAddress
 * shoppingパッケージ データアクセスオブジェクトクラス shopping_order_itemテーブル用
 */
class shopping_DaoShoppingOrderAddress extends database2_AbstractData {
	/** 番号	*/
	var $address_number;
	/** ID	*/
	var $address_id;
	/** 注文番号	*/
	var $order_id;
	/** 宛先番号	*/
	var $address_order	= 0;
	/** 宛先	*/
	var $address_name;
	/** 宛先フリガナ	*/
	var $address_kana;
	/** 宛先組織名	*/
	var $company_name;
	/** 宛先部署名	*/
	var $section_name;
	/** 宛先郵便番号	*/
	var $zip_code;
	/** 宛先都道府県番号	*/
	var $prefecture_number;
	/** 宛先	住所*/
	var $address;
	/** 宛先建物部屋番号	*/
	var $building;
	/** 宛先電話番号	*/
	var $telephone_number;
	/** 宛先FAX番号	*/
	var $faximili_number;
	/** 宛先携帯番号	*/
	var $mobile_number;
	/** 宛先メールアドレス	*/
	var $email;
	/** 包装タイプ文字列	*/
	var $wrapping_type;
	/** 包装料金	*/
	var $wrapping_price	= 0;
	/** 包装文言１	*/
	var $wrapping_words1;
	/** 包装文言２	*/
	var $wrapping_words2;
	/** 配送希望日	*/
	var $wishful_date;
	/** 配送希望時間帯(文字列)	*/
	var $wishful_time;
	/** 配送料金（注文時）	*/
	var $delivery_price	= 0;
	/** 決済手数料(注文時) */
	var $settle_fee		= 0;
	/** 宛先ごとの備考	*/
	var $order_comment;
	/** 配送伝票番号	*/
	var $delivery_code;
	
	// オブジェクト用メンバ
	/** 配送先に紐づく注文アイテムオブジェクト配列	*/
	var $shoppingOrderItemObjectArray	= array();
	// 郵便番号・電話番号の分活表示用一時プロパティ
	var $zip_code_pre;
	var $zip_code_pst;
	var $telephone_number_area;
	var $telephone_number_city;
	var $telephone_number_local;

	/**
	 * コンストラクタ
	 */
	function shopping_DaoShoppingOrderAddress(){
		$this->shoppingOrderItemObjectArray	= array();
		$this->variablePostFieldNameArray	= array(
			'address_name','address_kana','zip_code','prefecture_number',
			'address','building','telephone_number',
			'wrapping_type','wrapping_words1','wrapping_words2',
			'wishful_date','wishful_time','order_comment',
		);
	}
	/**
	 * 関連情報を読み込み
	 */
	function loadRelation($dbo) {
		$this->shoppingOrderItemObjectArray	= array();
		$sql	= 'SELECT * FROM '.TABLE_NAME_SHOPPING_ORDER_ITEM
			.' WHERE order_id='.$dbo->quote($this->order_id)
			.' AND address_id='.$dbo->quote($this->address_id)
			.' ORDER BY item_number ASC'
		;
		$orderItemObject		= spider_Controller::createObject('shopping_DaoShoppingOrderItem');
		$shoppingOrderItemObjectArray	= $dbo->queryAll( $sql,$orderItemObject,true, true );
		if ( false === $shoppingOrderItemObjectArray ) {
			$this->shoppingOrderItemObjectArray	= array();
		} else {
			$this->shoppingOrderItemObjectArray	= $shoppingOrderItemObjectArray;
		}
		$this->optimize();
	}
	/**
	 * インサート前に行いたい処理
	 * @param MDBObject $dbo MDB2オブジェクトかその互換オブジェクト
	 * @return boolean 成功したらtrue
	 */
	function pre_insert( $dbo ) {
		return true;
	}
	/**
	 * インサート後に行いたい処理
	 * @param MDBObject $dbo MDB2オブジェクトかその互換オブジェクト
	 * @return boolean 成功したらtrue
	 */
	function post_insert( $dbo ) {
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNumber => $shoppingOrderItemObject ) {
				$this->shoppingOrderItemObjectArray[$itemNumber]->order_id		= $this->order_id;
				$this->shoppingOrderItemObjectArray[$itemNumber]->address_id	= $this->address_id;
				if( $dbo->setNextId( $this->shoppingOrderItemObjectArray[$itemNumber], $this->address_id.'{num:4}' ) ) {
					if( $dbo->insert( $this->shoppingOrderItemObjectArray[$itemNumber] ) ) {
					} else if( is_object($dbo->request) ) {
						$dbo->request->addLocaledError('database2.error.insert',SPIDER_LOG_LEVEL_FATAL,array(''));
					}
				} else if( is_object($dbo->request) ) {
					$dbo->request->addLocaledError('database2.error.setnextid',SPIDER_LOG_LEVEL_FATAL,array(''));
				}
			}
		}
		if( is_object($dbo->request) && $dbo->request->isError() ) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * この宛先に注文商品を追加します
	 * @param $shoppingOrderItemObject shopping_DaoShoppingOrderItemオブジェクト
	 */
	function addItem( & $request, $shoppingOrderItemObject, $messagePrefix='' ) {
		if( !is_array($this->shoppingOrderItemObjectArray) ) {
			$this->shoppingOrderItemObjectArray	= array();
		}
		if( count($this->shoppingOrderItemObjectArray) >= 100 ) {
			$request->addLocaledError('shopping.error.cart.overcartcount',SPIDER_LOG_LEVEL_ERROR,array(''));
		} else {
			array_push( $this->shoppingOrderItemObjectArray, $shoppingOrderItemObject );
		}
	}
	/**
	 * この宛先の指定順序のカート内商品を削除します
	 * @param $cartOrder カート内商品順序
	 */
	function dropItem( & $request, $cartOrder ) {
		if( is_array($this->shoppingOrderItemObjectArray)
		&& isset($this->shoppingOrderItemObjectArray[$cartOrder]) ) {
			$newArray	= array();
			foreach( $this->shoppingOrderItemObjectArray as $ord => $itemObject ) {
				if( $cartOrder != $ord ) {
					array_push($newArray,$itemObject);
				}
			}
			$this->shoppingOrderItemObjectArray	= $newArray;
		}
	}
	/**
	 * 現在の注文情報でデータベース上の在庫を消化
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function useUnitStock( & $request ) {
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$this->shoppingOrderItemObjectArray[$itemNum]->useUnitStock( $request );
			}
		}
	}
	/**
	 * 指定販売単位IDの注文数を取得
	 * @param $unitId 販売単位ID
	 * @return 注文個数
	 */
	function getUnitOrderCount( $unitId ) {
		$unitOrderCount	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				if( $shoppingOrderItemObject->unit_id == $unitId ) {
					$unitOrderCount	+= $shoppingOrderItemObject->order_count;
				}
			}
		}
		return $unitOrderCount;
	}
	/**
	 * この宛先に含まれる注文販売単位と個数のハッシュを生成
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $unitIdCountHash （unit_id => 注文数）の連想配列
	 */
	function countOrderUnit( & $request, & $unitIdCountHash ) {
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $num => $shoppingOrderItemObject ) {
				if( isset($unitIdCountHash[$shoppingOrderItemObject->unit_id]) ) {
					$unitIdCountHash[$shoppingOrderItemObject->unit_id]	+= $shoppingOrderItemObject->order_count;
				} else {
					$unitIdCountHash[$shoppingOrderItemObject->unit_id]	= $shoppingOrderItemObject->order_count;
				}
			}
		}
	}
	/**
	 * 表示および計算の為全ての商品販売単位オブジェクトをセットします
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $unitObjectHash 読み込み済み販売単位オブジェクトの連想配列。[unit_id] => shopping_DaoShoppingProductUnit
	 */
	function setAllUnitObject( & $request, & $unitObjectHash ) {
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				if( array_key_exists( $shoppingOrderItemObject->unit_id, $unitObjectHash ) ) {
					$this->shoppingOrderItemObjectArray[$itemNum]->delivery_type	= $unitObjectHash[$shoppingOrderItemObject->unit_id]->delivery_type;
					$this->shoppingOrderItemObjectArray[$itemNum]->shoppingProductUnitObject	= $unitObjectHash[$shoppingOrderItemObject->unit_id];
				} else {
					$unitObject	= $this->shoppingOrderItemObjectArray[$itemNum]->getUnitObject( $request );
					$unitObjectHash[$unitObject->unit_id]	= $unitObject;
				}
			}
		}
	}
	/**
	 * セッション格納の為に全ての商品販売単位オブジェクトをアンセットします
	 */
	function unsetAllUnitObject() {
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$this->shoppingOrderItemObjectArray[$itemNum]->shoppingProductUnitObject	= null;
			}
		}
	}
	/**
	 * 現在の商品販売単位情報を取得して金額を再計算します
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function calculate( & $request, $renew=false ) {
		// 包装料金
		if( $renew ) {
			$this->reloadWrippingInformation( $request );
		}
		// 紐づいた注文商品の再計算
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				// 最新の商品販売単位情報・オプション情報で再計算
				$this->shoppingOrderItemObjectArray[$itemNum]->calculate( $request, $renew );
			}
		}
	}
	/**
	 * この宛先に紐づいた注文商品の販売金額合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalPaymentPrice( & $request ) {
		$totalPrice	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$totalPrice	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalPaymentPrice( $request );
			}
		}
		return $totalPrice;
	}
	/**
	 * この宛先に紐づいた注文商品の販売金額合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalUnitPrice( & $request ) {
		$totalPrice	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$totalPrice	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalUnitPrice( $request );
			}
		}
		return $totalPrice;
	}
	/**
	 * この宛先に紐づいた注文商品のオプション金額合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalOptionPrice( & $request ) {
		$totalPrice	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$totalPrice	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalOptionPrice( $request );
			}
		}
		return $totalPrice;
	}
	/**
	 * この宛先に紐づいた卸金額合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalCost( & $request ) {
		$totalPrice	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$totalPrice	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalCost( $request );
			}
		}
		return $totalPrice;
	}
	/**
	 * この宛先に紐づいた注文商品の卸金額合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalUnitCost( & $request ) {
		$totalPrice	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$totalPrice	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalUnitCost( $request );
			}
		}
		return $totalPrice;
	}
	/**
	 * この宛先に紐づいた注文商品の付与ポイント合計を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getTotalPresentPoint( & $request ) {
		$pointTotal	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$pointTotal	+= $this->shoppingOrderItemObjectArray[$itemNum]->getTotalPoint( $request );
			}
		}
		return $pointTotal;
	}
	/**
	 * この宛先に紐づいた購入情報の指定率の金額を計算して取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $rate int 割合
	 * @param $includeExceptions boolean 割引除外商品を含めるならtrue
	 * @param $includeOptions boolean オプション金額を含めるならtrue
	 * @param $includeDelivery boolean 配送料金を含めるならtrue
	 * @param $includeWrapping boolean 包装料金を含めるならtrue
	 * @param $roundMethod int 0=切り捨て, 1=切り上げ, 2=四捨五入, 3=五捨六入
	 * @param $denominator 分母（デフォルト100)
	 * @return int 金額
	 */
	function calculatePriceRate( & $request, $rate=5, $includeExceptions=false, $includeOptions=false, $includeDelivery=false, $includeWrapping=false, $roundMethod=0, $denominator=100 ) {
		$price	= 0;
		// 注文商品に対する集計
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$price	+= $this->shoppingOrderItemObjectArray[$itemNum]->calculatePriceRate( $request, $rate, $includeExceptions, $includeOptions, $roundMethod, $denominator );
			}
		}
		// 配送料金を含める場合
		if( $includeDelivery ) {
			$price	+= shopping_PackageConfig::_roundNumeric($this->delivery_price * $rate / $denominator, $roundMethod);
		}
		// 包装料金を含める場合
		if( $includeWrapping ) {
			$price	+= shopping_PackageConfig::_roundNumeric($this->wrapping_price * $rate / $denominator, $roundMethod);
		}
		return $price;
	}
	//
	// 包装関連メソッド
	//
	/**
	 * 包装情報を現在の設定から再読み込み
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function reloadWrippingInformation( & $request ) {
		$wrappingInfoHash		= $request->getAttribute('shopping.setting.delivery.wrappingInfoHash');
		if( !is_array($wrappingInfoHash) ) {
			// 配送設定が読み込まれていない場合は強制コール
			require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'setting'
				.DIRECTORY_SEPARATOR.'delivery'.DIRECTORY_SEPARATOR.'Load.class.php');
			shopping_setting_delivery_Load::execute( $request );
			$wrappingInfoHash		= $request->getAttribute('shopping.setting.delivery.wrappingInfoHash');
		}
		if( preg_match('/^[0-9]{1,2}$/', $this->wrapping_type ) > 0 ) {
			// 数字で入力されている場合は設定の行から名前と料金を取得
			if( isset($wrappingInfoHash[$this->wrapping_type])
			&& is_array($wrappingInfoHash[$this->wrapping_type]) ) {
				$infoHash	= $wrappingInfoHash[$this->wrapping_type];
				$this->wrapping_type	= $infoHash['name'];
				$this->wrapping_price	= $infoHash['price'];
				$this->wrapping_cost	= $infoHash['cost'];
			} else {
				$this->wrapping_type	= 'なし';
				$this->wrapping_price	= 0;
				$this->wrapping_cost	= 0;
			}
		} else {
			foreach( $wrappingInfoHash as $key => $infoHash ) {
				if( $infoHash['name'] == $this->wrapping_type ) {
					$this->wrapping_price	= $infoHash['price'];
					$this->wrapping_cost	= $infoHash['cost'];
					break;
				}
			}
		}
	}
	//
	// 配送関連メソッド
	//
	/**
	 * この注文オブジェクトに含まれる配送種別を配列で取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 */
	function getDeliveryTypeArray( & $request ) {
		$deliveryTypeArray	= array();
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				if( is_null( $shoppingOrderItemObject->shoppingProductUnitObject ) ) {
					$this->shoppingOrderItemObjectArray[$itemNum]->getUnitObject( $request );
				}
				if( in_array($shoppingOrderItemObject->shoppingProductUnitObject->delivery_type,$deliveryTypeArray) ) {
				} else {
					array_push( $deliveryTypeArray, $shoppingOrderItemObject->shoppingProductUnitObject->delivery_type );
				}
			}
		}
		return $deliveryTypeArray;
	}
	/**
	 * この宛先が実際の配送を要求するか確認
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @return boolean 配送が必要ならtrue
	 */
	function requireDelivery( & $request ) {
		$deliveryTypeArray	= $this->getDeliveryTypeArray( $request );
		if( in_array( '0', $deliveryTypeArray ) || in_array( '1', $deliveryTypeArray ) ) {
			// 通常便・クール便のいずれかを含むなら配送が必要
			return true;
		}
		return false;
	}
	/**
	 * 配送料金を現在の設定で再計算
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @return 配送料金合計金額
	 */
	function calculateDeliveryPrice( & $request, $renew=false, & $nomalWeightArray, & $coolWeightArray ) {
		if( $renew ) {
			if( strlen($this->prefecture_number) == 0 || !array_key_exists($this->prefecture_number,$GLOBALS['PREFECTURE_HASH']) ) {
				$this->delivery_price	= 0;
				return $this->delivery_price;
			} else if( count($this->shoppingOrderItemObjectArray) == 0 ) {
				$this->delivery_price	= 0;
				return $this->delivery_price;
			}
			$dbo	= $request->getAttribute( 'dbo' );
			$this->delivery_price	= 0;
			if( $this->getTotalPaymentPrice( $request ) >= SHOPPING_DELIVERY_FREE_PRICE ) {
				// この宛先への商品・オプション金額合計が配送無料に達していたら計算しない
				return $this->delivery_price;
			}
			if( $this->requireDelivery( $request )
			&& array_key_exists($this->prefecture_number,$GLOBALS['PREFECTURE_HASH']) ) {
				// 配送が必要で宛先都道府県が設定されていれば重さごとの口数を連想配列で取得
				$deliveryWeightCountHash = $this->getDeliveryWeightCountHash( $request, $nomalWeightArray, $coolWeightArray );
				// 現在の配送料設定をデータベースから取得
				$selectCondition	= array();
				foreach( $deliveryWeightCountHash as $deliveryType => $weightCountHash ) {
					foreach( $weightCountHash as $deliveryWeight => $orderCount ) {
						$str	= '( delivery_type='.$dbo->quote($deliveryType)
						.' AND delivery_weight='.$dbo->quote($deliveryWeight)
						.' AND prefecture_number='.$dbo->quote($this->prefecture_number).' )';
						array_push($selectCondition,$str);
					}
				}
				if( count($selectCondition) > 0 ) {
					$sql	= 'SELECT * FROM '.TABLE_NAME_SHOPPING_DELIVERY_SETTING
					.' WHERE '.implode(' OR ',$selectCondition);
					$resultHash	= $dbo->queryAll( $sql, 'hash' );
					if ( $resultHash === false ) {
						$request->addLocaledError('database2.error.common',SPIDER_LOG_LEVEL_FATAL,array($sql));
						return false;
					} else {
						foreach( $resultHash as $row ) {
							$type	= $row['delivery_type'];
							$weight	= $row['delivery_weight'];
							$price	= $row['delivery_price'];
							$this->delivery_price	+= $deliveryWeightCountHash[$type][$weight] * $price;
						}
					}
				}
			}
		}
		return $this->delivery_price;
	}
	/**
	 * 配送目安値から配送口数を連想配列で取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $nomalWeightArray 通常便配送目安切り分け配列
	 * @param $coolWeightArray クール便配送目安切り分け配列
	 * @return array [配送種別]=> array( [切り分け目安値] => [口数] ) の多次元連想配列
	 */
	function getDeliveryWeightCountHash( & $request, & $nomalWeightArray, & $coolWeightArray ) {
		$dbo	= $request->getAttribute( 'dbo' );
		// 通常便とクール便の目安値設定を取得
		if( is_null($nomalWeightArray) || count($nomalWeightArray)==0
		|| is_null($coolWeightArray) || count($coolWeightArray)==0 ) {
			$addNomal	= false;
			$addCool	= false;
			if( is_null($nomalWeightArray) || count($nomalWeightArray)==0 ){
				$nomalWeightArray	= array();
				$addNomal			= true;
			}
			if( is_null($coolWeightArray) || count($coolWeightArray)==0 ) {
				$coolWeightArray	= array();
				$addCool			= true;
			}
			$sql	= 'SELECT DISTINCT delivery_type, delivery_weight FROM '
			.TABLE_NAME_SHOPPING_DELIVERY_SETTING.' ORDER BY delivery_type ASC, delivery_weight ASC';
			$resultHash	= $dbo->queryAll( $sql, 'hash' );
			if ( $resultHash === false ) {
				return false;
			} else {
				foreach( $resultHash as $row ) {
					$type	= $row['delivery_type'];
					$weight	= $row['delivery_weight'];
					if( '1' == $type && $addCool ) {
						array_push($coolWeightArray,$weight);
					} else if( '0' == $type && $addNomal ) {
						array_push($nomalWeightArray,$weight);
					}
				}
			}
		}
		// 重量計算
		$totalWeightNomal	= 0;
		$totalWeightCool	= 0;
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$weight	= $shoppingOrderItemObject->delivery_weight * $shoppingOrderItemObject->order_count;
				if( '0' == $shoppingOrderItemObject->delivery_type ) {
					$totalWeightNomal += $weight;
				} else if( '1' == $shoppingOrderItemObject->delivery_type ) {
					$totalWeightCool += $weight;
				}
			}
		}
		// 計算
		$deliveryWeightCountHash	= array( '0'=> array(), '1'=>array() );
		if( !defined('SHOPPING_DELIVERY_TYPE_OPERATION')
		|| '0' == SHOPPING_DELIVERY_TYPE_OPERATION ) {
			// クール便を含む場合に全てクール便で配送する設定の場合
			if( $totalWeightCool > 0 ) {
				// クール便を含むならクール便
				$deliveryWeightCountHash['1'] = $this->__createDeliveryWeightCountHash( $request, $totalWeightCool+$totalWeightNomal, $coolWeightArray );
			} else {
				// クール便を含まないなら通常便
				$deliveryWeightCountHash['0'] = $this->__createDeliveryWeightCountHash( $request, $totalWeightNomal, $nomalWeightArray );
			}
		} else {
			// クール便を別口で送付する設定の場合
			// クール便サイズでクール便
			$deliveryWeightCountHash['1'] = $this->__createDeliveryWeightCountHash( $request, $totalWeightCool, $coolWeightArray );
			// 通常便サイズで通常便
			$deliveryWeightCountHash['0'] = $this->__createDeliveryWeightCountHash( $request, $totalWeightNomal, $nomalWeightArray );
		}
		return $deliveryWeightCountHash;
	}
	/**
	 * 重量とタイプから配送口数をハッシュに切り分けて取得する静的メソッド
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $totalWeight 合計重量
	 * @param $weightArray 口数分けに利用する目安値を格納した配列
	 * @return array [切り分け目安値] => [口数]の連想配列
	 */
	function __createDeliveryWeightCountHash( & $request, $totalWeight, $weightArray ) {
		$weightCountHash	= array();
		if( count($weightArray) > 0 ) {
			$maxWeight	= 0;
			while( $totalWeight > 0 ) {
				// 小さいサイズからループして残りの重さが入るか確認
				$ok	= false;
				foreach( $weightArray as $weight ) {
					if( !$ok && $totalWeight <= $weight ) {
						if( !isset($weightCountHash[$weight]) ){
							$weightCountHash[$weight]	= 0;
						}
						// 対象サイズに入るなら
						$totalWeight	= 0;
						$weightCountHash[$weight]	+= 1;
						$ok				= true;
					}
					if( $weight > $maxWeight ) {
						$maxWeight	= $weight;
					}
				}
				if( $totalWeight > 0 ) {
					// サイズで入りきらなかった場合は一番大きいサイズの料金を加算して重量減算
					$totalWeight	-= $maxWeight;
					$weightCountHash[$maxWeight]	+= 1;
				}
			}
		}
		return $weightCountHash;
	}
	//
	// メール文章作成関連
	//
	/**
	 * 注文商品情報メール送信用文字列を注文内容に変換した文字列を取得
	 * @param $request spider_HttpRequestオブジェクト参照
	 * @param $shoppingOrderObject shopping_DaoShoppingOrderオブジェクト
	 * @param $targetAddress 送信先メールアドレス
	 * @param $infoType wholesale/other
	 * @return string 変換後文字列
	 */
	function getMailStrings( & $request, $shoppingOrderObject, $targetAddress, $infoType=null, $searchDataObject=null ) {
		// フォーマット決定
		$formatName	= 'SHOPMAILSUBADDRS';
		// フォーマット文字列取得
		$addressFormatHash	= shopping_PackageConfig::getMailTemplateInformation( $request, $formatName, $targetAddress );
		if( false === $addressFormatHash ) {
			return false;
		}
		$addressFormat	= $addressFormatHash['strings'];
		// 置換
		$replaceHash	= array(
		'address_order'		=> ($this->address_order + 1),
		'address_name'		=> $this->address_name,
		'address_kana'		=> $this->address_kana,
		'email'		=> $this->email,
		'telephone_number'	=> $this->telephone_number,
		'zip_code'			=> $this->zip_code,
		'prefecture_number'	=> $this->prefecture_number,
		'prefecture_name'	=> $GLOBALS['PREFECTURE_HASH'][$this->prefecture_number],
		'address'			=> $this->address,
		'building'			=> $this->building,
		'wishful_date'		=> $this->wishful_date,
		'wishful_time'		=> $this->wishful_time,
		'wrapping_type'		=> $this->wrapping_type,
		'wrapping_words1'	=> $this->wrapping_words1,
		'wrapping_words2'	=> $this->wrapping_words2,
		'order_comment'		=> $this->order_comment,
		'delivery_price'	=> $this->delivery_price,
		'search'	=> $searchDataObject,
		);
		spider_Controller::loadClassDefinition('util_Mail');
		$addressFormat	= util_Mail::replaceFormatStrings( $addressFormat, $replaceHash );
		// 注文内容ごとの文字列取得と置換
		$itemStrings	= '';
		if( is_array($this->shoppingOrderItemObjectArray) ) {
			foreach( $this->shoppingOrderItemObjectArray as $itemNum => $shoppingOrderItemObject ) {
				$itemStrings	.= $shoppingOrderItemObject->getMailStrings( $request, $shoppingOrderObject, $targetAddress, $infoType, $searchDataObject );
			}
		}
		if( strlen(trim($itemStrings)) > 0 ) {
			$addressFormat	= str_replace('{order_items}',$itemStrings,$addressFormat);
		} else {
			$addressFormat	= str_replace("{order_items}\r\n",$itemStrings,$addressFormat);
			$addressFormat	= str_replace("{order_items}\r",$itemStrings,$addressFormat);
			$addressFormat	= str_replace("{order_items}\n",$itemStrings,$addressFormat);
		}
		return $addressFormat;
	}
	//
	// 妥当性検査関連
	//
	/**
	 * 入力値を補正して適正な値にします
	 */
	function optimize() {
		// 宛先郵便番号の分割
		if( strlen($this->zip_code_pre) > 0 || strlen($this->zip_code_pst) > 0 ) {
			$this->zip_code	= $this->zip_code_pre.'-'.$this->zip_code_pst;
		} else {
			list( $this->zip_code_pre,$this->zip_code_pst )	= explode('-',$this->zip_code);
		}
		// 宛先電話番号の分割
		if( strlen($this->telephone_number_area) > 0
			|| strlen($this->telephone_number_city) > 0
			|| strlen($this->telephone_number_local) > 0 ) {
			$this->telephone_number	= $this->telephone_number_area
				.'-'.$this->telephone_number_city
				.'-'.$this->telephone_number_local;
		} else {
			list( $this->telephone_number_area
				,$this->telephone_number_city
				,$this->telephone_number_local )	= explode('-',$this->telephone_number);
		}
	}
	/**
	 * 入力値の妥当性検査を行います
	 * @param $request spider_HttpRequestオブジェクトのインスタンス
	 * @param $messagePrefix エラーメッセージのプレフィックス
	 * @return エラーがあるならfalseを返します
	 */
	function validate( & $request, $messagePrefix='' ) {
		$this->optimize();
		$this->columnErrorHash	= array();

		// 妥当性検査：宛名
		if( strlen($this->address_name) == 0 ) {
			$this->addColumnError($request,'address_name','shopping.error.cart.address.requirename');
		} else if( strlen($this->address_name) > 240 ) {
			$this->addColumnError($request,'address_name','shopping.error.cart.address.invalidname');
		}
		// 妥当性検査：宛名フリガナ
		if( strlen($this->address_kana) == 0 ) {
		} else if( strlen($this->address_kana) > 240 ) {
			$this->addColumnError($request,'address_kana','shopping.error.cart.address.invalidkana');
		}
		// 妥当性検査： 所属組織
		if( strlen($this->company_name) == 0 ) {
		} else if( strlen($this->company_name) > 240 ) {
			$this->addColumnError($request,'address_kana','shopping.error.cart.address.invalidcompany');
		}
		// 妥当性検査： 所属部署・職位
		if( strlen($this->section_name) == 0 ) {
		} else if( strlen($this->section_name) > 240 ) {
			$this->addColumnError($request,'address_kana','shopping.error.cart.address.invalidsection');
		}
		// 妥当性検査：宛先 電話番号
		if( strlen($this->telephone_number) == 0 ) {
			$this->addColumnError($request,'telephone_number','shopping.error.cart.address.requiretelephone');
		} else if( strlen($this->telephone_number) > 16 ) {
			$this->addColumnError($request,'telephone_number','shopping.error.cart.address.invalidtelephone');
		}
		// 妥当性検査：宛先 郵便番号
		if( strlen($this->zip_code) == 0 ) {
		} else if( strlen($this->zip_code) > 16 ) {
			$this->addColumnError($request,'zip_code','shopping.error.cart.zip_code.invalidzip_code');
		}
		// 妥当性検査：宛先 都道府県
		if( strlen($this->prefecture_number) == 0 ) {
			$this->addColumnError($request,'prefecture_number','shopping.error.cart.address.requireprefecture');
		} else if( !array_key_exists($this->prefecture_number,$GLOBALS['PREFECTURE_HASH'] ) && $this->prefecture_number != '0' ) {
			$this->addColumnError($request,'prefecture_number','shopping.error.cart.address.invalidprefecture');
		}
		// 妥当性検査：宛先 住所
		if( strlen($this->address) == 0 ) {
			$this->addColumnError($request,'address','shopping.error.cart.address.requireaddress');
		} else if( strlen($this->address) > 240 ) {
			$this->addColumnError($request,'address','shopping.error.cart.address.invalidaddress');
		}
		// 妥当性検査：宛先 番地・建物
		if( strlen($this->building) == 0 ) {
		} else if( strlen($this->building) > 240 ) {
			$this->addColumnError($request,'building','shopping.error.cart.address.invalidbuilding');
		}
		
		// ラッピング選択肢の読み込み
		$deliveryWrappingHash		= $request->getAttribute('shopping.order.deliveryRappingHash');
		// 妥当性検査:包装
		if( count($deliveryWrappingHash) > 0 ) {
			if( strlen($this->wrapping_type) == 0 ) {
			} else {
				if( preg_match('/^[0-9]{1,3}$/',$this->wrapping_type) > 0 ) {
					// 数字のみで入力されている場合は置き換え
					if( isset($deliveryWrappingHash[$this->wrapping_type]) ) {
						$this->wrapping_type	= $deliveryWrappingHash[$this->wrapping_type]['name'];
					} else {
						$this->wrapping_type	= null;
					}
				}
				if( strlen($this->wrapping_type) > 128 ) {
					$this->addColumnError($request,'wrapping_type','shopping.error.cart.address.invalidwrappingtype');
				}
			}
		}
		// 妥当性検査：包装文言
		if( strlen($this->wrapping_words1) == 0 ) {
		} else if( strlen($this->wrapping_words1) > 240 ) {
			$this->addColumnError($request,'wrapping_words1','shopping.error.cart.address.invalidwrappingwords1');
		}
		if( strlen($this->wrapping_words2) == 0 ) {
		} else if( strlen($this->wrapping_words2) > 240 ) {
			$this->addColumnError($request,'wrapping_words2','shopping.error.cart.address.invalidwrappingwords2');
		}
		// 妥当性検査:お届け希望日
		if( strlen($this->wishful_date) == 0 ) {
		} else if( strlen($this->wishful_date) > 240 ) {
			$this->addColumnError($request,'wishful_date','shopping.error.cart.address.invalidwishfuldate');
		}
		// 妥当性検査:お届け希望時間帯
		if( strlen($this->wishful_time) == 0 ) {
		} else if( strlen($this->wishful_time) > 240 ) {
			$this->addColumnError($request,'wishful_time','shopping.error.cart.address.invalidwishfultime');
		}
		
		if( $request->isError() ) {
			return false;
		}
		return true;
	}
	/**
	 * CSVダウンロードの為のカラム取得メソッド
	 * 項目キーから値を取得します
	 */
	function getColumnString( $key, $quote=true, $filter=null ) {
		$returnColumn	= $this->$key;
		$returnStrings	= '';
		if( is_array($returnColumn) ) {
			$returnStrings	= implode(',',$returnColumn);
		} else {
			if ( $key=='prefecture_number' ) {
				// 宛先都道府県名
				$returnStrings	= $GLOBALS['PREFECTURE_HASH'][$returnColumn];
			} else {
				// 宛先情報の値
				$returnStrings	= $returnColumn;
			}
		}
		if( strlen(trim($filter)) > 0 ) {
			$returnStrings	= mb_convert_kana( $returnStrings, $filter );
		}
		if( $quote ) {
			$returnStrings	= '"'.str_replace('"','""',$returnStrings).'"';
		}
		return $returnStrings;
	}
	/**
	 * オブジェクト比較して要素の違いを抽出します
	 * @param spider_HttpRequest &$request spider_HttpRequestインスタンス参照
	 * @param object $compareObject 比較対象オブジェクト
	 * @return array 違いのキーと値ハッシュ
	 */
	function getDifference( & $request, $compareObject ) {
		$defferenceHash	= parent::getDifference( $request, $compareObject );
		$newDefferenceHash	= array();
		$GLOBALS['SHOPPING_DEFFERENCE_ORDER_ADDRESS_HASH']	= array(
			'address_name'	=>$GLOBALS['SHOPPING_LABEL_ADDRESS_NAME'].'名',
			'address_kana'	=>$GLOBALS['SHOPPING_LABEL_ADDRESS_NAME'].'名フリガナ',
			'zip_code'	=>'郵便場号',
			'prefecture_number'	=>'都道府県',
			'address'	=>'住所・番地',
			'building'	=>'建物・部屋番号',
			'telephone_number'	=>'電話番号',
			'email'	=>'メールアドレス',
			'wrapping_type'	=>'包装文字列',
			'wrapping_price'	=>'包装料金',
			'wrapping_words1'	=>'包装文言１',
			'wrapping_words2'	=>'包装文言２',
			'wishful_date'	=>'配送希望日',
			'wishful_time'	=>'配送希望時間帯',
			'delivery_price'	=>'配送料金',
			'settle_fee'	=>'決済手数料',
			'order_comment'	=>'備考',
			'delivery_code'	=>'配送伝票番号',
			'shoppingOrderItemObjectArray'	=>'予約施設情報',
		);
		foreach( $defferenceHash as $key => $val ){
			if( array_key_exists($key,$GLOBALS['SHOPPING_DEFFERENCE_ORDER_ADDRESS_HASH']) ){
				$newKey	= $GLOBALS['SHOPPING_DEFFERENCE_ORDER_ADDRESS_HASH'][$key];
				$newDefferenceHash[$newKey]	= $val;
			}
		}
		return $newDefferenceHash;
	}
}
?>