source: branches/version-2_5-dev/data/class/pages/admin/products/LC_Page_Admin_Products_ProductClass.php @ 18815

Revision 18815, 18.7 KB checked in by nanasess, 12 years ago (diff)

規格まわりの内部構成変更に伴う修正(#781)

  • 規格のデータ構造を木構造へ変更
  • 商品検索ロジックを SC_Product クラスへできるだけ集約
  • 以下の VIEW を削除
    • vw_category_count;
    • vw_product_class;
    • vw_products_nonclass;
    • vw_cross_products_class;
    • vw_cross_class;
    • vw_download_class;
  • Property svn:eol-style set to LF
  • Property svn:keywords set to "Id Revision Date"
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2010 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24// {{{ requires
25require_once(CLASS_PATH . "pages/LC_Page.php");
26
27/**
28 * 商品登録(商品規格)のページクラス.
29 *
30 * @package Page
31 * @author LOCKON CO.,LTD.
32 * @version $Id$
33 */
34class LC_Page_Admin_Products_ProductClass extends LC_Page {
35
36    // }}}
37    // {{{ functions
38
39    /**
40     * Page を初期化する.
41     *
42     * @return void
43     */
44    function init() {
45        parent::init();
46        $this->tpl_mainpage = 'products/product_class.tpl';
47        $this->tpl_subnavi = 'products/subnavi.tpl';
48        $this->tpl_mainno = 'products';
49        $this->tpl_subno = 'product';
50        $this->tpl_subtitle = '商品登録(商品規格)';
51    }
52
53    function process() {
54        $this->authorization();
55
56        $this->arrSearchHidden = $this->createSearchParams($_POST);
57
58        $this->tpl_product_id =
59            isset($_POST['product_id']) ? $_POST['product_id'] : "" ;
60        $this->tpl_pageno = isset($_POST['pageno']) ? $_POST['pageno'] : "";
61        if (!isset($_POST['mode'])) $_POST['mode'] = "";
62
63        switch ($_POST['mode']) {
64        case 'edit':
65            // 入力値の変換
66            $this->arrForm = $this->lfConvertParam($_POST);
67
68            // エラーチェック
69            $this->arrErr = $this->lfProductClassError($this->arrForm);
70            if (SC_Utils_Ex::isBlank($this->arrErr)) {
71                $this->tpl_mainpage = 'products/product_class_confirm.tpl';
72                $this->lfProductConfirmPage(); // 確認ページ表示
73
74            } else {
75                $this->doPreEdit(false);
76            }
77            break;
78
79        case 'delete':
80            $this->doDelete();
81            break;
82
83        case 'pre_edit':
84            $this->doPreEdit();
85            break;
86
87        case 'disp':
88            $this->doDisp();
89            break;
90
91        case 'confirm_return':
92            // フォームパラメータの引き継ぎ
93            $this->arrForm = $_POST;
94            // 規格の選択情報は引き継がない。
95            $this->arrForm['select_class_id1'] = "";
96            $this->arrForm['select_class_id2'] = "";
97            $this->doPreEdit(false);
98            break;
99
100        case 'complete':
101            // 完了ページ設定
102            $this->tpl_mainpage = 'products/product_class_complete.tpl';
103            // 商品規格の登録
104            $this->registerProductClass($_POST, $_POST['product_id']);
105            break;
106
107        default:
108        }
109
110        $this->arrClass = $this->getAllClass();
111        $this->arrForm['product_name'] = $this->getProductName($_POST['product_id']);
112        $this->assignView();
113    }
114
115    /**
116     * デストラクタ.
117     *
118     * @return void
119     */
120    function destroy() {
121        parent::destroy();
122    }
123
124    /**
125     * 規格の登録または更新を行う.
126     *
127     * TODO dtb_class_combination は, dtb_product_categories に倣って,
128     *      DELETE to INSERT だが, UPDATE を検討する.
129     *
130     * @param array $arrList 入力フォームの内容
131     * @param integer $product_id 登録を行う商品ID
132     */
133    function registerProductClass($arrList, $product_id) {
134        $objQuery =& SC_Query::getSingletonInstance();
135        $objDb = new SC_Helper_DB_Ex();
136
137        $objQuery->begin();
138
139        $productsClass = $objQuery->select("*", "dtb_products_class", "product_id = ?", array($product_id));
140
141        $exists = array();
142        foreach ($productsClass as $val) {
143            $exists[$val['product_class_id']] = $val;
144        }
145
146        $i = 1;
147        while (isset($arrList['classcategory_id1:' . $i])) {
148            $pVal = array();
149            $pVal['product_id'] = $product_id;;
150            $pVal['product_code'] = $arrList["product_code:".$i];
151            $pVal['stock'] = $arrList["stock:".$i];
152            $pVal['stock_unlimited'] = ($arrList["stock_unlimited:".$i]) ? '1' : '0';
153            $pVal['price01'] = $arrList['price01:'.$i];
154            $pVal['price02'] = $arrList['price02:'.$i];
155            $pVal['creator_id'] = $_SESSION['member_id'];
156            $pVal['update_date'] = "now()";
157
158            if($arrList["check:".$i] == 1) {
159                $pVal['del_flg'] = 0;
160            } else {
161                $pVal['del_flg'] = 1;
162            }
163
164            // 更新 or 登録
165            $isUpdate = false;
166            if (!SC_Utils_Ex::isBlank($arrList["product_class_id:".$i])) {
167                $isUpdate = true;
168                // 更新の場合は規格組み合わせを検索し, 削除しておく
169                $class_combination_id = $exists[$arrList["product_class_id:".$i]]['class_combination_id'];
170                $existsCombi = $objQuery->getRow("dtb_class_combination",
171                                                 "*", "class_combination_id = ?",
172                                                 array($class_combination_id));
173
174                $objQuery->delete("dtb_class_combination",
175                                  "class_combination_id IN (?, ?)",
176                                  array($existsCombi['class_combination_id'],
177                                        $existsCombi['parent_class_combination_id']));
178            }
179
180            // 規格組み合わせを登録
181            $cVal1['class_combination_id'] = $objQuery->nextVal('dtb_class_combination_class_combination_id');
182
183            $cVal1['classcategory_id'] = $arrList["classcategory_id1:".$i];
184            $cVal1['level'] = 1;
185            $objQuery->insert("dtb_class_combination", $cVal1);
186
187            $pVal['class_combination_id'] = $cVal1['class_combination_id'];
188
189            // 規格2も登録する場合
190            if (!SC_Utils_Ex::isBlank($arrList["classcategory_id2:".$i])) {
191                $cVal2['class_combination_id'] = $objQuery->nextVal('dtb_class_combination_class_combination_id');
192                $cVal2['classcategory_id'] = $arrList["classcategory_id2:".$i];
193                $cVal2['parent_class_combination_id'] = $cVal1['class_combination_id'];
194                $cVal2['level'] = 2;
195                $objQuery->insert("dtb_class_combination", $cVal2);
196
197                $pVal['class_combination_id'] = $cVal2['class_combination_id'];
198            }
199
200            // 更新
201            if ($isUpdate) {
202                $pVal['product_class_id'] = $arrList["product_class_id:".$i];
203                $objQuery->update("dtb_products_class", $pVal,
204                                  "product_class_id = ?",
205                                  array($pVal['product_class_id']));
206            }
207            // 新規登録
208            else {
209                $pVal['create_date'] = "now()";
210                $pVal['product_class_id'] = $objQuery->nextVal('dtb_products_class_product_class_id');
211                $objQuery->insert("dtb_products_class", $pVal);
212            }
213            $i++;
214        }
215
216        // 規格無し用の商品規格を非表示に
217        $bVal['del_flg'] = 1;
218        $bVal['update_date'] = 'now()';
219        $objQuery->update("dtb_products_class", $bVal,
220                          "product_class_id = ? AND class_combination_id IS NULL",
221                          array($pVal['product_class_id']));
222
223        // 件数カウントバッチ実行
224        $objDb->sfCategory_Count($objQuery);
225        $objQuery->commit();
226    }
227
228    // 規格選択エラーチェック
229    function lfClassError() {
230        $objErr = new SC_CheckError();
231        $objErr->doFunc(array("規格1", "select_class_id1"), array("EXIST_CHECK"));
232        $objErr->doFunc(array("規格", "select_class_id1", "select_class_id2"), array("TOP_EXIST_CHECK"));
233        $objErr->doFunc(array("規格1", "規格2", "select_class_id1", "select_class_id2"), array("DIFFERENT_CHECK"));
234        return $objErr->arrErr;
235    }
236
237    /* 取得文字列の変換 */
238    function lfConvertParam($array) {
239        /*
240         *  文字列の変換
241         *  K :  「半角(ハンカク)片仮名」を「全角片仮名」に変換
242         *  C :  「全角ひら仮名」を「全角かた仮名」に変換
243         *  V :  濁点付きの文字を一文字に変換。"K","H"と共に使用します
244         *  n :  「全角」数字を「半角(ハンカク)」に変換
245         */
246
247        $no = 1; // FIXME 未定義変数の修正
248        while($array["classcategory_id1:".$no] != "") {
249            $arrConvList["product_code:".$no] = "KVa";
250            $arrConvList["price01:".$no] = "n";
251            $arrConvList["price02:".$no] = "n";
252            $arrConvList["stock:".$no] = "n";
253            $no++;
254        }
255
256        // 文字変換
257        foreach ($arrConvList as $key => $val) {
258            // POSTされてきた値のみ変換する。
259            if(isset($array[$key])) {
260                $array[$key] = mb_convert_kana($array[$key] ,$val);
261            }
262        }
263        return $array;
264    }
265
266    // 商品規格エラーチェック
267    function lfProductClassError($array) {
268        $objErr = new SC_CheckError($array);
269        $no = 1; // FIXME 未定義変数の修正
270        while($array["classcategory_id1:".$no] != "") {
271            if($array["check:".$no] == 1) {
272                $objErr->doFunc(array("商品コード", "product_code:".$no, STEXT_LEN), array("MAX_LENGTH_CHECK"));
273                $objErr->doFunc(array(NORMAL_PRICE_TITLE, "price01:".$no, PRICE_LEN), array("NUM_CHECK", "MAX_LENGTH_CHECK"));
274                $objErr->doFunc(array(SALE_PRICE_TITLE, "price02:".$no, PRICE_LEN), array("EXIST_CHECK", "NUM_CHECK", "MAX_LENGTH_CHECK"));
275
276                if($array["stock_unlimited:".$no] != '1') {
277                    $objErr->doFunc(array("在庫数", "stock:".$no, AMOUNT_LEN), array("EXIST_CHECK", "NUM_CHECK", "MAX_LENGTH_CHECK"));
278                }
279            }
280            if(count($objErr->arrErr) > 0) {
281                $objErr->arrErr["error:".$no] = $objErr->arrErr["product_code:".$no];
282                $objErr->arrErr["error:".$no].= $objErr->arrErr["price01:".$no];
283                $objErr->arrErr["error:".$no].= $objErr->arrErr["price02:".$no];
284                $objErr->arrErr["error:".$no].= $objErr->arrErr["stock:".$no];
285            }
286            $no++;
287        }
288        return $objErr->arrErr;
289    }
290
291    /* 確認ページ表示用 */
292    function lfProductConfirmPage() {
293        $objDb = new SC_Helper_DB_Ex();
294        $this->arrForm['mode'] = 'complete';
295        $this->arrClass = $objDb->sfGetIDValueList("dtb_class", 'class_id', 'name');
296        $cnt = 0;
297        $check = 0;
298        $no = 1;
299        while($_POST["classcategory_id1:".$no] != "") {
300            if($_POST["check:".$no] != "") {
301                $check++;
302            }
303            $no++;
304            $cnt++;
305        }
306        $this->tpl_check = $check;
307        $this->tpl_count = $cnt;
308    }
309
310    /**
311     * 規格の組み合わせ一覧を表示する.
312     *
313     * 1. 規格1, 規格2を組み合わせた場合の妥当性を検証する.
314     * 2. 規格1, 規格2における規格分類のすべての組み合わせを取得し,
315     *    該当商品の商品規格の内容を取得し, フォームに設定する.
316     */
317    function doDisp() {
318        $this->arrForm['select_class_id1'] = $_POST['select_class_id1'];
319        $this->arrForm['select_class_id2'] = $_POST['select_class_id2'];
320
321        $this->arrErr = $this->lfClassError();
322        if (SC_Utils_Ex::isBlank($this->arrErr)) {
323            $this->arrClassCat = $this->getAllClassCategory($_POST['select_class_id1'], $_POST['select_class_id2']);
324
325            $productsClass = $this->getProductsClass($_POST['product_id']);
326
327            $total = count($this->arrClassCat);
328            for ($i = 1; $i <= $total; $i++) {
329                foreach ($productsClass as $key => $val) {
330                    $this->arrForm[$key . ":" . $i] = $val;
331                }
332            }
333        }
334        $this->tpl_onload.= "fnCheckAllStockLimit('$total', '" . DISABLED_RGB . "');";
335    }
336
337    /**
338     * 規格編集画面を表示する.
339     */
340    function doPreEdit($existsValue = true) {
341        $existsProductsClass = $this->getProductsClassAndClasscategory($_POST['product_id']);
342        $productsClass = $this->getProductsClass($_POST['product_id']);
343        $this->arrForm["class_id1"] = $existsProductsClass[0]['class_id1'];
344        $this->arrForm["class_id2"] = $existsProductsClass[0]['class_id2'];
345        $this->arrForm['select_class_id1'] = $this->arrForm["class_id1"];
346        $this->arrForm['select_class_id2'] = $this->arrForm["class_id2"];
347
348        $this->arrClassCat = $this->getAllClassCategory($this->arrForm["class_id1"], $this->arrForm["class_id2"]);
349        $total = count($this->arrClassCat);
350        for ($i = 1; $i <= $total; $i++) {
351            if ($existsValue) {
352                foreach ($productsClass as $key => $val) {
353                    $this->arrForm[$key . ":" . $i] = $val;
354                }
355            }
356            foreach ($existsProductsClass[$i] as $key => $val) {
357                $this->arrForm[$key . ":" . $i] = $val;
358            }
359            if (!SC_Utils_Ex::isBlank($this->arrForm['product_id:' . $i])
360                && $this->arrForm["del_flg:" . $i] == 0) {
361                $line .= "'check:" . $i . "',";
362            }
363        }
364
365        $line = preg_replace("/,$/", "", $line);
366        $this->tpl_javascript = "list = new Array($line);";
367        $color = DISABLED_RGB;
368        $this->tpl_onload.= "fnListCheck(list); fnCheckAllStockLimit('$total', '$color');";
369    }
370
371    function doDelete() {
372        $objQuery =& SC_Query::getSingletonInstance();
373
374        $objQuery->begin();
375        $val['del_flg'] = 0;
376        $objQuery->update("dtb_products_class", $val, "product_id = ? AND class_combination_id IS NULL", array($_POST['product_id']));
377
378        $val['del_flg'] = 1;
379        $objQuery->update("dtb_products_class", $val, "product_id = ? AND class_combination_id IS NOT NULL", array($_POST['product_id']));
380
381        $objQuery->commit();
382
383        // 在庫無し商品の非表示対応
384        if (NOSTOCK_HIDDEN === true) {
385            // 件数カウントバッチ実行
386            //$objDb->sfCategory_Count($objQuery);
387        }
388    }
389
390    /**
391     * 規格ID1, 規格ID2の規格分類すべてを取得する.
392     *
393     * @param integer $class_id1 規格ID1
394     * @param integer $class_id2 規格ID2
395     * @return array 規格と規格分類の配列
396     */
397    function getAllClassCategory($class_id1, $class_id2 = null) {
398        $objQuery =& SC_Query::getSingletonInstance();
399
400        $col = "T1.class_id AS class_id1, "
401            . " T1.classcategory_id AS classcategory_id1, "
402            . " T1.name AS name1, "
403            . " T1.rank AS rank1 ";
404
405        if(SC_Utils_Ex::isBlank($class_id2)) {
406            $table = "dtb_classcategory T1 ";
407            $objQuery->setWhere("T1.class_id = ?")
408                     ->setOrder("T1.rank DESC");
409            $val = array($class_id1);
410        } else {
411            $col .= ","
412                . "T2.class_id AS class_id2,"
413                . "T2.classcategory_id AS classcategory_id2,"
414                . "T2.name AS name2,"
415                . "T2.rank AS rank2";
416            $table = "dtb_classcategory AS T1, dtb_classcategory AS T2";
417            $objQuery->setWhere("T1.class_id = ? AND T2.class_id = ?")
418                     ->setOrder("T1.rank DESC, T2.rank DESC");
419            $val = array($class_id1, $class_id2);
420        }
421        return $objQuery->select($col, $table, "", $val);
422    }
423
424    /**
425     * 商品名を取得する.
426     *
427     * @access private
428     * @param integer $product_id 商品ID
429     * @return string 商品名の文字列
430     */
431    function getProductName($product_id) {
432        $objQuery =& SC_Query::getSingletonInstance();
433        return $objQuery->getOne("SELECT name FROM dtb_products WHERE product_id = ?", array($product_id));
434    }
435
436    /**
437     * 検索パラメータを生成する.
438     *
439     * "search_" で始まるパラメータのみを生成して返す.
440     *
441     * TODO パラメータの妥当性検証
442     *
443     * @access private
444     * @param array $params 生成元の POST パラメータ
445     * @return array View にアサインするパラメータの配列
446     */
447    function createSearchParams($params) {
448        $results = array();
449        foreach ($params as $key => $val) {
450            if (substr($key, 0, 7) == "search_") {
451                $results[$key] = $val;
452            }
453        }
454        return $results;
455    }
456
457    /**
458     * 規格分類の登録された, すべての規格を取得する.
459     *
460     * @access private
461     * @return array 規格分類の登録された, すべての規格
462     */
463    function getAllClass() {
464        $objDb = new SC_Helper_DB_Ex();
465        $arrClass = $objDb->sfGetIDValueList("dtb_class", 'class_id', 'name');
466
467        // 規格分類が登録されていない規格は表示しないようにする。
468        $arrClassCatCount = SC_Utils_Ex::sfGetClassCatCount();
469
470        $results = array();
471        if (!SC_Utils_Ex::isBlank($arrClass)) {
472            foreach($arrClass as $key => $val) {
473                if($arrClassCatCount[$key] > 0) {
474                    $results[$key] = $arrClass[$key];
475                }
476            }
477        }
478        return $results;
479    }
480
481    /**
482     * 商品IDをキーにして, 商品規格を取得する.
483     *
484     * @param integer $product_id 商品ID
485     * @return array 商品規格の配列
486     */
487    function getProductsClass($product_id) {
488        $objQuery =& SC_Query::getSingletonInstance();
489        return $objQuery->getRow("dtb_products_class", "*", "product_id = ?", array($product_id));
490    }
491
492    /**
493     * 登録済みの商品規格, 規格, 規格分類を取得する.
494     *
495     * @param integer $product_id 商品ID
496     * @return array 商品規格, 規格, 規格分類の配列
497     */
498    function getProductsClassAndClasscategory($productId) {
499        $objProduct = new SC_Product();
500        return $objProduct->getProductsClassFullByProductId($productId);
501    }
502
503    /**
504     * @access private
505     */
506    function authorization() {
507        SC_Utils_Ex::sfIsSuccess(new SC_Session());
508    }
509
510    /**
511     * @access private
512     */
513    function assignView() {
514        $objView = new SC_AdminView();
515        $objView->assignobj($this);
516        $objView->display(MAIN_FRAME);
517    }
518}
519?>
Note: See TracBrowser for help on using the repository browser.