<?php
/**
 * DouPHP
 * --------------------------------------------------------------------------------------------------
 * 版权所有 2013-2024 漳州豆壳网络科技有限公司，并保留所有权利。
 * 网站地址: http://www.douphp.com
 * --------------------------------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在遵守授权协议前提下对程序代码进行修改和使用；不允许对程序代码以任何形式任何目的的再发布。
 * 授权协议: http://www.douphp.com/license.html
 * --------------------------------------------------------------------------------------------------
 * Author: DouCo Co.,Ltd.
 * Release Date: 2024-09-30
 */
if (!defined('IN_DOUCO')) {
    die('Hacking attempt');
}
class Order {
    /**
     * +----------------------------------------------------------
     * 用户权限判断
     * +----------------------------------------------------------
     * $session_cart session储存的商品信息
     * +----------------------------------------------------------
     */
    function get_cart($user_id = '') {
        $user_id = $user_id ? $user_id : $GLOBALS['_GLOBAL_USER']['user_id'];
        
        /* 获取产品列表 */
        $query = $GLOBALS['dou']->query("SELECT * FROM " . $GLOBALS['dou']->table('order_cart') . " WHERE user_id = '$user_id' ORDER BY id DESC");
        while ($row = $GLOBALS['dou']->fetch_array($query)) {
            $item = $GLOBALS['dou']->get_row($row['module'], '*', "id = '$row[item_id]'");
         
            // 格式化
            $level_price = $GLOBALS['dou']->level_price($item['level_price'], $user_id); // 会员等级价格
            $price = $level_price ? $level_price : $item['price']; // 交易价格
            $name = $item['name'] ? $item['name'] : $item['title'];
         
            // 款式属性
            if ($GLOBALS['_OPEN']['attribute']) {
                $attribute_list = explode('_', $row['attribute']);
                foreach ($attribute_list as $value_id) {
                    $value = $GLOBALS['dou']->get_row('attribute_value', '*', "id = '$value_id'");
                    $name = $name . ' ' . $value['value'];
                    $price = $price + $value['price_change'];
                }
            }
             
            $url = $GLOBALS['dou']->rewrite_url($row['module'], $item['id']);
            $subtotal = $price > 0 ? $GLOBALS['dou']->price_format($price * $row['item_number']) : $GLOBALS['_LANG']['price_discuss'];
            
            $cart['list'][] = array (
                    "id" => $row['id'],
                    "name" => $name,
                    "item_id" => $row['item_id'],
                    "price_normal" => $price,
                    "price" => $price > 0 ? $GLOBALS['dou']->price_format($price) : $GLOBALS['_LANG']['price_discuss'],
                    "point" => $item['point'],
                    "point_format" => $item['point'] . $GLOBALS['_LANG']['point_point'],
                    "url" => $url,
                    "thumb" => $item['module'] == 'product' ? $GLOBALS['dou']->dou_file($item['image'], true) : $GLOBALS['dou']->dou_file($item['image']),
                    "defined" => $item['defined'],
                    "subtotal" => $subtotal,
                    "number" => $row['item_number'],
                    "attribute" => $row['attribute']
            );
            
            // 所属模块
            $cart['module'] = $row['module'];
         
            // 商品总数量
            $cart['total'] += $row['item_number'];
            
            // 商品总金额
            $cart['item_amount'] += ($price * $row['item_number']);
            $cart['item_amount_format'] = $GLOBALS['dou']->price_format($cart['item_amount']);
            $cart['order_point'] += ($item['point'] * $row['item_number']);
        }
            
        return $cart;
    }
    
    /**
     * +----------------------------------------------------------
     * 清空会员购物车
     * +----------------------------------------------------------
     */
    function clear_cart($user_id = '') {
        if ($user_id = ($user_id ? $user_id : $GLOBALS['_GLOBAL_USER']['user_id']))
            $GLOBALS['dou']->query("DELETE FROM " . $GLOBALS['dou']->table('order_cart') . " WHERE user_id = '$user_id'");
    }
    
    /**
     * +----------------------------------------------------------
     * 生成唯一的订单编号
     * +----------------------------------------------------------
     */
    function create_order_sn() {
        $user_sn = $GLOBALS['_GLOBAL_USER']['user_sn'];
        
        // 随机生成订单号
        $order_sn = date('ymdHis') . str_pad(mt_rand(1, 99), 2, '0', STR_PAD_LEFT) . $user_sn;
     
        return $order_sn;
    }

    /**
     * +----------------------------------------------------------
     * 格式化支付和配送方式
     * +----------------------------------------------------------
     */
    function payship_format($data) {
        if ($data) {
            foreach (explode("\r\n", $data) as $value) {
                $arr = explode('/', $value);
                $item['name'] = $arr['0'];
                $item['id'] = $arr['1'];
                $array[] = $item;
            }
        }
        
        return $array;
    }

    /**
     * +----------------------------------------------------------
     * 获取订单商品
     * +----------------------------------------------------------
     * $order_id 订单编号
     * +----------------------------------------------------------
     */
    function get_order_item($order_id, $user_id = '') {
        /* 获取产品列表 */
        $query = $GLOBALS['dou']->query("SELECT * FROM " . $GLOBALS['dou']->table('order_item') . " WHERE order_id = '$order_id' ORDER BY id DESC");
    
        while ($row = $GLOBALS['dou']->fetch_array($query)) {
            // 格式化价格
            $price = $GLOBALS['dou']->price_format($row['price']);
            $image = $GLOBALS['dou']->get_one("SELECT image FROM " . $GLOBALS['dou']->table($row['module']) . " WHERE id = '$row[item_id]'");
            $url = $GLOBALS['dou']->rewrite_url($row['module'], $row['item_id']);
            
            $item_list[] = array (
                    "id" => $row['id'],
                    "item_id" => $row['item_id'],
                    "name" => $row['name'],
                    "image" => $row['module'] == 'product' ? $GLOBALS['dou']->dou_file($image, true) : $GLOBALS['dou']->dou_file($image),
                    "url" => $url,
                    "item_number" => $row['item_number'],
                    "price" => $price,
                    "point" => $row['point'],
                    "point_format" => $row['point'] . $GLOBALS['_LANG']['point_point'],
                    "comment_url" => $this->if_can_comment($order_id, $row['id'], $user_id) ? $GLOBALS['dou']->param($GLOBALS['dou']->rewrite_url('comment', 'post') . '&order_item_id=' . $row['id']) : '',
                    "defined" => $defined
            );
        }
        
        $order = $GLOBALS['dou']->get_row('order', 'module, item_id, item_name, item_amount', "order_id = '$order_id'");
        if (!$item_list && $order) {
            $item_list[] = array (
                    "item_id" => $order['item_id'],
                    "name" => $order['item_name'],
                    "item_number" => 1,
                    "price" => $GLOBALS['dou']->price_format($order['item_amount']),
                    "point" => $order['point'],
                    "point_format" => $row['point'] . $GLOBALS['_LANG']['point_point'],
            );
        }
        
        return $item_list;
    }
 
    /**
     * +----------------------------------------------------------
     * 验证订单商品是否可评论
     * +----------------------------------------------------------
     */
    function if_can_comment($order_id, $order_item_id, $user_id = '') {
        global $_GLOBAL_USER;
        
        // 如果来自小程序，就需要手动传入user_id
        $user_id = $user_id ? $user_id : $_GLOBAL_USER['user_id'];
        
        // 订单状态
        $allow_comment = $GLOBALS['dou']->get_one("SELECT allow_comment FROM " . $GLOBALS['dou']->table('order') . " WHERE order_id = '$order_id' AND user_id = '$user_id' AND status = '10'");
        
        if ($allow_comment == '1') {
            return $GLOBALS['dou_comment']->check_permission($order_item_id, $user_id);
        } else {
            return false;
        }
    }
    
    /**
     * +----------------------------------------------------------
     * 改变订单状态
     * +----------------------------------------------------------
     * $order_sn 订单编号
     * $status 由数字表示的订单状态
     * +----------------------------------------------------------
     */
    function change_status($order_sn, $new_status) {
        $order = $GLOBALS['dou']->get_row('order', '*', "order_sn = '$order_sn'");
        $status = $new_status;
        
        if ($order['order_id'] && $status) {
            // 如果没有安装物流插件则直接将订单标记为已完成
            if (!$GLOBALS['dou']->value_exist('plugin', 'plugin_group', 'shipping') && $status == 1)
                $status = '10';
            
            // 订单完成操作（记为可申请售后、可评论）
            if ($status == '10') {
                $shipping_time = time();
                $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET shipping_time = '$shipping_time', allow_aftersale = '1', allow_comment = '1' WHERE order_id = '$order[order_id]'");
            }
            
            // 订单付款后操作
            if ($new_status == '1') {
                $pay_time = time();
                $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET pay_time = '$pay_time', status = '$status' WHERE order_id = '$order[order_id]'");
                $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order_item') . " SET order_status = '$status' WHERE order_id = '$order[order_id]'");

                // 开启库存功能情况下，遍历订单商品，减去相应库存
                if ($GLOBALS['_CFG']['stock'] && $order['module'] == 'product') {
                    $query = $GLOBALS['dou']->query("SELECT item_id, item_number FROM " . $GLOBALS['dou']->table('order_item') . " WHERE order_id = '$order[order_id]' ORDER BY id DESC");
                    while ($row = $GLOBALS['dou']->fetch_array($query)) {
                        // 减少库存 并 增加销量
                        $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('product') . " SET stock = stock - " . $row['item_number'] . ", sales = sales + " . $row['item_number'] . " WHERE id = '$row[item_id]'");
                    }

                    // 商品下单后会锁定库存，付款后解锁，这里操作解锁（stock_lock = 0）
                    $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order_item') . " SET stock_lock = '0' WHERE order_id = '$order[order_id]'");
                }

                // 更新模块数据状态
                if ($order['item_link_status']) {
                    $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table($order['module']) . " SET status = '$order[item_link_status]' WHERE order_sn = '$order_sn'");
                }

                // 消费积分（每消费100元）
                if ($_OPEN['point'] && ($status == 1 || $status == 10)) {
                    $point = ($order['order_amount'] / 100) * ($GLOBALS['_PARAM']['point_scale'] ? $GLOBALS['_PARAM']['point_scale'] : 1);
                    $GLOBALS['dou_user']->create_point($order['user_id'], 'shopping', intval($point), $order_sn);
                }
            }
        }
    }
    
    /**
     * +----------------------------------------------------------
     * 支付成功，写入支付信息
     * +----------------------------------------------------------
     * $order_sn 订单编号
     * $pay_id 支付方式别名
     * +----------------------------------------------------------
     */
    function write_pay_id($order_sn, $pay_id) {
        $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET pay_id = '$pay_id' WHERE order_sn = '$order_sn'");
    }

    /**
     * +----------------------------------------------------------
     * 发送下单并付款成功通知邮件
     * +----------------------------------------------------------
     * $order_sn 订单编号
     * +----------------------------------------------------------
     */
    function send_order_success_email($order_sn) {
        // 订单成功邮件提醒
        $order = $GLOBALS['dou']->get_row('order', '*', "order_sn = '$order_sn'");
        $order['add_time'] = date("Y-m-d H:i:s", $order['add_time']);
        
        $title = $GLOBALS['_LANG']['order_success'] . '：' . $order['order_sn'];
        $body  = $GLOBALS['_LANG']['order_add_time'] . '：' . $order['add_time'] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_sn'] . '：' . $order['order_sn'] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_order_amount'] . '：' . $order['order_amount'] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_status'] . '：' . $GLOBALS['_LANG']['order_status_' . $order['status']] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_contact'] . '：' . $order['contact'] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_phone'] . '：' . $order['phone'] . '<br/>';
        $body .= $GLOBALS['_LANG']['order_address'] . '：' . $order['address'];
        
        $GLOBALS['dou']->send_mail($GLOBALS['_CFG']['email'], $title, $body);
    }
    
    /**
     * +----------------------------------------------------------
     * 批量取消订单
     * +----------------------------------------------------------
     */
    function cancel_all($checkbox) {
        $sql_in = $GLOBALS['dou']->create_sql_in($_POST['checkbox']);
        
        // 取消所选订单
        $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET status = '-1' WHERE order_id " . $sql_in);
     
        // 商品下单付款后会锁定库存，付款后解锁，这里操作解锁（stock_lock = 0）
        $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order_item') . " SET stock_lock = '0' WHERE order_id " . $sql_in);
        
        $GLOBALS['dou']->create_admin_log($GLOBALS['_LANG']['order_cancel'] . ': ' . strtoupper('order') . ' ' . addslashes($sql_in));
        $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['order_cancel_success'], 'order.php');
    }
    
    /**
     * +----------------------------------------------------------
     * 获取支付方式列表
     * +----------------------------------------------------------
     */
    function get_payment_list() {
        if ($GLOBALS['dou']->table_exist('plugin')) {
            if (defined('IS_MOBILE') || $GLOBALS['dou']->is_mobile()) {
                $client = 'MOBILE';
            } else {
                $client = 'PC';
            }

            /* 获取支付方式列表 */
            $query = $GLOBALS['dou']->query("SELECT * FROM " . $GLOBALS['dou']->table('plugin') . " WHERE plugin_group = 'payment' AND (allow_client = '$client' OR allow_client = 'ALL')");

            $i = 0;
            while ($row = $GLOBALS['dou']->fetch_array($query)) {
                $image = ROOT_URL . 'include/plugin/' . $row['unique_id'] . '/icon.gif';
                $payment_list[] = array (
                        "id" => $row['unique_id'],
                        "name" => $row['name'],
                        "image" => $image,
                        "checked" => $i == 0 ? true : false
                );
                $i++;
            }

            return $payment_list;
        }
    }
    
    /**
     * +----------------------------------------------------------
     * 获取配送方式列表
     * +----------------------------------------------------------
     */
    function get_shipping_list() {
        if ($GLOBALS['dou']->table_exist('plugin')) {
            /* 获取配送方式列表 */
            $query = $GLOBALS['dou']->query("SELECT * FROM " . $GLOBALS['dou']->table('plugin') . " WHERE plugin_group = 'shipping'");

            $i = 0;
            while ($row = $GLOBALS['dou']->fetch_array($query)) {
                $config = unserialize($row['config']);
                $fee_format = $config['fee'] ? $GLOBALS['dou']->price_format($config['fee']) : $GLOBALS['_LANG']['order_shipping_free'];
                $free_format = preg_replace('/d%/Ums', $GLOBALS['dou']->price_format($config['free']), $GLOBALS['_LANG']['order_shipping_free_cue']);
                $shipping_list[] = array (
                        "unique_id" => $row['unique_id'],
                        "name" => $row['name'],
                        "description" => $row['other'],
                        "fee" => $config['fee'],
                        "fee_format" => $fee_format,
                        "free" => $config['free'],
                        "free_format" => $free_format,
                        "checked" => $i == 0 ? true : false
                );
                $i++;
            }

            return $shipping_list;
        }
    }
 
    /**
     * +----------------------------------------------------------
     * 更新订单可评论状态，检测可评论状态为1的订单，需要保证超过售后期限后将其标注为0
     * +----------------------------------------------------------
     */
    function auto_update_comment($and = '') {
        if ($GLOBALS['_OPEN']['comment']) {
            $and = $and ? " AND $and" : '';
            $timeout = ($GLOBALS['_PARAM']['order_allow_comment_time'] ? $GLOBALS['_PARAM']['order_allow_comment_time'] : 168) * 3600; // 3600秒等于1个小时，默认为168小时（7天）
            $time_limit = time() - $timeout;

            // 超过自动评价
            $sql = "SELECT * FROM " . $GLOBALS['dou']->table('order') . " WHERE allow_aftersale = '1' AND shipping_time < '$time_limit'" . $and;
            $query = $GLOBALS['dou']->query($sql);
            while ($row = $GLOBALS['dou']->fetch_array($query)) {
                $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET allow_comment = '0' WHERE order_id = '$row[order_id]'");
                $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order_item') . " SET comment = '1' WHERE order_id = '$row[order_id]'");
             
                // 自动好评
                $ip = $dou->get_ip();
                $add_time = time();
                $content = $GLOBALS['_LANG']['comment_content_default'];
                
                $sql_item = "SELECT * FROM " . $GLOBALS['dou']->table('order_item') . " WHERE order_id = '$row[order_id]' AND comment = '0'";
                $query_item = $GLOBALS['dou']->query($sql_item);
                while ($row = $GLOBALS['dou']->fetch_array($query_item)) {
                    $GLOBALS['dou']->query("INSERT INTO " . $GLOBALS['dou']->table('comment') . " (id, user_id, order_item_id, module, item_id, content, star, anonymous, ip, add_time)" . " VALUES (NULL, '$row[user_id]', '$row[id]', '$row[module]', '$row[item_id]', '$content', '5', '1', '$ip', '$add_time')");
                }
            }
        }
    }
 
    /**
     * +----------------------------------------------------------
     * 更新订单可申请售后状态，检测可申请售后状态为1的订单，需要保证超过售后期限后将其标注为0
     * +----------------------------------------------------------
     */
    function auto_update_aftersale_status($and = '') {
        if ($GLOBALS['_OPEN']['aftersale']) {
            $and = $and ? " AND $and" : '';
            $timeout = ($GLOBALS['_PARAM']['order_allow_aftersale_time'] ? $GLOBALS['_PARAM']['order_allow_aftersale_time'] : 168) * 3600; // 3600秒等于1个小时，默认为168小时（7天）
            $time_limit = time() - $timeout;

            // 超过期限将售后状态标记为不可申请售后
            $sql = "UPDATE " . $GLOBALS['dou']->table('order') . " SET allow_aftersale = '0' WHERE allow_aftersale = '1' AND shipping_time < '$time_limit'" . $and;
            $GLOBALS['dou']->query($sql);
        }
    }
 
    /**
     * +----------------------------------------------------------
     * 订单超过时间未付款，将自动取消，并释放库存
     * +----------------------------------------------------------
     */
    function auto_cancel_order($and = '') {
        // 如果没有开启付款插件则不自动取消订单
        if ($GLOBALS['dou']->table_exist('plugin')) {
            if (!$GLOBALS['dou']->value_exist('plugin', 'plugin_group', 'payment'))
                return;
        } else {
            return;
        }
        
        $and = $and ? " AND $and" : '';
        $timeout = ($GLOBALS['_PARAM']['order_pay_timeout'] ? $GLOBALS['_PARAM']['order_pay_timeout'] : 60)  * 60; // 60秒等于1分钟，默认为60分钟
        $time_limit = time() - $timeout;
        
        // 筛选出未付款的订单
        $sql = "SELECT * FROM " . $GLOBALS['dou']->table('order') . " WHERE status = '0' AND add_time < '$time_limit'" . $and;
        $query = $GLOBALS['dou']->query($sql);
        while ($row = $GLOBALS['dou']->fetch_array($query)) {
            // 更新订单状态
            if ($GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order') . " SET status = '-1' WHERE order_id = '$row[order_id]'")) {
                // 商品下单付款后会锁定库存，取消订单后解锁，这里操作解锁（stock_lock = 0）
                if ($row['module'] == 'product')
                    $GLOBALS['dou']->query("UPDATE " . $GLOBALS['dou']->table('order_item') . " SET stock_lock = '0' WHERE order_id = '$row[order_id]'");
            }
        }
    }
 
    /**
     * +----------------------------------------------------------
     * 购买限制
     * +----------------------------------------------------------
     */
    function check_stock($module, $item_id, $number) {
        // 验证购买限制前，先更新订单状态，订单超过时间未付款，将自动取消，并释放库存
        $this->auto_cancel_order();
        
        // 必须有库存字段，才会读取库存
        if ($GLOBALS['dou']->field_exist($module, 'stock'))
            $stock = $GLOBALS['dou']->get_one("SELECT stock FROM " . $GLOBALS['dou']->table($module) . " WHERE id = '$item_id'");
        
        // 必须有设置库存，才会通过减去库存锁定计算实时库存
        if ($stock)
            $real_time_stock = $this->real_time_stock($module, $item_id);
        
        // 必须有设置库存，并且购买数量超过实时库存，则提示库存不足
        if ($GLOBALS['_CFG']['stock'] && $number > $real_time_stock) {
            
            $data = array (
                    "code" => 'out_stock',
                    "real_time_stock" => $real_time_stock,
                    "msg" => $GLOBALS['_LANG']['order_out_stock'] . $real_time_stock
            );
        } else {
            $data = array (
                    "code" => 'without_limit',
                    "msg" => ''
            );
        }
        
        return $data;
    }
 
    /**
     * +----------------------------------------------------------
     * 计算时间差 86400 = 24x60x60 24小时
     * +----------------------------------------------------------
     */
    function time_limit($time_limit) {  
        $second = $time_limit;
     
        $day = floor($second / (3600*24));
        $second = $second % (3600 * 24);//除去整天之后剩余的时间
        $hour = sprintf("%02d", floor($second / 3600));
        $second = $second % 3600;//除去整小时之后剩余的时间
        $minute = sprintf("%02d", floor($second / 60));
        $second = sprintf("%02d", $second % 60);//除去整分钟之后剩余的时间
        
        //返回字符串
        return ($day ? $day . $GLOBALS['_LANG']['order_pay_time_out_day'] : '') . ($hour != '00' ? $hour . $GLOBALS['_LANG']['order_pay_time_out_hour'] : '') . ($minute != '00' ? $minute . $GLOBALS['_LANG']['order_pay_time_out_minute'] : '');
    }
 
    /**
     * +----------------------------------------------------------
     * 实时库存
     * +----------------------------------------------------------
     */
    function pay_time_limit($add_time = '', $short = false, $only_number = false) {  
        // 订单付款超时时间
        $timeout = ($GLOBALS['_PARAM']['order_pay_timeout'] ? $GLOBALS['_PARAM']['order_pay_timeout'] : 60) * 60; // 60秒等于1分钟，默认为60分钟
        
        // 显示付款超时时间
        $time_limit = $add_time ? $timeout - (time() - $add_time) : $timeout; // 如果有订单时间则显示剩余，没有则显示设定的超时时长
        $time_limit = $this->time_limit($time_limit);
        if (!$only_number) {
            $lang = $short ? $GLOBALS['_LANG']['order_pay_time_out_short'] : $GLOBALS['_LANG']['order_pay_time_out'];
            $time_limit = preg_replace('/d%/Ums', $time_limit, $lang);
        }
     
        return $time_limit;
    }
 
    /**
     * +----------------------------------------------------------
     * 实时库存
     * +----------------------------------------------------------
     */
    function real_time_stock($module, $item_id) {
        $stock_lock = $GLOBALS['dou']->get_one("SELECT SUM(item_number) FROM " . $GLOBALS['dou']->table('order_item') . " WHERE module = '$module' AND item_id = '$item_id' AND stock_lock = '1'");
        $stock = $GLOBALS['dou']->get_one("SELECT stock FROM " . $GLOBALS['dou']->table($module) . " WHERE id = '$item_id'");
        $real_time_stock = $stock - $stock_lock; // 实际库存 = 库存-锁定库存
        
        return $real_time_stock > 0 ? $real_time_stock : 0; 
    }

}
?>