Order.php 10.7 KB
<?php

namespace app\common\model;

use think\Model;
use think\Db;

class Order extends Model
{
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';
    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';

    protected $append = [
        'status_text'
    ];

    // 错误提示
    public $error = '';

    /**
     * 订单商品列表
     */
    public function goods()
    {
        return $this->hasMany('OrderGoods');
    }

    /**
     * 关联订单收货地址表
     */
    public function address()
    {
        return $this->hasOne('OrderAddress');
    }

    /**
     * 关联售后表
     */
    public function refund()
    {
        return $this->hasOne('OrderRefund');
    }

    /**
     * 订单状态
     */
    public function getStatusTextAttr($value,$data){
        $status_text = '';
        if($data['refund_status'] > '0'){
            if($this['refund']['type'] == '1'){
                $refund_status_arr = ['1'=>'退款申请中','2'=>'已退款','3'=>'已拒绝'];
                $status_text = $refund_status_arr[$data['refund_status']];
            }else{
                $refund_status_arr = ['1'=>'退货申请中','2'=>'已退款','3'=>'已拒绝'];
                $status_text = $refund_status_arr[$data['refund_status']];
            }
        }else{
            if($data['pay_status'] == '0'){
                $status_text = '待支付';
            }else{
                if($data['delivery_status'] == '0'){
                    $status_text = '待发货';
                }else{
                    if($data['receive_status'] == '0'){
                        $status_text = '待收货';
                    }else{
                        if($data['appraise_status'] == '0'){
                            $status_text = '待评价';
                        }else{
                            $status_text = '已评价';
                        }
                    }
                }
            }
        }
        return $status_text;
    }

    /**
     * 新增订单
     */
    public function add($user_id, $order)
    {
        if (empty($order['address'])) {
            $this->error = '请先选择收货地址';
            return false;
        }
        Db::startTrans();
        // 记录订单信息
        $this->save([
            'user_id' => $user_id,
            'order_no' => date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8),
            'total_price' => $order['total_price'],
            'order_price' => $order['order_price'],
            'express_price' => $order['express_price'],
            'reduce_price' => $order['reduce_price'],
            'user_coupon_id' => $order['coupon']['user_coupon_id'],
            'coupon_price' => $order['coupon']['coupon_price'],
            'score' => $order['score']['score_price'] > 0 ? $order['score']['score'] : 0,
            'score_price' => $order['score']['score_price']
        ]);
        // 订单商品列表
        $goodsList = [];
        foreach ($order['goods_list'] as $goods) {
            $goodsList[] = [
                'goods_id' => $goods['goods_id'],
                'goods_name' => $goods['goods']['goods_name'],
                'goods_image' => $goods['goods']['goods_image'],
                'goods_price' => $goods['goods_price'],
                'goods_num' => $goods['goods_num'],
                'user_size_id' => !empty($goods['user_size']) ? $goods['user_size']['id'] : 0,
                'goods_style' => $goods['goods_style'],
                'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
                'goods_attr' => $goods['goods_sku']['goods_attr'],
                'goods_total_price' => $goods['goods_total_price']
            ];
        }
        // 保存订单商品信息
        $this->goods()->saveAll($goodsList);
        // 记录收货地址
        $this->address()->save([
            'name' => $order['address']['name'],
            'phone' => $order['address']['phone'],
            'province_id' => $order['address']['province_id'],
            'city_id' => $order['address']['city_id'],
            'district_id' => $order['address']['district_id'],
            'detail' => $order['address']['detail'],
        ]);
        // 用掉优惠券
        if($order['coupon']['user_coupon_id'] > 0){
            UserCoupon::where('id',$order['user_coupon_id'])->setField('status','2');
        }
        // 用掉积分
        if($order['score']['score'] > 0){
            User::score(-$order['score']['score'],$order['user_id'],'订单支付');
        }
        Db::commit();
        return true;
    }

    /**
     * 用户中心订单列表
     */
    public function getList($user_id, $type = 'all')
    {
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';//待支付
                $filter['pay_status'] = '0';
                $filter['refund_status'] = '0';
                break;
            case 'delivery';//待发货
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '0';
                $filter['refund_status'] = '0';
                break;
            case 'receive';//待收货
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '1';
                $filter['receive_status'] = '0';
                $filter['refund_status'] = '0';
                break;
            case 'appraise';//待评价
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '1';
                $filter['receive_status'] = '1';
                $filter['appraise_status'] = '0';
                $filter['refund_status'] = '0';
                break;
        }
        return $this->with('goods')
            ->where('user_id', $user_id)
            ->where('order_status', '<>', '2')
            ->where($filter)
            ->order(['createtime' => 'desc'])
            ->select();
    }

    /**
     * 订单详情
     */
    public function getUserOrderDetail($order_id, $user_id)
    {
        if (!$order = $this->get([
            'id' => $order_id,
            'user_id' => $user_id,
            'order_status' => ['<>', '2']
        ], ['goods' => ['goods','spec'], 'address'])) {
            $this->setError('订单不存在');
            return false;
        }
        return $order;
    }

    /**
     * 取消订单
     */
    public function cancel()
    {
        if ($this['pay_status'] == '1') {
            $this->setError('已付款订单不可取消');
            return false;
        }
        // 退回优惠券
        if($this['user_coupon_id'] > 0){
            UserCoupon::where('id',$this['user_coupon_id'])->setField('status','1');
        }
        // 退回积分
        if($this['score'] > 0){
            User::score(-$this['score'],$this['user_id'],'取消订单,退回积分');
        }
        return $this->save(['order_status' => '2']);
    }

    /**
     * 提醒发货
     */
    public function remind()
    {
        if ($this['delivery_status'] == '1') {
            $this->setError('订单已发货');
            return false;
        }
        if(cache('remind_'.$this['id'])){
            $this->setError('您已提醒发货,请稍后再提醒');
            return false;
        }
        cache('remind_'.$this['id'],$this['id'],60);
        return true;
    }

    /**
     * 申请退款
     */
    public function toRefund($post)
    {
        if(empty($post['refund_reason'])){
            $this->setError('请选择退款原因!');
            return false;
        }
        if($this['refund_status'] == '2'){
            $this->setError('订单已退款!');
            return false;
        }
        if($this['refund_status'] == '1'){
            $this->setError('正在申请退款中!');
            return false;
        }
        if($this['delivery_status'] == '1'){
            $this->setError('订单当前无法退款!');
            return false;
        }
        Db::startTrans();
        if(!$this['refund']){
            $this->refund()->save(array_merge([
                'type' => '1'
            ],$post));
        }else{
            $this['refund']->save($post);
        }
        $this->save(['refund_status'=>'1']);
        Db::commit();
        return true;
    }

    /**
     * 申请退货
     */
    public function returnGoods($post)
    {
        if(empty($post['refund_reason'])){
            $this->setError('请选择退货原因!');
            return false;
        }
        if($this['refund_status'] == '2'){
            $this->setError('订单已退货!');
            return false;
        }
        if($this['refund_status'] == '1'){
            $this->setError('正在申请退货中!');
            return false;
        }
        if($this['receive_status'] == '1'){
            $this->setError('订单当前无法退货!');
            return false;
        }
        Db::startTrans();
        if(!$this['refund']){
            $this->refund()->save(array_merge([
                'type' => '2'
            ],$post));
        }else{
            $this['refund']->save($post);
        }
        $this->save(['refund_status'=>'1']);
        Db::commit();
        return true;
    }

    /**
     * 确认收货
     */
    public function receive()
    {
        if ($this['delivery_status'] == '0' || $this['receive_status'] == '1') {
            $this->setError('该订单不合法');
            return false;
        }
        return $this->save([
            'receive_status' => '1',
            'receive_time' => time(),
            'order_status' => '3'
        ]);
    }

    /**
     * 判断商品库存不足 (未付款订单)
     */
    public function checkGoodsStatusFromOrder($goodsList)
    {
        foreach ($goodsList as $goods) {
            // 判断商品是否下架
            if ($goods['goods']['issale'] != '1') {
                $this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
                return false;
            }
            // 付款减库存
            if ($goods['spec']['stock_num'] < 1) {
                $this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
                return false;
            }
        }
        return true;
    }

    /**
     * 设置错误信息
     * @param $error
     */
    private function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 是否存在错误
     * @return bool
     */
    private function hasError()
    {
        return !empty($this->error);
    }

    /**
     * 获取错误信息
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }
}