在ecshop源码折扣计算中的代码在lib_main.php

的update_user_info()函数中


$sql = 'SELECT u.user_money,u.email, u.pay_points, u.user_rank, u.rank_points, '.
             ' IFNULL(b.type_money, 0) AS user_bonus, u.last_login, u.last_ip'.
             ' FROM ' .$GLOBALS['ecs']->table('users'). ' AS u ' .
             ' LEFT JOIN ' .$GLOBALS['ecs']->table('user_bonus'). ' AS ub'.
             ' ON ub.user_id = u.user_id AND ub.used_time = 0 ' .
             ' LEFT JOIN ' .$GLOBALS['ecs']->table('bonus_type'). ' AS b'.
             " ON b.type_id = ub.bonus_type_id AND b.use_start_date <= '$time' AND b.use_end_date >= '$time' ".
             " WHERE u.user_id = '$_SESSION[user_id]'";
     if ($row = $GLOBALS['db']->getRow($sql))
     {
         /* 更新SESSION */
         $_SESSION['last_time']   = $row['last_login'];
         $_SESSION['last_ip']     = $row['last_ip'];
         $_SESSION['login_fail']  = 0;
         $_SESSION['email']       = $row['email'];

         /*判断是否是特殊等级,可能后台把特殊会员组更改普通会员组*/
         if($row['user_rank'] >0)
         {
             $sql="SELECT special_rank from ".$GLOBALS['ecs']->table('user_rank')."where rank_id='$row[user_rank]'";
             if($GLOBALS['db']->getOne($sql)==='0' || $GLOBALS['db']->getOne($sql)===null)
             {   
                 $sql="update ".$GLOBALS['ecs']->table('users')."set user_rank='0' where user_id='$_SESSION[user_id]'";
                 $GLOBALS['db']->query($sql);
                 $row['user_rank']=0;
             }
         }

         /* 取得用户等级和折扣 */
         if ($row['user_rank'] == 0)
         {
             // 非特殊等级,根据等级积分计算用户等级(注意:不包括特殊等级)
             $sql = 'SELECT rank_id, discount FROM ' . $GLOBALS['ecs']->table('user_rank') . " WHERE special_rank = '0' AND min_points <= " . intval($row['rank_points']) . ' AND max_points > ' . intval($row['rank_points']);
             if ($row = $GLOBALS['db']->getRow($sql))
             {
                 $_SESSION['user_rank'] = $row['rank_id'];
                 $_SESSION['discount']  = $row['discount'] / 100.00;
             }
             else
             {
                 $_SESSION['user_rank'] = 0;
                 $_SESSION['discount']  = 1;
             }
         }
         else
         {
             // 特殊等级
             $sql = 'SELECT rank_id, discount FROM ' . $GLOBALS['ecs']->table('user_rank') . " WHERE rank_id = '$row[user_rank]'";
             if ($row = $GLOBALS['db']->getRow($sql))
             {
                 $_SESSION['user_rank'] = $row['rank_id'];
                 $_SESSION['discount']  = $row['discount'] / 100.00;
             }
             else
             {
                 $_SESSION['user_rank'] = 0;
                 $_SESSION['discount']  = 1;
             }
         }
     }

在看分析前必须理解三个概念,

user_rank不一定是最终计算折扣的等级

user_rank>0时,系统就认为该会员属于特殊会员组

special_rank=0时,系统就认为该等级属于特殊会员组

根据这段代码分析,

一、ecshop 先按照user_id取出数据,根据用户数据的user_rank是否>0来判断该用户以前是否是特殊会员组。

但是又有2种情况发生,

1,当后台把user_rank所在的等级由原来的特殊会员组改为非特殊会员组时

2,管理员把user_rank所在的等级删除了

所以在代码中针对这两种情况代码执行

$sql="update ".$GLOBALS['ecs']->table('users')."set user_rank='0' where user_id='$_SESSION[user_id]'";
  $GLOBALS['db']->query($sql);
 $row['user_rank']=0;

也就是把user_rank重置为0,也就是当前用户已经还原成为了非特殊会员组

二、用户在此根据user_rank==0来判断该会员现在是否属于特殊会员组  =0则属于非特殊会员组

当user_rank==0 时 根据 rank_points来进行计算,,最终得到折扣。但是sql中添加了special_rank = '0'的条件,

根据这个分析,ecshop 的等级积分可能会存在重叠的情况,但是推荐会员等级列表中非特殊会员组最好永远只有1组而且积分连续而且不重叠

这样才会每次按积分查询时都会满足唯一一个非特殊等级组,才符合实际情况。

user_rank>0时根据user_rank 来进行计算,最终得到折扣。此时此等级的积分基本无效,所以建议把积分上下限都设为很大很大如(100000000)

这样当错误的操作或无意中取消为非会员组时,才不会影响到程序


针对如果积分范围不属于某个非特殊会员组,和特殊会员组不存在的2种情况,ecshop也进行了

$_SESSION['user_rank'] = 0;
  $_SESSION['discount']  = 1;

的操作