source: branches/version-2_5-dev/data/class/SC_CartSession.php @ 19928

Revision 19928, 21.2 KB checked in by nanasess, 13 years ago (diff)

#843(複数配送先の指定)

  • 送料計算を修正
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • 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/* カートセッション管理クラス */
25class SC_CartSession {
26    /** ユニークIDを指定する. */
27    var $key_tmp;
28
29    /** カートのセッション変数. */
30    var $cartSession;
31
32    /* コンストラクタ */
33    function SC_CartSession($cartKey = "cart") {
34        $this->cartSession =& $_SESSION[$cartKey];
35    }
36
37    // 商品購入処理中のロック
38    function saveCurrentCart($key_tmp, $productTypeId) {
39        $this->key_tmp = "savecart_" . $key_tmp;
40        // すでに情報がなければ現状のカート情報を記録しておく
41        if(count($_SESSION[$this->key_tmp]) == 0) {
42            $_SESSION[$this->key_tmp] = $this->cartSession[$productTypeId];
43        }
44        // 1世代古いコピー情報は、削除しておく
45        foreach($_SESSION as $k => $val) {
46            if($k != $this->key_tmp && preg_match("/^savecart_/", $k)) {
47                unset($this->cartSession[$productTypeId][$k]);
48            }
49        }
50        $this->registerKey($productTypeId);
51    }
52
53    // 商品購入中の変更があったかをチェックする。
54    function getCancelPurchase($productTypeId) {
55        $ret = isset($this->cartSession[$productTypeId]['cancel_purchase'])
56            ? $this->cartSession[$productTypeId]['cancel_purchase'] : "";
57        $this->cartSession[$productTypeId]['cancel_purchase'] = false;
58        return $ret;
59    }
60
61    // 購入処理中に商品に変更がなかったかを判定
62    function checkChangeCart($productTypeId) {
63        $change = false;
64        $max = $this->getMax($productTypeId);
65        for($i = 1; $i <= $max; $i++) {
66            if ($this->cartSession[$productTypeId][$i]['quantity']
67                != $_SESSION[$this->key_tmp][$i]['quantity']) {
68
69                $change = true;
70                break;
71            }
72            if ($this->cartSession[$productTypeId][$i]['id']
73                != $_SESSION[$this->key_tmp][$i]['id']) {
74
75                $change = true;
76                break;
77            }
78        }
79        if ($change) {
80            // 一時カートのクリア
81            unset($_SESSION[$this->key_tmp]);
82            $this->cartSession[$productTypeId][$key]['cancel_purchase'] = true;
83        } else {
84            $this->cartSession[$productTypeId]['cancel_purchase'] = false;
85        }
86        return $this->cartSession[$productTypeId]['cancel_purchase'];
87    }
88
89    // 次に割り当てるカートのIDを取得する
90    function getNextCartID($productTypeId) {
91        foreach($this->cartSession[$productTypeId] as $key => $val){
92            $arrRet[] = $this->cartSession[$productTypeId][$key]['cart_no'];
93        }
94        return (max($arrRet) + 1);
95    }
96
97    /**
98     * 商品ごとの合計価格
99     * XXX 実際には、「商品」ではなく、「カートの明細行(≒商品規格)」のような気がします。
100     *
101     * @param integer $id
102     * @return string 商品ごとの合計価格(税込み)
103     * @deprecated SC_CartSession::getCartList() を使用してください
104     */
105    function getProductTotal($id, $productTypeId) {
106        $max = $this->getMax($productTypeId);
107        for($i = 0; $i <= $max; $i++) {
108            if(isset($this->cartSession[$productTypeId][$i]['id'])
109               && $this->cartSession[$productTypeId][$i]['id'] == $id) {
110
111                // 税込み合計
112                $price = $this->cartSession[$productTypeId][$i]['price'];
113                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
114                $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
115                $total = $incTax * $quantity;
116                return $total;
117            }
118        }
119        return 0;
120    }
121
122    // 値のセット
123    function setProductValue($id, $key, $val, $productTypeId) {
124        $max = $this->getMax($productTypeId);
125        for($i = 0; $i <= $max; $i++) {
126            if(isset($this->cartSession[$productTypeId][$i]['id'])
127               && $this->cartSession[$productTypeId][$i]['id'] == $id) {
128                $this->cartSession[$productTypeId][$i][$key] = $val;
129            }
130        }
131    }
132
133    // カート内商品の最大要素番号を取得する。
134    function getMax($productTypeId) {
135        $max = 0;
136        if (count($this->cartSession[$productTypeId]) > 0){
137            foreach($this->cartSession[$productTypeId] as $key => $val) {
138                if (is_numeric($key)) {
139                    if($max < $key) {
140                        $max = $key;
141                    }
142                }
143            }
144        }
145        return ($max);
146    }
147
148    // カート内商品数の合計
149    function getTotalQuantity($productTypeId) {
150        $total = 0;
151        $max = $this->getMax($productTypeId);
152        for($i = 0; $i <= $max; $i++) {
153            $total+= $this->cartSession[$productTypeId][$i]['quantity'];
154        }
155        return $total;
156    }
157
158
159    // 全商品の合計価格
160    function getAllProductsTotal($productTypeId) {
161        // 税込み合計
162        $total = 0;
163        $max = $this->getMax($productTypeId);
164        for($i = 0; $i <= $max; $i++) {
165
166            if (!isset($this->cartSession[$productTypeId][$i]['price'])) {
167                $this->cartSession[$productTypeId][$i]['price'] = "";
168            }
169
170            $price = $this->cartSession[$productTypeId][$i]['price'];
171
172            if (!isset($this->cartSession[$productTypeId][$i]['quantity'])) {
173                $this->cartSession[$productTypeId][$i]['quantity'] = "";
174            }
175            $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
176
177            $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
178            $total+= ($incTax * $quantity);
179        }
180        return $total;
181    }
182
183    // 全商品の合計税金
184    function getAllProductsTax($productTypeId) {
185        // 税合計
186        $total = 0;
187        $max = $this->getMax($productTypeId);
188        for($i = 0; $i <= $max; $i++) {
189            $price = $this->cartSession[$productTypeId][$i]['price'];
190            $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
191            $tax = SC_Helper_DB_Ex::sfTax($price);
192            $total+= ($tax * $quantity);
193        }
194        return $total;
195    }
196
197    // 全商品の合計ポイント
198    function getAllProductsPoint($productTypeId) {
199        // ポイント合計
200        $total = 0;
201        if (USE_POINT !== false) {
202            $max = $this->getMax($productTypeId);
203            for($i = 0; $i <= $max; $i++) {
204                $price = $this->cartSession[$productTypeId][$i]['price'];
205                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
206
207                if (!isset($this->cartSession[$productTypeId][$i]['point_rate'])) {
208                    $this->cartSession[$productTypeId][$i]['point_rate'] = "";
209                }
210                $point_rate = $this->cartSession[$productTypeId][$i]['point_rate'];
211
212                if (!isset($this->cartSession[$productTypeId][$i]['id'][0])) {
213                    $this->cartSession[$productTypeId][$i]['id'][0] = "";
214                }
215                $id = $this->cartSession[$productTypeId][$i]['id'][0];
216                $point = SC_Utils_Ex::sfPrePoint($price, $point_rate, POINT_RULE, $id);
217                $total+= ($point * $quantity);
218            }
219        }
220        return $total;
221    }
222
223    // カートへの商品追加
224    function addProduct($id, $quantity, $productTypeId) {
225        $find = false;
226        $max = $this->getMax($productTypeId);
227        for($i = 0; $i <= $max; $i++) {
228
229            if($this->cartSession[$productTypeId][$i]['id'] == $id) {
230                $val = $this->cartSession[$productTypeId][$i]['quantity'] + $quantity;
231                if(strlen($val) <= INT_LEN) {
232                    $this->cartSession[$productTypeId][$i]['quantity'] += $quantity;
233                }
234                $find = true;
235            }
236        }
237        if(!$find) {
238            $this->cartSession[$productTypeId][$max+1]['id'] = $id;
239            $this->cartSession[$productTypeId][$max+1]['quantity'] = $quantity;
240            $this->cartSession[$productTypeId][$max+1]['cart_no'] = $this->getNextCartID($productTypeId);
241        }
242    }
243
244    // 前頁のURLを記録しておく
245    function setPrevURL($url) {
246        // 前頁として記録しないページを指定する。
247        $arrExclude = array(
248            "/shopping/"
249        );
250        $exclude = false;
251        // ページチェックを行う。
252        foreach($arrExclude as $val) {
253            if(preg_match("/" . preg_quote($val) . "/", $url)) {
254                $exclude = true;
255                break;
256            }
257        }
258        // 除外ページでない場合は、前頁として記録する。
259        if(!$exclude) {
260            $_SESSION['prev_url'] = $url;
261        }
262    }
263
264    // 前頁のURLを取得する
265    function getPrevURL() {
266        return isset($_SESSION['prev_url']) ? $_SESSION['prev_url'] : "";
267    }
268
269    // キーが一致した商品の削除
270    function delProductKey($keyname, $val, $productTypeId) {
271        $max = count($this->cartSession[$productTypeId]);
272        for($i = 0; $i < $max; $i++) {
273            if($this->cartSession[$productTypeId][$i][$keyname] == $val) {
274                unset($this->cartSession[$productTypeId][$i]);
275            }
276        }
277    }
278
279    function setValue($key, $val, $productTypeId) {
280        $this->cartSession[$productTypeId][$key] = $val;
281    }
282
283    function getValue($key, $productTypeId) {
284        return $this->cartSession[$productTypeId][$key];
285    }
286
287    function getCartList($productTypeId) {
288        $objProduct = new SC_Product();
289        $max = $this->getMax($productTypeId);
290        $arrRet = array();
291        for($i = 0; $i <= $max; $i++) {
292            if(isset($this->cartSession[$productTypeId][$i]['cart_no'])
293               && $this->cartSession[$productTypeId][$i]['cart_no'] != "") {
294
295                if (SC_Utils_Ex::isBlank($this->cartSession[$productTypeId][$i]['productsClass'])) {
296                    $this->cartSession[$productTypeId][$i]['productsClass'] =&
297                            $objProduct->getDetailAndProductsClass(
298                                    $this->cartSession[$productTypeId][$i]['id']);
299                }
300
301                $price = $this->cartSession[$productTypeId][$i]['productsClass']['price02'];
302                $this->cartSession[$productTypeId][$i]['price'] = $price;
303
304                $this->cartSession[$productTypeId][$i]['point_rate'] =
305                        $this->cartSession[$productTypeId][$i]['productsClass']['point_rate'];
306
307
308                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
309                $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
310                $total = $incTax * $quantity;
311
312                $this->cartSession[$productTypeId][$i]['total_inctax'] = $total;
313
314                $arrRet[] =& $this->cartSession[$productTypeId][$i];
315            }
316        }
317        return $arrRet;
318    }
319
320    /**
321     * すべてのカートの内容を取得する.
322     *
323     * @return array すべてのカートの内容
324     */
325    function getAllCartList() {
326        $results = array();
327        $cartKeys = $this->getKeys();
328        $i = 0;
329        foreach ($cartKeys as $key) {
330            $cartItems = $this->getCartList($key);
331            foreach (array_keys($cartItems) as $itemKey) {
332                $cartItem =& $cartItems[$itemKey];
333                $results[$key][$i] =& $cartItem;
334                $i++;
335            }
336        }
337        return $results;
338    }
339
340    // カート内にある商品IDを全て取得する
341    function getAllProductID($productTypeId) {
342        $max = $this->getMax($productTypeId);
343        for($i = 0; $i <= $max; $i++) {
344            if($this->cartSession[$productTypeId][$i]['cart_no'] != "") {
345                $arrRet[] = $this->cartSession[$productTypeId][$i]['id'][0];
346            }
347        }
348        return $arrRet;
349    }
350
351    /**
352     * カート内にある商品規格IDを全て取得する.
353     *
354     * @param integer $productTypeId 商品種別ID
355     * @return array 商品規格ID の配列
356     */
357    function getAllProductClassID($productTypeId) {
358        $max = $this->getMax($productTypeId);
359        for($i = 0; $i <= $max; $i++) {
360            if($this->cartSession[$productTypeId][$i]['cart_no'] != "") {
361                $arrRet[] = $this->cartSession[$productTypeId][$i]['id'];
362            }
363        }
364        return $arrRet;
365    }
366
367    function delAllProducts($productTypeId) {
368        $max = $this->getMax($productTypeId);
369        for($i = 0; $i <= $max; $i++) {
370            unset($this->cartSession[$productTypeId][$i]);
371        }
372    }
373
374    // 商品の削除
375    function delProduct($cart_no, $productTypeId) {
376        $max = $this->getMax($productTypeId);
377        for($i = 0; $i <= $max; $i++) {
378            if($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
379                unset($this->cartSession[$productTypeId][$i]);
380            }
381        }
382    }
383
384    // 数量の増加
385    function upQuantity($cart_no, $productTypeId) {
386        $quantity = $this->getQuantity($cart_no, $productTypeId);
387        if (strlen($quantity + 1) <= INT_LEN) {
388            $this->setQuantity($quantity + 1, $cart_no, $productTypeId);
389        }
390    }
391
392    // 数量の減少
393    function downQuantity($cart_no, $productTypeId) {
394        $quantity = $this->getQuantity($cart_no, $productTypeId);
395        if ($quantity > 1) {
396            $this->setQuantity($quantity - 1, $cart_no, $productTypeId);
397        }
398    }
399
400    function getQuantity($cart_no, $productTypeId) {
401        $max = $this->getMax($productTypeId);
402        for ($i = 0; $i <= $max; $i++) {
403            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
404                return $this->cartSession[$productTypeId][$i]['quantity'];
405            }
406        }
407    }
408
409    function setQuantity($quantity, $cart_no, $productTypeId) {
410        $max = $this->getMax($productTypeId);
411        for ($i = 0; $i <= $max; $i++) {
412            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
413                $this->cartSession[$productTypeId][$i]['quantity'] = $quantity;
414            }
415        }
416    }
417
418    function getProductClassId($cart_no, $productTypeId) {
419        for ($i = 0; $i <= $max; $i++) {
420            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
421                return $this->cartSession[$productTypeId][$i]['id'];
422            }
423        }
424    }
425
426    /**
427     * カート内の商品の妥当性をチェックする.
428     *
429     * エラーが発生した場合は, 商品をカート内から削除又は数量を調整し,
430     * エラーメッセージを返す.
431     *
432     * 1. 削除/非表示商品のチェック
433     * 2. 商品購入制限数のチェック
434     * 3. 在庫数チェック
435     *
436     * @param string $key 商品種別ID
437     * @return string エラーが発生した場合はエラーメッセージ
438     */
439    function checkProducts($productTypeId) {
440        $objProduct = new SC_Product();
441        $tpl_message = "";
442
443        // カート内の情報を取得
444        $items = $this->getCartList($productTypeId);
445        foreach (array_keys($items) as $key) {
446            $item =& $items[$key];
447            $product =& $item['productsClass'];
448            /*
449             * 表示/非表示商品のチェック
450             */
451            if (SC_Utils_Ex::isBlank($product)) {
452                $this->delProduct($item['cart_no'], $productTypeId);
453                $tpl_message .= "※ 現時点で販売していない商品が含まれておりました。該当商品をカートから削除しました。\n";
454            }
455
456            /*
457             * 商品購入制限数, 在庫数のチェック
458             */
459            $limit = $objProduct->getBuyLimit($product);
460            if (!is_null($limit) && $item['quantity'] > $limit) {
461                if ($limit > 0) {
462                    $this->setProductValue($item['id'], 'quantity', $limit, $productTypeId);
463                    $tpl_message .= "※「" . $product['name'] . "」は販売制限(または在庫が不足)しております。一度に数量{$limit}以上の購入はできません。\n";
464                } else {
465                    $this->delProduct($item['cart_no'], $productTypeId);
466                    $tpl_message .= "※「" . $product['name'] . "」は売り切れました。\n";
467                    continue;
468                }
469            }
470        }
471        return $tpl_message;
472    }
473
474    /**
475     * カートの内容を計算する.
476     *
477     * カートの内容を計算し, 下記のキーを保持する連想配列を返す.
478     *
479     * - tax: 税額
480     * - subtotal: カート内商品の小計
481     * - deliv_fee: カート内商品の合計送料 FIXME
482     * - total: 合計金額
483     * - payment_total: お支払い合計
484     * - add_point: 加算ポイント
485     *
486     *  TODO ダウンロード商品のみの場合の送料を検討する
487     *  TODO 使用ポイント, 配送都道府県, 支払い方法, 手数料の扱いを検討
488     *
489     * @param integer $productTypeId 商品種別ID
490     * @param SC_Customer $objCustomer ログイン中の SC_Customer インスタンス
491     * @param integer $use_point 今回使用ポイント
492     * @param integer|array $deliv_pref 配送先都道府県ID.
493                                        複数に配送する場合は都道府県IDの配列
494     * @param integer $charge 手数料
495     * @param integer $discount 値引
496     * @return array カートの計算結果の配列
497     */
498    function calculate($productTypeId, &$objCustomer, $use_point = 0,
499                       $deliv_pref = "", $charge = 0, $discount = 0) {
500        $objDb = new SC_Helper_DB_Ex();
501
502        $total_point = $this->getAllProductsPoint($productTypeId);
503        $results['tax'] = $this->getAllProductsTax($productTypeId);
504        $results['subtotal'] = $this->getAllProductsTotal($productTypeId);
505        $results['deliv_fee'] = 0;
506
507        // 商品ごとの送料を加算
508        if (OPTION_PRODUCT_DELIV_FEE == 1) {
509            $cartItems = $this->getCartList($productTypeId);
510            foreach ($cartItems as $item) {
511                $results['deliv_fee'] += $item['deliv_fee'] * $item['quantity'];
512            }
513        }
514
515        // 配送業者の送料を加算
516        if (OPTION_DELIV_FEE == 1) {
517            $results['deliv_fee'] += $objDb->sfGetDelivFee($deliv_pref, $productTypeId);
518        }
519
520        // 送料無料の購入数が設定されている場合
521        if (DELIV_FREE_AMOUNT > 0) {
522            // 商品の合計数量
523            $total_quantity = $this->getTotalQuantity($productTypeId);
524
525            if($total_quantity >= DELIV_FREE_AMOUNT) {
526                $results['deliv_fee'] = 0;
527            }
528        }
529
530        // 送料無料条件が設定されている場合
531        $arrInfo = $objDb->sfGetBasisData();
532        if($arrInfo['free_rule'] > 0) {
533            // 小計が無料条件を超えている場合
534            if($results['subtotal'] >= $arrInfo['free_rule']) {
535                $results['deliv_fee'] = 0;
536            }
537        }
538
539        // 合計を計算
540        $results['total'] = $results['subtotal'];
541        $results['total'] += $results['deliv_fee'];
542        $results['total'] += $charge;
543        $results['total'] -= $discount;
544
545        // お支払い合計
546        $results['payment_total'] = $results['total'] - $use_point * POINT_VALUE;
547
548        // 加算ポイントの計算
549        if (USE_POINT !== false) {
550            $results['add_point'] = SC_Helper_DB_Ex::sfGetAddPoint($total_point,
551                                                                   $use_point);
552            if($objCustomer != "") {
553                // 誕生日月であった場合
554                if($objCustomer->isBirthMonth()) {
555                    $results['birth_point'] = BIRTH_MONTH_POINT;
556                    $results['add_point'] += $results['birth_point'];
557                }
558            }
559            if($results['add_point'] < 0) {
560                $results['add_point'] = 0;
561            }
562        }
563        return $results;
564    }
565
566    function getKeys() {
567        $keys = array_keys($this->cartSession);
568        // 数量が 0 の商品種別は削除する
569        foreach ($keys as $key) {
570            $quantity = $this->getTotalQuantity($key);
571            if ($quantity < 1) {
572                unset($this->cartSession[$key]);
573            }
574        }
575        return array_keys($this->cartSession);
576    }
577
578    function registerKey($key) {
579        $_SESSION['cartKey'] = $key;
580    }
581
582    function unsetKey() {
583        unset($_SESSION['cartKey']);
584    }
585
586    function getKey() {
587        return $_SESSION['cartKey'];
588    }
589}
590?>
Note: See TracBrowser for help on using the repository browser.