Index: branches/version-2_5-dev/data/class/pages/admin/customer/LC_Page_Admin_Customer.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/customer/LC_Page_Admin_Customer.php	(revision 18772)
+++ branches/version-2_5-dev/data/class/pages/admin/customer/LC_Page_Admin_Customer.php	(revision 18815)
@@ -335,5 +335,5 @@
                 case 'delete_all':
                     // 検索結果をすべて削除
-                    $where = "product_id IN (SELECT product_id FROM vw_products_nonclass AS noncls WHERE $where)";
+                    $where = "product_id IN (SELECT product_id FROM SC_Product::alldtlSQL() WHERE $where)";
                     $sqlval['del_flg'] = 1;
                     $objQuery->update("dtb_products", $sqlval, $where, $arrval);
Index: branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail.php	(revision 18798)
+++ branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail.php	(revision 18815)
@@ -535,4 +535,5 @@
 
         // メイン商品の情報取得
+        // FIXME SC_Product クラスを使用した実装
         $sql = "SELECT name, main_image, point_rate, deliv_fee, price01_min, price01_max, price02_min, price02_max FROM vw_products_allclass AS allcls WHERE product_id = ?";
         $main = $objQuery->getAll($sql, array($list_data["sub_product_id" .$j]));
Index: branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail_Preview.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail_Preview.php	(revision 18772)
+++ branches/version-2_5-dev/data/class/pages/admin/mail/LC_Page_Admin_Mail_Preview.php	(revision 18815)
@@ -85,4 +85,5 @@
 
             // メイン商品の情報取得
+            // FIXME SC_Product クラスを使用した実装
             $sql = "SELECT name, main_image, point_rate, deliv_fee, price01_min, price01_max, price02_min, price02_max FROM vw_products_allclass AS allcls WHERE product_id = ?";
             $main = $objQuery->getAll($sql, array($this->list_data["main_product_id"]));
@@ -90,4 +91,5 @@
 
             // サブ商品の情報取得
+            // FIXME SC_Product クラスを使用した実装
             $sql = "SELECT product_id, name, main_list_image, price01_min, price01_max, price02_min, price02_max FROM vw_products_allclass WHERE product_id = ?";
             $k = 0;
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductClass.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductClass.php	(revision 18788)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductClass.php	(revision 18815)
@@ -49,125 +49,44 @@
         $this->tpl_subno = 'product';
         $this->tpl_subtitle = '商品登録(商品規格)';
-
-        $masterData = new SC_DB_MasterData_Ex();
-        $this->arrSRANK = $masterData->getMasterData("mtb_srank");
-        $this->arrDISP = $masterData->getMasterData("mtb_disp");
-        $this->arrCLASS = $masterData->getMasterData("mtb_class");
-        $this->arrSTATUS = $masterData->getMasterData("mtb_status");
-        $this->tpl_onload = "";
-    }
-
-    /**
-     * Page のプロセス.
-     *
-     * @return void
-     */
+    }
+
     function process() {
-        $objView = new SC_AdminView();
-        // 認証可否の判定
-        $objSess = new SC_Session();
-        SC_Utils_Ex::sfIsSuccess($objSess);
-
-        // 検索パラメータの引き継ぎ
-        foreach ($_POST as $key => $val) {
-            if (ereg("^search_", $key)) {
-                $this->arrSearchHidden[$key] = $val;
-            }
-        }
+        $this->authorization();
+
+        $this->arrSearchHidden = $this->createSearchParams($_POST);
 
         $this->tpl_product_id =
             isset($_POST['product_id']) ? $_POST['product_id'] : "" ;
-
         $this->tpl_pageno = isset($_POST['pageno']) ? $_POST['pageno'] : "";
-
         if (!isset($_POST['mode'])) $_POST['mode'] = "";
 
-        switch($_POST['mode']) {
-        // 規格削除要求
-        case 'delete':
-            $objQuery = new SC_Query();
-            $objDb = new SC_Helper_DB_Ex();
-
-            $objQuery->setLimitOffset(1);
-            $where = "product_id = ? AND NOT (classcategory_id1 = 0 AND classcategory_id2 = 0)";
-            $objQuery->setOrder("rank1 DESC, rank2 DESC");
-            $arrRet = $objQuery->select("*", "vw_cross_products_class AS crs_prd", $where, array($_POST['product_id']));
-
-            if(count($arrRet) > 0) {
-
-                $sqlval['product_id'] = $arrRet[0]['product_id'];
-                $sqlval['classcategory_id1'] = '0';
-                $sqlval['classcategory_id2'] = '0';
-                $sqlval['product_code'] = $arrRet[0]['product_code'];
-                $sqlval['stock'] = $arrRet[0]['stock'];
-                $sqlval['price01'] = $arrRet[0]['price01'];
-                $sqlval['price02'] = $arrRet[0]['price02'];
-                $sqlval['creator_id'] = $_SESSION['member_id'];
-                $sqlval['create_date'] = "now()";
-                $sqlval['update_date'] = "now()";
-
-                $objQuery->begin();
-                $where = "product_id = ?";
-                $objQuery->delete("dtb_products_class", $where, array($_POST['product_id']));
-                $sqlval['product_class_id'] = $objQuery->nextVal('dtb_products_class_product_class_id');
-                $objQuery->insert("dtb_products_class", $sqlval);
-
-                $objQuery->commit();
-            }
-            
-	        // 在庫無し商品の非表示対応
-	        if (NOSTOCK_HIDDEN === true) {
-	            // 件数カウントバッチ実行
-	            $objDb->sfCategory_Count($objQuery);
-	        }
-            
-            $this->lfProductClassPage();   // 規格登録ページ
-            break;
-
-        // 編集要求
-        case 'pre_edit':
-            $objQuery = new SC_Query();
-            $where = "product_id = ? AND NOT(classcategory_id1 = 0 AND classcategory_id2 = 0) ";
-            $ret = $objQuery->count("dtb_products_class", $where, array($_POST['product_id']));
-
-            if($ret > 0) {
-                // 規格組み合わせ一覧の取得(DBの値を優先する。)
-                $this->arrClassCat = $this->lfGetClassCatListEdit($_POST['product_id']);
-            }
-            $this->lfProductClassPage();   // 規格登録ページ
-            break;
-            
-        // 規格組み合わせ表示
-        case 'disp':
-            $this->arrForm['select_class_id1'] = $_POST['select_class_id1'];
-            $this->arrForm['select_class_id2'] = $_POST['select_class_id2'];
-
-            $this->arrErr = $this->lfClassError();
-            if (count($this->arrErr) == 0) {
-                // 規格組み合わせ一覧の取得
-                $this->arrClassCat = $this->lfGetClassCatListDisp($_POST['select_class_id1'], $_POST['select_class_id2']);
-            }
-            $this->lfProductClassPage();   // 規格登録ページ
-            break;
-            
-        // 規格登録要求
+        switch ($_POST['mode']) {
         case 'edit':
             // 入力値の変換
             $this->arrForm = $this->lfConvertParam($_POST);
+
             // エラーチェック
             $this->arrErr = $this->lfProductClassError($this->arrForm);
-
-            if(count($this->arrErr) == 0) {
-                // 確認ページ設定
+            if (SC_Utils_Ex::isBlank($this->arrErr)) {
                 $this->tpl_mainpage = 'products/product_class_confirm.tpl';
                 $this->lfProductConfirmPage(); // 確認ページ表示
+
             } else {
-                // 規格組み合わせ一覧の取得
-                $this->arrClassCat = $this->lfGetClassCatListDisp($_POST['class_id1'], $_POST['class_id2'], false);
-                $this->lfProductClassPage();   // 規格登録ページ
+                $this->doPreEdit(false);
             }
             break;
-            
-        // 確認ページからの戻り
+
+        case 'delete':
+            $this->doDelete();
+            break;
+
+        case 'pre_edit':
+            $this->doPreEdit();
+            break;
+
+        case 'disp':
+            $this->doDisp();
+            break;
+
         case 'confirm_return':
             // フォームパラメータの引き継ぎ
@@ -176,23 +95,20 @@
             $this->arrForm['select_class_id1'] = "";
             $this->arrForm['select_class_id2'] = "";
-            // 規格組み合わせ一覧の取得(デフォルト値は出力しない)
-            $this->arrClassCat = $this->lfGetClassCatListDisp($_POST['class_id1'], $_POST['class_id2'], false);
-            $this->lfProductClassPage();   // 規格登録ページ
+            $this->doPreEdit(false);
             break;
-            
+
         case 'complete':
             // 完了ページ設定
             $this->tpl_mainpage = 'products/product_class_complete.tpl';
             // 商品規格の登録
-            $this->lfInsertProductClass($_POST, $_POST['product_id']);
+            $this->registerProductClass($_POST, $_POST['product_id']);
             break;
-            
+
         default:
-            $this->lfProductClassPage();   // 規格登録ページ
-            break;
-        }
-
-        $objView->assignobj($this);
-        $objView->display(MAIN_FRAME);
+        }
+
+        $this->arrClass = $this->getAllClass();
+        $this->arrForm['product_name'] = $this->getProductName($_POST['product_id']);
+        $this->assignView();
     }
 
@@ -206,181 +122,105 @@
     }
 
-    /* 規格登録ページ表示用 */
-    function lfProductClassPage() {
+    /**
+     * 規格の登録または更新を行う.
+     *
+     * TODO dtb_class_combination は, dtb_product_categories に倣って,
+     *      DELETE to INSERT だが, UPDATE を検討する.
+     *
+     * @param array $arrList 入力フォームの内容
+     * @param integer $product_id 登録を行う商品ID
+     */
+    function registerProductClass($arrList, $product_id) {
+        $objQuery =& SC_Query::getSingletonInstance();
         $objDb = new SC_Helper_DB_Ex();
 
-        $this->arrHidden = $_POST;
-        $this->arrHidden['select_class_id1'] = "";
-        $this->arrHidden['select_class_id2'] = "";
-        $arrClass = $objDb->sfGetIDValueList("dtb_class", 'class_id', 'name');
-
-        // 規格分類が登録されていない規格は表示しないようにする。
-        $arrClassCatCount = SC_Utils_Ex::sfGetClassCatCount();
-        if (count($arrClass) > 0) {
-            foreach($arrClass as $key => $val) {
-                if($arrClassCatCount[$key] > 0) {
-                    $this->arrClass[$key] = $arrClass[$key];
-                }
-            }
-        }
-        // 商品名を取得
-        $objQuery = new SC_Query();
-        $product_name = $objQuery->getOne("SELECT name FROM dtb_products WHERE product_id = ?", array($_POST['product_id']));
-        $this->arrForm['product_name'] = $product_name;
-    }
-    
-    /**
-     * デフォルトの表示
-     *
-     * @param object $objQuery
-     * @param integer $product_id 製品のID
-     * @param integer $max 表示される最大値
-     */
-    function lfSetDefaultClassCat($objQuery, $product_id, $max) {
-
-        // デフォルト値の読込
-        $col = "product_class_id, product_code, price01, price02, stock, stock_unlimited";
-        $arrRet = $objQuery->select($col, "dtb_products_class", "product_id = ? AND classcategory_id1 = 0 AND classcategory_id2 = 0", array($product_id));;
-
-        if(count($arrRet) > 0) {
-            $no = 1;
-            for($cnt = 0; $cnt < $max; $cnt++) {
-                $this->arrForm["product_class_id:".$no] = $arrRet[0]['product_class_id'];
-                $this->arrForm["product_code:".$no] = $arrRet[0]['product_code'];
-                $this->arrForm['stock:'.$no] = $arrRet[0]['stock'];
-                $this->arrForm['price01:'.$no] = $arrRet[0]['price01'];
-                $this->arrForm['price02:'.$no] = $arrRet[0]['price02'];
-                $this->arrForm['stock_unlimited:'.$no] = $arrRet[0]['stock_unlimited'];
-                $no++;
-            }
-        }
-    }
-
-    /* 規格組み合わせ一覧の取得 */
-    function lfGetClassCatListDisp($class_id1, $class_id2, $default = true) {
-        $objQuery = new SC_Query();
-
-        if($class_id2 != "") {
-            // 規格1と規格2
-            $sql = "SELECT * ";
-            $sql.= "FROM vw_cross_class AS crs_cls ";
-            $sql.= "WHERE class_id1 = ? AND class_id2 = ? ORDER BY rank1 DESC, rank2 DESC;";
-            $arrRet = $objQuery->getAll($sql, array($class_id1, $class_id2));
-        } else {
-            // 規格1のみ
-            $sql = "SELECT * ";
-            $sql.= "FROM vw_cross_class AS crs_cls ";
-            $sql.= "WHERE class_id1 = ? AND class_id2 = 0 ORDER BY rank1 DESC;";
-            $arrRet = $objQuery->getAll($sql, array($class_id1));
-            
-        }
-
-        $max = count($arrRet);
-
-        if($default) {
-            // デフォルト値を設定
-            $this->lfSetDefaultClassCat($objQuery, $_POST['product_id'], $max);
-        }
-
-        $this->arrForm["class_id1"] = $arrRet[0]['class_id1'];
-        $this->arrForm["class_id2"] = $arrRet[0]['class_id2'];
-        $this->tpl_onload.= "fnCheckAllStockLimit('$max', '" . DISABLED_RGB . "');";
-
-        return $arrRet;
-    }
-
-    /* 規格組み合わせ一覧の取得(編集画面) */
-    function lfGetClassCatListEdit($product_id) {
-        // 既存編集の場合
-        $objQuery = new SC_Query();
-
-        $col = "class_id1, class_id2, name1, name2, rank1, rank2, ";
-        $col.= "product_class_id, product_id, T1_classcategory_id AS classcategory_id1, T2_classcategory_id AS classcategory_id2, ";
-        $col.= "product_code, stock, stock_unlimited, sale_limit, price01, price02, status";
-
-        $sql = "SELECT $col FROM ";
-        $sql.= "( ";
-        $sql.= "SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS T1_classcategory_id, T2.classcategory_id AS T2_classcategory_id, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2 ";
-        $sql.= "FROM dtb_classcategory AS T1, dtb_classcategory AS T2 ";
-        $sql.= "WHERE T1.class_id IN (SELECT class_id1 FROM vw_cross_products_class AS crs_prd WHERE product_id = ? GROUP BY class_id1, class_id2) AND T2.class_id IN (SELECT class_id2 FROM vw_cross_products_class AS crs_prd WHERE product_id = ? GROUP BY class_id1, class_id2)";
-        $sql.= ") AS T1 ";
-
-        $sql.= "LEFT JOIN (SELECT * FROM dtb_products_class WHERE product_id = ?) AS T3 ";
-        $sql.= "ON T1_classcategory_id = T3.classcategory_id1 AND T2_classcategory_id = T3.classcategory_id2 ";
-        $sql.= "ORDER BY rank1 DESC, rank2 DESC";
-
-        $arrList =  $objQuery->getAll($sql, array($product_id, $product_id, $product_id));
-
-        $this->arrForm["class_id1"] = $arrList[0]['class_id1'];
-        $this->arrForm["class_id2"] = $arrList[0]['class_id2'];
-
-        $max = count($arrList);
-
-        // デフォルト値を設定
-        $this->lfSetDefaultClassCat($objQuery, $product_id, $max);
-        $no = 1;
-        for($cnt = 0; $cnt < $max; $cnt++) {
-            $this->arrForm["classcategory_id1:".$no] = $arrList[$cnt]['classcategory_id1'];
-            $this->arrForm["classcategory_id2:".$no] = $arrList[$cnt]['classcategory_id2'];
-            $this->arrForm["product_class_id:".$no] = $arrList[$cnt]['product_class_id'];
-            if($arrList[$cnt]['product_id'] != "") {
-                $this->arrForm["product_code:".$no] = $arrList[$cnt]['product_code'];
-                $this->arrForm['stock:'.$no] = $arrList[$cnt]['stock'];
-                $this->arrForm['stock_unlimited:'.$no] = $arrList[$cnt]['stock_unlimited'];
-                $this->arrForm['price01:'.$no] = $arrList[$cnt]['price01'];
-                $this->arrForm['price02:'.$no] = $arrList[$cnt]['price02'];
-                // JavaScript初期化用文字列
-                $line.= "'check:".$no."',";
-            }
-            $no++;
-        }
-
-        $line = ereg_replace(",$", "", $line);
-        $this->tpl_javascript = "list = new Array($line);";
-        $color = DISABLED_RGB;
-        $this->tpl_onload.= "fnListCheck(list); fnCheckAllStockLimit('$max', '$color');";
-
-        return $arrList;
-    }
-
-    /* 規格の登録 */
-    function lfInsertProductClass($arrList, $product_id) {
-        $objQuery = new SC_Query();
-        $objDb = new SC_Helper_DB_Ex();
-
         $objQuery->begin();
 
-        // 既存規格の削除
-        $where = "product_id = ?";
-        $objQuery->delete("dtb_products_class", $where, array($product_id));
-
-        $cnt = 1;
-        // すべての規格を登録する。
-        while($arrList["classcategory_id1:".$cnt] != "") {
-            if($arrList["check:".$cnt] == 1) {
-                $sqlval = array();
-                $sqlval['product_id'] = $product_id;
-                $sqlval['classcategory_id1'] = $arrList["classcategory_id1:".$cnt];
-                $sqlval['classcategory_id2'] = $arrList["classcategory_id2:".$cnt];
-                if( strlen($arrList["product_class_id:".$cnt]) > 0 ){
-                    $sqlval['product_class_id'] = $arrList["product_class_id:".$cnt];
-                }
-                $sqlval['product_code'] = $arrList["product_code:".$cnt];
-                $sqlval['stock'] = $arrList["stock:".$cnt];
-                $sqlval['stock_unlimited'] = ($arrList["stock_unlimited:".$cnt]) ? '1' : '0';
-                $sqlval['price01'] = $arrList['price01:'.$cnt];
-                $sqlval['price02'] = $arrList['price02:'.$cnt];
-                $sqlval['creator_id'] = $_SESSION['member_id'];
-                $sqlval['create_date'] = "now()";
-                $sqlval['update_date'] = "now()";
-                // INSERTの実行
-                $objQuery->insert("dtb_products_class", $sqlval);
-            }
-            $cnt++;
-        }
-        
+        $productsClass = $objQuery->select("*", "dtb_products_class", "product_id = ?", array($product_id));
+
+        $exists = array();
+        foreach ($productsClass as $val) {
+            $exists[$val['product_class_id']] = $val;
+        }
+
+        $i = 1;
+        while (isset($arrList['classcategory_id1:' . $i])) {
+            $pVal = array();
+            $pVal['product_id'] = $product_id;;
+            $pVal['product_code'] = $arrList["product_code:".$i];
+            $pVal['stock'] = $arrList["stock:".$i];
+            $pVal['stock_unlimited'] = ($arrList["stock_unlimited:".$i]) ? '1' : '0';
+            $pVal['price01'] = $arrList['price01:'.$i];
+            $pVal['price02'] = $arrList['price02:'.$i];
+            $pVal['creator_id'] = $_SESSION['member_id'];
+            $pVal['update_date'] = "now()";
+
+            if($arrList["check:".$i] == 1) {
+                $pVal['del_flg'] = 0;
+            } else {
+                $pVal['del_flg'] = 1;
+            }
+
+            // 更新 or 登録
+            $isUpdate = false;
+            if (!SC_Utils_Ex::isBlank($arrList["product_class_id:".$i])) {
+                $isUpdate = true;
+                // 更新の場合は規格組み合わせを検索し, 削除しておく
+                $class_combination_id = $exists[$arrList["product_class_id:".$i]]['class_combination_id'];
+                $existsCombi = $objQuery->getRow("dtb_class_combination",
+                                                 "*", "class_combination_id = ?",
+                                                 array($class_combination_id));
+
+                $objQuery->delete("dtb_class_combination",
+                                  "class_combination_id IN (?, ?)",
+                                  array($existsCombi['class_combination_id'],
+                                        $existsCombi['parent_class_combination_id']));
+            }
+
+            // 規格組み合わせを登録
+            $cVal1['class_combination_id'] = $objQuery->nextVal('dtb_class_combination_class_combination_id');
+
+            $cVal1['classcategory_id'] = $arrList["classcategory_id1:".$i];
+            $cVal1['level'] = 1;
+            $objQuery->insert("dtb_class_combination", $cVal1);
+
+            $pVal['class_combination_id'] = $cVal1['class_combination_id'];
+
+            // 規格2も登録する場合
+            if (!SC_Utils_Ex::isBlank($arrList["classcategory_id2:".$i])) {
+                $cVal2['class_combination_id'] = $objQuery->nextVal('dtb_class_combination_class_combination_id');
+                $cVal2['classcategory_id'] = $arrList["classcategory_id2:".$i];
+                $cVal2['parent_class_combination_id'] = $cVal1['class_combination_id'];
+                $cVal2['level'] = 2;
+                $objQuery->insert("dtb_class_combination", $cVal2);
+
+                $pVal['class_combination_id'] = $cVal2['class_combination_id'];
+            }
+
+            // 更新
+            if ($isUpdate) {
+                $pVal['product_class_id'] = $arrList["product_class_id:".$i];
+                $objQuery->update("dtb_products_class", $pVal,
+                                  "product_class_id = ?",
+                                  array($pVal['product_class_id']));
+            }
+            // 新規登録
+            else {
+                $pVal['create_date'] = "now()";
+                $pVal['product_class_id'] = $objQuery->nextVal('dtb_products_class_product_class_id');
+                $objQuery->insert("dtb_products_class", $pVal);
+            }
+            $i++;
+        }
+
+        // 規格無し用の商品規格を非表示に
+        $bVal['del_flg'] = 1;
+        $bVal['update_date'] = 'now()';
+        $objQuery->update("dtb_products_class", $bVal,
+                          "product_class_id = ? AND class_combination_id IS NULL",
+                          array($pVal['product_class_id']));
+
         // 件数カウントバッチ実行
         $objDb->sfCategory_Count($objQuery);
-        
         $objQuery->commit();
     }
@@ -467,4 +307,213 @@
         $this->tpl_count = $cnt;
     }
+
+    /**
+     * 規格の組み合わせ一覧を表示する.
+     *
+     * 1. 規格1, 規格2を組み合わせた場合の妥当性を検証する.
+     * 2. 規格1, 規格2における規格分類のすべての組み合わせを取得し,
+     *    該当商品の商品規格の内容を取得し, フォームに設定する.
+     */
+    function doDisp() {
+        $this->arrForm['select_class_id1'] = $_POST['select_class_id1'];
+        $this->arrForm['select_class_id2'] = $_POST['select_class_id2'];
+
+        $this->arrErr = $this->lfClassError();
+        if (SC_Utils_Ex::isBlank($this->arrErr)) {
+            $this->arrClassCat = $this->getAllClassCategory($_POST['select_class_id1'], $_POST['select_class_id2']);
+
+            $productsClass = $this->getProductsClass($_POST['product_id']);
+
+            $total = count($this->arrClassCat);
+            for ($i = 1; $i <= $total; $i++) {
+                foreach ($productsClass as $key => $val) {
+                    $this->arrForm[$key . ":" . $i] = $val;
+                }
+            }
+        }
+        $this->tpl_onload.= "fnCheckAllStockLimit('$total', '" . DISABLED_RGB . "');";
+    }
+
+    /**
+     * 規格編集画面を表示する.
+     */
+    function doPreEdit($existsValue = true) {
+        $existsProductsClass = $this->getProductsClassAndClasscategory($_POST['product_id']);
+        $productsClass = $this->getProductsClass($_POST['product_id']);
+        $this->arrForm["class_id1"] = $existsProductsClass[0]['class_id1'];
+        $this->arrForm["class_id2"] = $existsProductsClass[0]['class_id2'];
+        $this->arrForm['select_class_id1'] = $this->arrForm["class_id1"];
+        $this->arrForm['select_class_id2'] = $this->arrForm["class_id2"];
+
+        $this->arrClassCat = $this->getAllClassCategory($this->arrForm["class_id1"], $this->arrForm["class_id2"]);
+        $total = count($this->arrClassCat);
+        for ($i = 1; $i <= $total; $i++) {
+            if ($existsValue) {
+                foreach ($productsClass as $key => $val) {
+                    $this->arrForm[$key . ":" . $i] = $val;
+                }
+            }
+            foreach ($existsProductsClass[$i] as $key => $val) {
+                $this->arrForm[$key . ":" . $i] = $val;
+            }
+            if (!SC_Utils_Ex::isBlank($this->arrForm['product_id:' . $i])
+                && $this->arrForm["del_flg:" . $i] == 0) {
+                $line .= "'check:" . $i . "',";
+            }
+        }
+
+        $line = preg_replace("/,$/", "", $line);
+        $this->tpl_javascript = "list = new Array($line);";
+        $color = DISABLED_RGB;
+        $this->tpl_onload.= "fnListCheck(list); fnCheckAllStockLimit('$total', '$color');";
+    }
+
+    function doDelete() {
+        $objQuery =& SC_Query::getSingletonInstance();
+
+        $objQuery->begin();
+        $val['del_flg'] = 0;
+        $objQuery->update("dtb_products_class", $val, "product_id = ? AND class_combination_id IS NULL", array($_POST['product_id']));
+
+        $val['del_flg'] = 1;
+        $objQuery->update("dtb_products_class", $val, "product_id = ? AND class_combination_id IS NOT NULL", array($_POST['product_id']));
+
+        $objQuery->commit();
+
+        // 在庫無し商品の非表示対応
+        if (NOSTOCK_HIDDEN === true) {
+            // 件数カウントバッチ実行
+            //$objDb->sfCategory_Count($objQuery);
+        }
+    }
+
+    /**
+     * 規格ID1, 規格ID2の規格分類すべてを取得する.
+     *
+     * @param integer $class_id1 規格ID1
+     * @param integer $class_id2 規格ID2
+     * @return array 規格と規格分類の配列
+     */
+    function getAllClassCategory($class_id1, $class_id2 = null) {
+        $objQuery =& SC_Query::getSingletonInstance();
+
+        $col = "T1.class_id AS class_id1, "
+            . " T1.classcategory_id AS classcategory_id1, "
+            . " T1.name AS name1, "
+            . " T1.rank AS rank1 ";
+
+        if(SC_Utils_Ex::isBlank($class_id2)) {
+            $table = "dtb_classcategory T1 ";
+            $objQuery->setWhere("T1.class_id = ?")
+                     ->setOrder("T1.rank DESC");
+            $val = array($class_id1);
+        } else {
+            $col .= ","
+                . "T2.class_id AS class_id2,"
+                . "T2.classcategory_id AS classcategory_id2,"
+                . "T2.name AS name2,"
+                . "T2.rank AS rank2";
+            $table = "dtb_classcategory AS T1, dtb_classcategory AS T2";
+            $objQuery->setWhere("T1.class_id = ? AND T2.class_id = ?")
+                     ->setOrder("T1.rank DESC, T2.rank DESC");
+            $val = array($class_id1, $class_id2);
+        }
+        return $objQuery->select($col, $table, "", $val);
+    }
+
+    /**
+     * 商品名を取得する.
+     *
+     * @access private
+     * @param integer $product_id 商品ID
+     * @return string 商品名の文字列
+     */
+    function getProductName($product_id) {
+        $objQuery =& SC_Query::getSingletonInstance();
+        return $objQuery->getOne("SELECT name FROM dtb_products WHERE product_id = ?", array($product_id));
+    }
+
+    /**
+     * 検索パラメータを生成する.
+     *
+     * "search_" で始まるパラメータのみを生成して返す.
+     *
+     * TODO パラメータの妥当性検証
+     *
+     * @access private
+     * @param array $params 生成元の POST パラメータ
+     * @return array View にアサインするパラメータの配列
+     */
+    function createSearchParams($params) {
+        $results = array();
+        foreach ($params as $key => $val) {
+            if (substr($key, 0, 7) == "search_") {
+                $results[$key] = $val;
+            }
+        }
+        return $results;
+    }
+
+    /**
+     * 規格分類の登録された, すべての規格を取得する.
+     *
+     * @access private
+     * @return array 規格分類の登録された, すべての規格
+     */
+    function getAllClass() {
+        $objDb = new SC_Helper_DB_Ex();
+        $arrClass = $objDb->sfGetIDValueList("dtb_class", 'class_id', 'name');
+
+        // 規格分類が登録されていない規格は表示しないようにする。
+        $arrClassCatCount = SC_Utils_Ex::sfGetClassCatCount();
+
+        $results = array();
+        if (!SC_Utils_Ex::isBlank($arrClass)) {
+            foreach($arrClass as $key => $val) {
+                if($arrClassCatCount[$key] > 0) {
+                    $results[$key] = $arrClass[$key];
+                }
+            }
+        }
+        return $results;
+    }
+
+    /**
+     * 商品IDをキーにして, 商品規格を取得する.
+     *
+     * @param integer $product_id 商品ID
+     * @return array 商品規格の配列
+     */
+    function getProductsClass($product_id) {
+        $objQuery =& SC_Query::getSingletonInstance();
+        return $objQuery->getRow("dtb_products_class", "*", "product_id = ?", array($product_id));
+    }
+
+    /**
+     * 登録済みの商品規格, 規格, 規格分類を取得する.
+     *
+     * @param integer $product_id 商品ID
+     * @return array 商品規格, 規格, 規格分類の配列
+     */
+    function getProductsClassAndClasscategory($productId) {
+        $objProduct = new SC_Product();
+        return $objProduct->getProductsClassFullByProductId($productId);
+    }
+
+    /**
+     * @access private
+     */
+    function authorization() {
+        SC_Utils_Ex::sfIsSuccess(new SC_Session());
+    }
+
+    /**
+     * @access private
+     */
+    function assignView() {
+        $objView = new SC_AdminView();
+        $objView->assignobj($this);
+        $objView->display(MAIN_FRAME);
+    }
 }
 ?>
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php	(revision 18701)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php	(revision 18815)
@@ -139,4 +139,5 @@
     /* 商品読み込み */
     function lfGetProduct($category_id) {
+        // FIXME SC_Product クラスを使用した実装
         $objQuery = new SC_Query();
         $col = "product_id, name, main_list_image, product_code_min, product_code_max, status";
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products.php	(revision 18792)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products.php	(revision 18815)
@@ -244,5 +244,5 @@
                 $order = "update_date DESC, product_id DESC";
                 $objQuery = new SC_Query();
-
+                $objProduct = new SC_Product();
                 switch($_POST['mode']) {
                     case 'csv':
@@ -253,9 +253,9 @@
                         // CSVを送信する。正常終了の場合、終了。
                         $objCSV->sfDownloadProductsCsv($where, $arrval, $order) && exit;
-                        
                         break;
                     case 'delete_all':
                         // 検索結果をすべて削除
-                        $where = "product_id IN (SELECT product_id FROM vw_products_allclass_detail AS alldtl WHERE $where)";
+                        $where = "product_id IN (SELECT product_id FROM "
+                            . $objProduct->alldtlSQL() . " WHERE $where)";
                         $sqlval['del_flg'] = 1;
                         $objQuery->update("dtb_products", $sqlval, $where, $arrval);
@@ -269,5 +269,5 @@
                         // 読み込む列とテーブルの指定
                         $col = "product_id, name, main_list_image, status, product_code_min, product_code_max, price02_min, price02_max, stock_min, stock_max, stock_unlimited_min, stock_unlimited_max, update_date";
-                        $from = "vw_products_allclass_detail AS alldtl ";
+                        $from = $objProduct->alldtlSQL();
 
                         // 行数の取得
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php	(revision 18788)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php	(revision 18815)
@@ -66,5 +66,4 @@
 
         $masterData = new SC_DB_MasterData_Ex();
-        $this->arrSRANK = $masterData->getMasterData("mtb_srank");
         $this->arrDISP = $masterData->getMasterData("mtb_disp");
         $this->arrCLASS = $masterData->getMasterData("mtb_class");
@@ -292,6 +291,6 @@
 
             if((isset($this->arrForm[$keyname]) && !empty($this->arrForm[$keyname])) && $this->arrForm[$delkey] != 1) {
-                $arrRet = $objQuery->select("main_list_image, product_code_min, name", "vw_products_allclass AS allcls", "product_id = ?", array($this->arrForm[$keyname]));
-                $arrRecommend[$i] = $arrRet[0];
+                $objProduct = new SC_Product();
+                $arrRecommend[$i] = $objProduct->getDetail($this->arrForm[$keyname]);
                 $arrRecommend[$i]['product_id'] = $this->arrForm[$keyname];
                 $arrRecommend[$i]['comment'] = $this->arrForm[$commentkey];
@@ -352,5 +351,21 @@
 
         $col = "*";
-        $table = "vw_products_nonclass AS noncls ";
+        $table = <<< __EOF__
+                      dtb_products AS T1
+            LEFT JOIN (
+                       SELECT product_id AS product_id_sub,
+                              product_code,
+                              price01,
+                              price02,
+                              stock,
+                              stock_unlimited,
+                              sale_limit,
+                              sale_unlimited,
+                              point_rate
+                         FROM dtb_products_class
+                        WHERE class_combination_id IS NULL
+                       ) AS T2
+                     ON T1.product_id = T2.product_id_sub
+__EOF__;
         $where = "product_id = ?";
 
@@ -431,6 +446,6 @@
 
         // 配列の添字を定義
-        $checkArray = array("name", "status", "product_flag",
-                            "main_list_comment", "main_comment", "point_rate",
+        $checkArray = array("name", "status",
+                            "main_list_comment", "main_comment",
                             "deliv_fee", "comment1", "comment2", "comment3",
                             "comment4", "comment5", "comment6", "main_list_comment",
@@ -441,9 +456,6 @@
         $sqlval['name'] = $arrList['name'];
         $sqlval['status'] = $arrList['status'];
-        $sqlval['product_flag'] = $arrList['product_flag'];
         $sqlval['main_list_comment'] = $arrList['main_list_comment'];
         $sqlval['main_comment'] = $arrList['main_comment'];
-        $sqlval['point_rate'] = $arrList['point_rate'];
-        $sqlval['deliv_fee'] = $arrList['deliv_fee'];
         $sqlval['comment1'] = $arrList['comment1'];
         $sqlval['comment2'] = $arrList['comment2'];
@@ -453,5 +465,4 @@
         $sqlval['comment6'] = $arrList['comment6'];
         $sqlval['main_list_comment'] = $arrList['main_list_comment'];
-        $sqlval['sale_limit'] = $arrList['sale_limit'];
         $sqlval['deliv_date_id'] = $arrList['deliv_date_id'];
         $sqlval['maker_id'] = $arrList['maker_id'];
@@ -843,25 +854,26 @@
         if ($objDb->sfHasProductClass($product_id)) return;
 
-        // 既存規格の削除
-        $where = 'product_id = ?';
-        $objQuery->delete('dtb_products_class', $where, array($product_id));
-
         // 配列の添字を定義
-        $checkArray = array('product_class_id', 'product_id', 'product_code', 'stock', 'stock_unlimited', 'price01', 'price02');
+        $checkArray = array('product_class_id', 'product_id', 'product_code', 'stock', 'stock_unlimited', 'price01', 'price02', 'sale_limit', 'sale_unlimited', 'deliv_fee', 'point_rate', 'del_flg');
         $sqlval = SC_Utils_Ex::sfArrayIntersectKeys($arrList, $checkArray);
         $sqlval = SC_Utils_Ex::arrayDefineIndexes($sqlval, $checkArray);
 
+        $sqlval['stock_unlimited'] = $sqlval['stock_unlimited'] ? '1' : '0';
+        $sqlval['creator_id'] = strlen($_SESSION['member_id']) >= 1 ? $_SESSION['member_id'] : '0';
+
         if (strlen($sqlval['product_class_id']) == 0) {
             $sqlval['product_class_id'] = $objQuery->nextVal('dtb_products_class_product_class_id');
-        }
-        $sqlval['classcategory_id1'] = '0';
-        $sqlval['classcategory_id2'] = '0';
-        $sqlval['stock_unlimited'] = $sqlval['stock_unlimited'] ? '1' : '0';
-        $sqlval['creator_id'] = strlen($_SESSION['member_id']) >= 1 ? $_SESSION['member_id'] : '0';
-        $sqlval['create_date'] = 'now()';
-
-        // INSERTの実行
-        $objQuery->insert('dtb_products_class', $sqlval);
-    }
+            $sqlval['create_date'] = 'now()';
+            $sqlval['update_date'] = 'now()';
+            // INSERTの実行
+            $objQuery->insert('dtb_products_class', $sqlval);
+        } else {
+            $sqlval['update_date'] = 'now()';
+            // UPDATEの実行
+            $objQuery->update('dtb_products_class', $sqlval, "product_class_id = ?", array($sqlval['product_class_id']));
+
+        }
+    }
+
     /* ダウンロードファイル情報の初期化 */
     function lfInitDownFile() {
Index: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductSelect.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductSelect.php	(revision 18789)
+++ branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductSelect.php	(revision 18815)
@@ -105,8 +105,4 @@
             $order = "update_date DESC, product_id DESC ";
 
-            // 読み込む列とテーブルの指定
-            $col = "product_id, name, category_id, main_list_image, status, product_code, price01, stock, stock_unlimited";
-            $from = "vw_products_nonclass AS noncls ";
-
             $objQuery = new SC_Query();
             // 行数の取得
@@ -135,9 +131,7 @@
             $objQuery->setOrder($order);
 
-            // viewも絞込みをかける(mysql用)
-            //sfViewWhere("&&noncls_where&&", $where, $arrval, $objQuery->order . " " .  $objQuery->setLimitOffset($page_max, $startno, true));
-
             // 検索結果の取得
-            $this->arrProducts = $objQuery->select($col, $from, $where, $arrval);
+            // FIXME 商品コードの表示
+            $this->arrProducts = $objQuery->select("*", SC_Product::alldtlSQL(), $where, $arrval);
         }
 
Index: branches/version-2_5-dev/data/class/pages/admin/order/LC_Page_Admin_Order_ProductSelect.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/order/LC_Page_Admin_Order_ProductSelect.php	(revision 18789)
+++ branches/version-2_5-dev/data/class/pages/admin/order/LC_Page_Admin_Order_ProductSelect.php	(revision 18815)
@@ -109,4 +109,7 @@
             }
 
+            /*
+             * FIXME パフォーマンスに問題があるため SC_Product::lists() を使用する
+             */
             // 読み込む列とテーブルの指定
             $col = "DISTINCT T1.product_id, product_code_min, product_code_max,"
@@ -115,5 +118,5 @@
                 . " stock_unlimited_max, del_flg, status, name, comment1,"
                 . " comment2, comment3, main_list_comment, main_image,"
-                . " main_list_image, product_flag, deliv_date_id, sale_limit,"
+                . " main_list_image, deliv_date_id, sale_limit,"
                 . " point_rate, create_date, deliv_fee, "
                 . " T4.product_rank, T4.category_rank";
@@ -153,7 +156,4 @@
             $objQuery->setOrder($order);
 
-            // viewも絞込みをかける(mysql用)
-            //sfViewWhere("&&noncls_where&&", $where, $arrval, $objQuery->order . " " .  $objQuery->setLimitOffset($page_max, $startno, true));
-
             // 検索結果の取得
             $this->arrProducts = $objQuery->select($col, $from, $where, $arrval);
@@ -209,4 +209,5 @@
     }
 
+    // FIXME SC_Product クラスを使用する
     /* 規格セレクトボックスの作成 */
     function lfMakeSelect($product_id, $arrClassName, $arrClassCatName) {
Index: branches/version-2_5-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_RecommendSearch.php
===================================================================
--- branches/version-2_5-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_RecommendSearch.php	(revision 18772)
+++ branches/version-2_5-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_RecommendSearch.php	(revision 18815)
@@ -103,8 +103,4 @@
             $order = "update_date DESC, product_id DESC";
 
-            // 読み込む列とテーブルの指定
-            $col = "product_id, name, category_id, main_list_image, status, product_code, price01, stock, stock_unlimited";
-            $from = "vw_products_nonclass AS noncls ";
-
             $objQuery = new SC_Query();
             // 行数の取得
@@ -131,6 +127,7 @@
             $objQuery->setOrder($order);
 
+            // FIXME 商品コードの表示
             // 検索結果の取得
-            $this->arrProducts = $objQuery->select($col, $from, $where, $arrval);
+            $this->arrProducts = $objQuery->select("*", SC_Product::alldtlSQL(), $where, $arrval);
         }
 
