<?php

namespace app\crontab\controller;

use app\common\logic\Queue;
use app\common\logic\Ticket;
use app\common\model\TicketOrder;
use think\facade\Cache;
use think\facade\Db;

/**
 * ============================================================================
 * DSMall多用户商城
 * ============================================================================
 * 版权所有 2014-2028 长沙德尚网络科技有限公司，并保留所有权利。
 * 网站地址: http://www.csdeshang.com
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用 .
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * 定时器
 */
class Minutes extends BaseCron
{
    const ORDER_CANCEL_TIME = 600;

    /**
     * 默认方法
     */
    public function index()
    {
        /*$this->_cron_queue();
        $this->_cron_common();
        $this->_cron_mail_send();
        $this->_cron_pintuan();
        $this->_cron_bonus();
        $this->_cron_pbargain();
        $this->_cron_presell();
        $this->_cron_sms();*/
        $this->_order_timeout_cancel();
        $this->_ticket_timeout_cancel();
        $this->_order_timeout_no_translate();
    }

    /**
     * 短信的处理
     */
    private function _cron_sms()
    {
        $smslog_model = model('smslog');
        $condition    = [];
        $condition[]  = ['smslog_state', '=', 0];
        $smslog_list  = $smslog_model->getSmsList($condition, '', 100, 'smslog_id asc');
        $sms          = new \sendmsg\Sms();
        foreach ($smslog_list as $val) {
            $smslog_param = json_decode($val['smslog_msg'], true);
            $smslog_msg   = $smslog_param['message'];
            $send_result  = $sms->send($val['smslog_phone'], $smslog_param);
            if ($send_result['code'] == true) {
                $smslog_state = 1;
            } else {
                $smslog_state = 2;
            }
            $condition   = [];
            $condition[] = ['smslog_id', '=', $val['smslog_id']];
            $update      = [
                'smslog_state'   => $smslog_state,
                'smslog_msg'     => $smslog_msg,
                'smslog_smstime' => TIMESTAMP,
            ];
            $smslog_model->editSms($update, $condition);
        }
    }

    /**
     * 预售活动的状态的处理
     */
    private function _cron_presell()
    {
        $presell_model = model('presell');
        //自动开始时间到期的店铺预售活动
        $condition   = [];
        $condition[] = ['presell_state', '=', 1];
        $condition[] = ['presell_start_time', '<', TIMESTAMP];
        $presell_model->editPresell(['presell_state' => 2], $condition);
        //自动结束时间过期的店铺预售活动
        $condition   = [];
        $condition[] = ['presell_end_time', '<', TIMESTAMP];
        $presell_model->endPresell($condition);
        //预售结束后72小时未付尾款取消订单
        $order_model = model('order');
        $logic_order = model('order', 'logic');
        $condition   = [];
        $condition[] = ['presell_deposit_amount', '>', 0];
        $condition[] = ['presell_end_time', '<', TIMESTAMP - 72 * 3600];
        $condition[] = ['order_state', 'in', [ORDER_STATE_NEW, ORDER_STATE_DEPOSIT, ORDER_STATE_REST]];

        $order_list = $order_model->getOrderList($condition, 100);
        foreach ($order_list as $order_info) {
            $logic_order->changeOrderStateCancel($order_info, 'system', '预售结束后72小时未付尾款取消订单');
        }
    }


    /**
     * 砍价活动的状态的处理
     */
    private function _cron_pbargain()
    {
        $pbargain_model = model('pbargain');
        //自动开始时间到期的店铺砍价活动
        $condition   = [];
        $condition[] = ['bargain_state', '=', 1];
        $condition[] = ['bargain_begintime', '<', TIMESTAMP];
        $pbargain_model->editBargain(['bargain_state' => 2], $condition);
        //自动结束时间过期的店铺砍价活动
        $condition   = [];
        $condition[] = ['bargain_endtime', '<', TIMESTAMP];
        $pbargain_model->endBargain($condition);
        //自动结束砍价失败的用户砍价活动
        $pbargainorder_model = model('pbargainorder');
        $condition           = 'bargainorder_state=1 AND bargainorder_endtime<' . TIMESTAMP . ' AND bargainorder_times<bargain_total';
        $pbargainorder_model->editPbargainorder($condition, ['bargainorder_state' => 3]);
    }

    /**
     * 邮件信息发送队列的处理
     */
    private function _cron_queue()
    {
        //获取当前存储的数量
        $QueueClientNum = Cache::get('QueueClientNum');
        var_dump('-----------队列执行开始-------------');
        var_dump('数量：' . $QueueClientNum);
        $QueueLogic = new Queue();
        for ($i = 1; $i <= $QueueClientNum; $i++) {
            $info = Cache::pull('QueueClient_' . $i);#获取缓存
            if (empty($info)) {
                continue;
            }
            $info  = unserialize($info);
            $key   = key($info);
            $value = current($info);
            $QueueLogic->$key($value);
        }
        var_dump('-----------队列结束-------------');
        Cache::set('QueueClientNum', NULL);
    }


    /**
     * 拼团相关处理
     */
    private function _cron_pintuan()
    {
        $ppintuan_model      = model('ppintuan');
        $ppintuangroup_model = model('ppintuangroup');
        $ppintuanorder_model = model('ppintuanorder');
        //自动关闭时间过期的店铺拼团活动
        $condition   = [];
        $condition[] = ['pintuan_end_time', '<', TIMESTAMP];
        $ppintuan_model->endPintuan($condition);


        //查看正在进行开团的列表.
        $condition         = [];
        $condition[]       = ['pintuangroup_state', '=', 1];
        $pintuangroup_list = $ppintuangroup_model->getPpintuangroupList($condition);

        $success_ids = [];#拼团开团成功的拼团开团ID
        $fail_ids    = [];#拼团开团失败的拼团开团ID
        foreach ($pintuangroup_list as $key => $pintuangroup) {

            //判断当前参团是否已过期
            if (TIMESTAMP >= $pintuangroup['pintuangroup_starttime'] + $pintuangroup['pintuangroup_limit_hour'] * 3600) {

                //当已参团人数  大于 当前开团的  参团人数   
                if ($pintuangroup['pintuangroup_joined'] >= $pintuangroup['pintuangroup_limit_number']) {

                    //满足开团人数,查看对应的订单是否付款,未付款则拼团失败,订单取消,订单款项退回.
                    $condition   = [];
                    $condition[] = ['ppintuanorder.pintuangroup_id', '=', $pintuangroup['pintuangroup_id']];

                    if (!$pintuangroup['pintuangroup_is_virtual']) {
                        $condition[] = ['order.order_state', '=', 20];
                        $count       = Db::name('ppintuanorder')->alias('ppintuanorder')->join('order order', 'order.order_id=ppintuanorder.order_id')->where($condition)->count();
                    } else {
                        $condition[] = ['vrorder.order_state', '=', 20];
                        $count       = Db::name('ppintuanorder')->alias('ppintuanorder')->join('vrorder vrorder', 'vrorder.order_id=ppintuanorder.order_id')->where($condition)->count();
                    }
                    if ($count == $pintuangroup['pintuangroup_joined']) {
                        //表示全部付款,拼团成功
                        $success_ids[] = $pintuangroup['pintuangroup_id'];
                    } else {
                        $fail_ids[] = $pintuangroup['pintuangroup_id'];
                    }
                } else {
                    //未满足开团人数
                    $fail_ids[] = $pintuangroup['pintuangroup_id'];
                }
            }
        }

        $condition = [];
        //在拼团失败的所有订单，已经付款的订单列表，取消订单,并且退款，未付款的订单自动取消订单
        $condition[]        = ['ppintuanorder.pintuangroup_id', 'in', implode(',', $fail_ids)];
        $condition[]        = ['ppintuanorder.pintuanorder_type', '=', 0];
        $condition[]        = ['order.order_state', '=', 20];
        $ppintuanorder_list = Db::name('ppintuanorder')->field('order.*')->alias('ppintuanorder')->join('order order', 'order.order_id=ppintuanorder.order_id')->where($condition)->select()->toArray();

        //针对已付款,拼团没成功的订单,进行取消订单以及退款操作
        $order_model = model('order');
        $logic_order = model('order', 'logic');

        foreach ($ppintuanorder_list as $key => $order_info) {
            try {
                Db::startTrans();
                $logic_order->changeOrderStateCancel($order_info, 'system', '系统', '拼团未成功系统自动关闭订单', true, false, true);
            } catch (\Exception $e) {
                Db::rollback();
                continue;
            }
            Db::commit();
        }


        $condition          = [];
        $condition[]        = ['ppintuanorder.pintuangroup_id', 'in', implode(',', $fail_ids)];
        $condition[]        = ['ppintuanorder.pintuanorder_type', '=', 1];
        $condition[]        = ['vrorder.order_state', '=', 20];
        $ppintuanorder_list = Db::name('ppintuanorder')->field('vrorder.*')->alias('ppintuanorder')->join('vrorder vrorder', 'vrorder.order_id=ppintuanorder.order_id')->where($condition)->select()->toArray();

        $logic_vrorder = model('vrorder', 'logic');

        foreach ($ppintuanorder_list as $key => $order_info) {
            $logic_vrorder->changeOrderStateCancel($order_info, 'system', '系统', '拼团未成功系统自动关闭订单', false);
        }

        //失败修改拼团相关数据库信息
        $condition   = [];
        $condition[] = ['pintuangroup_id', 'in', implode(',', $fail_ids)];
        $ppintuangroup_model->failPpintuangroup($condition);

        //成功修改拼团相关数据库信息
        $condition    = [];
        $condition[]  = ['pintuangroup_is_virtual', '=', 0];
        $condition[]  = ['pintuangroup_id', 'in', implode(',', $success_ids)];
        $condition2   = [];
        $condition2[] = ['pintuangroup_id', 'in', implode(',', $success_ids)];
        $ppintuangroup_model->successPpintuangroup($condition, $condition2);
        //给成功拼团的虚拟订单发送兑换码
        $vrorder_model = model('vrorder');
        $condition     = [];
        $condition[]   = ['order_promotion_type', '=', 2];
        $condition[]   = ['promotions_id', 'in', implode(',', $success_ids)];
        $vrorder_list  = $vrorder_model->getVrorderList($condition, 1000);
        foreach ($vrorder_list as $vrorder) {
            $vrorder_model->addVrorderCode($vrorder);
            $condition   = [];
            $condition[] = ['pintuangroup_id', '=', $vrorder['promotions_id']];
            $ppintuangroup_model->successPpintuangroup($condition, $condition);
        }
    }

    /**
     * 处理过期红包
     */
    private function _cron_bonus()
    {
        $condition   = [];
        $condition[] = ['bonus_endtime', '<', TIMESTAMP];
        $condition[] = ['bonus_state', '=', 1];
        $data        = [
            'bonus_state' => 2,
        ];
        model('bonus')->editBonus($condition, $data);
    }

    /**
     * 发送邮件消息
     */
    private function _cron_mail_send()
    {
        //每次发送数量
        $_num               = 50;
        $storemsgcron_model = model('mailcron');
        $cron_array         = $storemsgcron_model->getMailCronList([], $_num);
        if (!empty($cron_array)) {
            $email      = new \sendmsg\Email();
            $mail_array = [];
            foreach ($cron_array as $val) {
                $return = $email->send_sys_email($val['mailcron_address'], $val['mailcron_subject'], $val['mailcron_contnet']);
                if ($return) {
                    // 记录需要删除的id
                    $mail_array[] = $val['mailcron_id'];
                }
            }
            // 删除已发送的记录
            $storemsgcron_model->delMailCron([['mailcron_id', 'in', $mail_array]]);
        }
    }

    /**
     * 执行通用任务
     */
    private function _cron_common()
    {

        //查找待执行任务
        $cron_model = model('cron');
        $cron       = $cron_model->getCronList([['exetime', '<=', TIMESTAMP]]);

        if (!is_array($cron)) return;
        $cron_array = [];
        $cronid     = [];
        foreach ($cron as $v) {
            $cron_array[$v['type']][$v['exeid']] = $v;
        }
        foreach ($cron_array as $k => $v) {
            // 如果方法不存是，直接删除id
            if (!method_exists($this, '_cron_' . $k)) {
                $tmp      = current($v);
                $cronid[] = $tmp['id'];
                continue;
            }
            $result = call_user_func_array([$this, '_cron_' . $k], [$v]);
            if (is_array($result)) {
                $cronid = array_merge($cronid, $result);
            }
        }
        //删除执行完成的cron信息
        if (!empty($cronid) && is_array($cronid)) {
            $cron_model->delCron([['id', 'in', $cronid]]);
        }
    }

    /**
     * 上架
     *
     * @param array $cron
     */
    private function _cron_1($cron = [])
    {
        $condition = [['goods_commonid', 'in', array_keys($cron)]];
        $update    = model('goods')->editProducesOnline($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 根据商品id更新商品促销价格
     *
     * @param array $cron
     */
    private function _cron_2($cron = [])
    {
        $condition = [['goods_id', 'in', array_keys($cron)]];
        $update    = model('goods')->editGoodsPromotionPrice($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 优惠套装过期
     *
     * @param array $cron
     */
    private function _cron_3($cron = [])
    {
        $pbundling_model = model('pbundling');
        if (intval(config('ds_config.promotion_bundling_price')) != 0) {
            //如果没有购买过套餐，则将之前添加的优惠组合关闭
            Db::name('pbundling')->alias('pbundling')->join('pbundlingquota pbundlingquota', 'pbundling.store_id = pbundlingquota.store_id', 'LEFT')->where('pbundlingquota.store_id', null)->update(['bl_state' => $pbundling_model::STATE0]);
        }
        $condition = [['store_id', 'in', array_keys($cron)]];
        $update    = $pbundling_model->editBundlingQuotaClose($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 推荐展位过期
     *
     * @param array $cron
     */
    private function _cron_4($cron = [])
    {
        $pbooth_model = model('pbooth');
        if (intval(config('ds_config.promotion_bundling_price')) != 0) {
            //如果没有购买过套餐，则将之前添加的优惠组合关闭
            Db::name('pboothgoods')->alias('pboothgoods')->join('pboothquota pboothquota', 'pboothgoods.store_id = pboothquota.store_id', 'LEFT')->where('pboothquota.store_id', null)->update(['boothgoods_state' => $pbooth_model::STATE0]);
        }
        $condition = [['store_id', 'in', array_keys($cron)]];
        $update    = $pbooth_model->editBoothClose($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 抢购开始更新商品促销价格
     *
     * @param array $cron
     */
    private function _cron_5($cron = [])
    {
        $condition   = [];
        $condition[] = ['goods_commonid', 'in', array_keys($cron)];
        $condition[] = ['groupbuy_starttime', '<', TIMESTAMP];
        $condition[] = ['groupbuy_endtime', '>', TIMESTAMP];
        $groupbuy    = model('groupbuy')->getGroupbuyList($condition);
        foreach ($groupbuy as $val) {
            model('goods')->editGoods(['goods_promotion_price' => $val['groupbuy_price'], 'goods_promotion_type' => 1], ['goods_commonid' => $val['goods_commonid']]);
        }
        //返回执行成功的cronid
        $cronid = [];
        foreach ($cron as $v) {
            $cronid[] = $v['id'];
        }
        return $cronid;
    }

    /**
     * 抢购过期
     *
     * @param array $cron
     */
    private function _cron_6($cron = [])
    {
        $condition = [['goods_commonid', 'in', array_keys($cron)]];
        //抢购活动过期
        $update = model('groupbuy')->editExpireGroupbuy($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 限时折扣过期
     *
     * @param array $cron
     */
    private function _cron_7($cron = [])
    {
        $condition = [['xianshi_id', 'in', array_keys($cron)]];
        //限时折扣过期
        $update = model('pxianshi')->editExpireXianshi($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 批发过期
     *
     * @param array $cron
     */
    private function _cron_8($cron = [])
    {
        $condition = [['wholesale_id', 'in', array_keys($cron)]];
        //限时折扣过期
        $update = model('wholesale')->editExpireWholesale($condition);
        if ($update) {
            //返回执行成功的cronid
            $cronid = [];
            foreach ($cron as $v) {
                $cronid[] = $v['id'];
            }
        } else {
            return false;
        }
        return $cronid;
    }

    /**
     * 未付款订单超期自动关闭
     */
    private function _order_timeout_cancel()
    {

        //实物订单超期未支付系统自动关闭
        $_break            = false;
        $chain_order_model = model('chain_order');
        $order_model       = model('order');
        $logic_order       = model('order', 'logic');
        $condition         = [];
        $condition[]       = ['order_state', '=', ORDER_STATE_NEW];
        $condition[]       = ['add_time', '<', TIMESTAMP - self::ORDER_CANCEL_TIME];
        //分批，每批处理100个订单，最多处理5W个订单
        for ($i = 0; $i < 500; $i++) {
            if ($_break) {
                break;
            }
            $order_list = $order_model->getOrderList($condition, '', '*', '', 100);
            if (empty($order_list))
                break;
            foreach ($order_list as $order_info) {
                try {
                    Db::startTrans();
                    $member = Db::name('member')->where('member_id', $order_info['buyer_id'])->find();
                    $logic_order->changeOrderStateCancel($order_info, 'system', '系统', '超期未支付系统自动关闭订单', true, false);
                    $logic_order->orderCancelBack($order_info, $member);
                } catch (\Exception $e) {
                    Db::rollback();
                    $this->log('实物订单超期未支付关闭失败SN:' . $order_info['order_sn']);
                    $_break = true;
                    break;
                }
                Db::commit();

                $chain_order_model->editChainOrderCancel($order_info['order_id']);
            }
        }

        //虚拟订单超期未支付系统自动关闭
        $_break        = false;
        $vrorder_model = model('vrorder');
        $logic_vrorder = model('vrorder', 'logic');
        $condition     = [];
        $condition[]   = ['order_state', '=', ORDER_STATE_NEW];
        $condition[]   = ['add_time', '<', TIMESTAMP - self::ORDER_CANCEL_TIME];

        //分批，每批处理100个订单，最多处理5W个订单
        for ($i = 0; $i < 500; $i++) {
            if ($_break) {
                break;
            }
            $order_list = $vrorder_model->getVrorderList($condition, '', '*', '', 100);
            if (empty($order_list))
                break;
            foreach ($order_list as $order_info) {
                $member = Db::name('member')->where('member_id', $order_info['buyer_id'])->find();
                $result = $logic_vrorder->changeOrderStateCancel($order_info, 'system', '超期未支付系统自动关闭订单', false);
                $logic_vrorder->orderCancelBack($order_info, $member);
            }
            if (!$result['code']) {
                $this->log('虚拟订单超期未支付关闭失败SN:' . $order_info['order_sn']);
                $_break = true;
                break;
            }
        }
    }

    /**
     * 电影票超时取消
     */
    private function _ticket_timeout_cancel()
    {
        $ticket_model = new TicketOrder();
        $logic_ticket = new Ticket();
        $condition    = [];
        $condition[]  = ['order_state', '=', ORDER_STATE_NEW];
        $condition[]  = ['add_time', '<', TIMESTAMP - self::ORDER_CANCEL_TIME];
        $order_list   = $ticket_model->where($condition)->select();
        if (!$order_list->isEmpty()) {
            foreach ($order_list as $order_info) {
                $logic_ticket->changeOrderStateCancel($order_info);
            }
        }
    }



    /**
     * 实物订单已付款24小时未发货，增加短信提醒
     */
    private function _order_timeout_no_translate()
    {
        //获取超时订单
        $out_time   = TIMESTAMP - (60 * 60 * 24);
        $order_list = Db::name('order')
            ->where('order_state', 20)
            ->where('payment_time', '<', $out_time)
            ->where('timeout_no_translate_message', 0)
            ->select();

        //获取店铺信息
        $store_ids = [];
        foreach ($order_list as $v) {
            $store_ids[] = $v['store_id'];
        }
        $store_list = Db::name('store')->where('store_id', 'in', $store_ids)->column('store_phone', 'store_id');

        //发送短信
        $smslog_model   = model('smslog');
        $storemsg_model = model('storemsg');
        foreach ($order_list as $v) {
            $store_phone = $store_list[$v['store_id']];
            if (!empty($store_phone)) {
                $smslog_model->sendSms($store_phone, ['message' => '福利商城有订单已超过24小时未发货，订单号：' . $v['order_sn'] . '请及时发货']);
            }
            Db::name('order')->where('order_id', $v['order_id'])->update(['timeout_no_translate_message' => 1]);

            $storemsg_model->addStoremsg([
                'storemt_code'     => 'timeout_no_translate',
                'store_id'         => $v['store_id'],
                'storemsg_content' => '福利商城有订单已超过24小时未发货，订单号：' . $v['order_sn'] . '请及时发货',
            ]);
        }
    }
}

?>
