<?php

namespace app\home\service;

use app\model\FeeSettingModel;
use app\admin\service\setting\IPOService as adminIPOService;
use app\model\TradeFeeModel;
use app\model\UserArrearsModel;
use think\facade\Db;
use think\facade\Queue;

class IPOService extends BaseHomeService
{

    // 列表
    public function index($marketType, $param)
    {
        try {
            if (empty($param['page']) || !is_numeric($param['page']) || empty($param['limit']) || !is_numeric($param['limit'])) {
                $param['page'] = 1;
                $param['limit'] = 10;
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $where = [];
            $where[] = ['is_delete', '=', 1];
            $where[] = ['status', '=', 1];

            $query = Db::table($tableObj['stock_table'])->where($where);
            $totalQuery = Db::table($tableObj['stock_table'])->where($where);
            // 申购状态筛选 1 可申购 2 带中签 3 待上市 4 已上市
            if (isset($param['open_status']) && in_array($param['open_status'], ['1', '2', '3', '4'])) {
                switch ($param['open_status']) {
                    case '1':
                        $query = $query->whereTime('end_time', '>', $nowDate);
                        $totalQuery = $totalQuery->whereTime('end_time', '>', $nowDate);
                        break;
                    case '2':
                        $query = $query->whereTime('end_time', '<', $nowDate)->where('sign_status', '=', 2);
                        $totalQuery = $totalQuery->whereTime('end_time', '<', $nowDate)->where('sign_status', '=', 2);
                        break;
                    case '3':
                        $query = $query->where('sign_status', '=', 1)->where('open_status', 1);
                        $totalQuery = $totalQuery->where('sign_status', '=', 1)->where('open_status', 1);
                        break;
                    case '4':
                        $query = $query->where('open_status', 2);
                        $totalQuery = $totalQuery->where('open_status', 2);
                        break;
                }
            }

            $list = $query->page($param['page'], $param['limit'])->order('open_time', 'desc')->select();
            $total = $totalQuery->count();

            $rows = [];
            if (!$list->isEmpty()) {
                foreach ($list as $item) {
                    // 是否延期开盘
                    $is_defer = '0';
                    if ($item['open_time'] < $nowDate && $item['open_status'] == 1) {
                        $is_defer = '1';
                    }

                    $is_start = '0';
                    if ($item['start_time'] <= $nowDate && $item['end_time'] >= $nowDate) {
                        $is_start = '1';
                    }

                    $progressStatus = 1;
                    if (time() >= $item['end_time']) $progressStatus = 2;
                    if ($item['sign_status'] == 1) $progressStatus = 3;
                    if ($item['is_post_pay'] == 2 && $item['pay_deadline_time'] < $nowDate) $progressStatus = 4;
                    if ($item['open_status'] == 2) $progressStatus = $item['is_post_pay'] == 2 ? 5 : 4;

                    $rows[] = [
                        'id' => $item['id'],
                        'stock_code' => $item['stock_code'],
                        'stock_name' => $item['stock_name'],
                        'stock_type' => $item['stock_type'],
                        'price' => $item['price'],
                        'min' => $item['min'],
                        'total' => $item['total'],
                        'tape' => $item['tape'],
                        'start_time' => $item['start_time'],
                        'end_time' => $item['end_time'],
                        'get_time' => $item['get_time'],
                        'open_time' => $item['open_time'],
                        'rate' => $item['rate'],
                        'is_defer' => $is_defer,
                        'is_start' => $is_start,
                        'is_post_pay' => $item['is_post_pay'],
                        'logo' => $item['logo'],
                        'company_info' => $item['company_info'],
                        'company_open_time' => $item['company_open_time'],
                        'company_reg_amount' => $item['company_reg_amount'],
                        'pay_deadline_time' => $item['pay_deadline_time'],
                        'progress_status' => $progressStatus,
                    ];
                }
            }

            $extend = (new adminIPOService)->getStockTape($marketType);
            return $this->toData('0', 'SUCCESS', ['list' => $rows, 'total' => $total, 'extend' => [
                'tape_list' => $extend['tape'],
                'stock_type_list' => $extend['type'],
            ]]);
        } catch (\Exception $exception) {
            return $this->toData('1', 'System error', [$exception->getMessage(),$exception->getTrace()]);
        }
    }

    // 股票详情
    public function stockDetail($marketType, $param)
    {
        try {
            if (empty($param['id']) || !is_numeric($param['id'])) {
                return $this->toData('1', 'Params error', []);
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $preStock = Db::table($tableObj['stock_table'])->where('id', $param['id'])->where('is_delete', 1)->where('status', 1)->find();
            if (empty($preStock)) {
                return $this->toData('1', 'Params error', []);
            }

            $is_defer = '0';
            if ($preStock['open_time'] < $nowDate && $preStock['open_status'] == 1) {
                $is_defer = '1';
            }

            $is_start = '0';
            if ($preStock['start_time'] <= $nowDate && $preStock['end_time'] >= $nowDate) {
                $is_start = '1';
            }

            $progressStatus = 1;
            if (time() >= $preStock['end_time']) $progressStatus = 2;
            if ($preStock['sign_status'] == 1) $progressStatus = 3;
            if ($preStock['is_post_pay'] == 2 && $preStock['pay_deadline_time'] < $nowDate) $progressStatus = 4;
            if ($preStock['open_status'] == 2) $progressStatus = $preStock['is_post_pay'] == 2 ? 5 : 4;

            $data = [
                'id' => $preStock['id'],
                'stock_code' => $preStock['stock_code'],
                'stock_name' => $preStock['stock_name'],
                'stock_type' => $preStock['stock_type'],
                'price' => $preStock['price'],
                'min' => $preStock['min'],
                'total' => $preStock['total'],
                'tape' => $preStock['tape'],
                'start_time' => $preStock['start_time'],
                'end_time' => $preStock['end_time'],
                'get_time' => $preStock['get_time'],
                'open_time' => $preStock['open_time'],
                'rate' => $preStock['rate'],
                'is_defer' => $is_defer,
                'is_start' => $is_start,
                'is_post_pay' => $preStock['is_post_pay'],
                'logo' => $preStock['logo'],
                'company_info' => $preStock['company_info'],
                'company_open_time' => $preStock['company_open_time'],
                'company_reg_amount' => $preStock['company_reg_amount'],
                'pay_deadline_time' => $preStock['pay_deadline_time'],
                'progress_status' => $progressStatus,
            ];

            $extend = (new adminIPOService)->getStockTape($marketType);
            return $this->toData('0', 'SUCCESS', ['data' => $data, 'extend' => [
                'tape_list' => $extend['tape'],
                'stock_type_list' => $extend['type'],
            ]]);
        } catch (\Exception $exception) {
            return $this->toData('1', 'System error', []);
        }
    }

    // 申购操作
    public function order($marketType, $param, $userId)
    {
        try {
            if (empty($param['id']) || !is_numeric($param['id'])) {
                return $this->toData('1', 'Params error', []);
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $preStock = Db::table($tableObj['stock_table'])->where('id', $param['id'])
                ->where('status', 1)
                ->where('is_delete', 1)
                ->whereTime('start_time', '<=', $nowDate)
                ->whereTime('end_time', '>=', $nowDate)
                ->find();
            if (empty($preStock)) {
                return $this->toData('1', 'Params error', []);
            }

            $hasOrder = Db::table($tableObj['order_table'])->where('user_id', $userId)->where('pre_stock_id', $param['id'])->count();
            if ($preStock['limit_get_num'] <= $hasOrder) {
                return $this->toData('1', 'Had Purchased', []);
            }

            // 下单参数
            if (empty($param['num']) || !is_numeric($param['num']) || ceil($param['num']) != $param['num'] || $param['num'] <= 0) {
                return $this->toData('1', 'Params error', []);
            }

            if ($param['num'] < $preStock['min']) {
                return $this->toData('1', 'Order quantity less than the minimum', []);
            }

            if ($preStock['max'] > 0 && $param['num'] > $preStock['max']) {
                return $this->toData('1', 'Order quantity greater than maximum', []);
            }

            if ($preStock['price'] <= 0) {
                return $this->toData('1', 'Price error', []);
            }

            // 支付类型
            if (empty($param['pay_type']) || !is_numeric($param['pay_type']) || !in_array($param['pay_type'], [1, 2])) {
                return $this->toData('1', 'Params error', []);
            }

            // 计算金额
            $amount = bcmul($param['num'], $preStock['price'], 18);
            // 计算手续费
            $purchaseFee = FeeSettingModel::where('market_type', $marketType)->value('purchase_fee');
            if($purchaseFee == null){
                return $this->toData('1', 'Setting error', []);
            }

            if ($purchaseFee <= 0) {
                $fee = 0;
            } else {
                $fee = bcmul($amount, $purchaseFee, 18);
            }

            Db::startTrans();
            $orderNo = $this->generateOrderNumber(20);
            $insertOrderArr = [
                'user_id' => $userId,
                'pre_stock_id' => $preStock['id'],
                'status' => $param['pay_type'] == 1 ? 1 : 5,
                'pay_type' => $param['pay_type'],
                'order_no' => $orderNo,
                'num' => $param['num'],
                'get_num' => 0,
                'price' => $preStock['price'],
                'amount' => $amount,
                'get_amount' => 0,
                'fee' => $fee,
                'get_fee' => 0,
                'fee_rate' => $purchaseFee,
                'get_time' => $preStock['get_time'],
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s'),
                'trade_status' => 0
            ];
            $insertOrderNum = Db::table($tableObj['order_table'])->insert($insertOrderArr);
            if ($insertOrderNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'create order error', []);
            }

            if ($param['pay_type'] == 2) {
                Db::commit();
                return $this->toData('0', 'SUCCESS', []);
            }

            // 扣除用户资产
            $beforeAmount = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
            if ($beforeAmount < $amount) {
                Db::rollback();
                return $this->toData('1', 'assert not enough', []);
            }

            $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                ->where('usable_num', '>=', $amount)->dec('usable_num', $amount)
                ->inc('frozen_num', $amount)
                ->update(['update_time' => $nowDate]);
            if ($updateNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'Update user amount error', []);
            }

            // 生成流水 
            $insertStockLogArr = [
                'user_id' => $userId,
                'change_type' => 15, // 新股申购扣减费用
                'stock_id' => $tableObj['stock_id'],
                'before_num' => $beforeAmount,
                'change_num' => '-' . $amount,
                'order_id' => $orderNo,
                'create_time' => $nowDate,
                'update_time' => $nowDate
            ];
            $insertStockLogNum = Db::table($tableObj['log_table'])->insert($insertStockLogArr);
            if ($insertStockLogNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'create user log error', []);
            }

            // 扣除手续费
            if ($fee > 0) {
                $beforeFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                if ($beforeFee < $fee) {
                    Db::rollback();
                    return $this->toData('1', 'assert not enough', []);
                }

                $updateNumFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                    ->where('usable_num', '>=', $fee)->dec('usable_num', $fee)
                    ->inc('frozen_num', $fee)
                    ->update(['update_time' => $nowDate]);
                if ($updateNumFee <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'Update user amount error', []);
                }

                // 生成流水
                $insertStockLogArrFee = [
                    'user_id' => $userId,
                    'change_type' => 16, // 新股申购扣减费用
                    'stock_id' => $tableObj['stock_id'],
                    'before_num' => $beforeFee,
                    'change_num' => '-' . $fee,
                    'order_id' => $orderNo,
                    'create_time' => $nowDate,
                    'update_time' => $nowDate
                ];
                $insertStockLogNumFee = Db::table($tableObj['log_table'])->insert($insertStockLogArrFee);
                if ($insertStockLogNumFee <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'create user log error', []);
                }
            }

            Db::commit();
            return $this->toData('0', 'SUCCESS', []);
        } catch (\Exception $exception) {
            Db::rollback();
            return $this->toData('1', 'System error', [$exception->getMessage(),$exception->getTrace()]);
        }
    }

    // 后支付 - 支付
    public function postPay1($marketType, $param, $userId)
    {
        try {
            if (empty($param['id']) || empty($param['stock_code']) || !is_numeric($param['id'])) {
                return $this->toData('1', 'Params error2', []);
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $preStock = Db::table($tableObj['stock_table'])->where('stock_code', $param['stock_code'])
                ->where('status', 1)
                ->where('is_delete', 1)
                ->where('is_post_pay', 2)
//                ->whereTime('pay_deadline_time', '>=', $nowDate)
                ->find();
            if (empty($preStock)) {
                return $this->toData('1', 'Payment deadline exceeded', []);
            }

            $hasOrder = Db::table($tableObj['order_table'])->where('user_id', $userId)->where('id', $param['id'])->where('pay_type', 2)->where('status', 5)->find();
            if (empty($hasOrder)) {
                return $this->toData('1', 'Params error3', []);
            }

            $orderNo = $hasOrder['order_no'];
            Db::startTrans();
            if ($preStock['sign_status'] == 1) {
                //已签名
                $amount = $hasOrder['get_amount'];
                $fee = $hasOrder['get_fee'];
                $getNum = $hasOrder['get_num'];
                if ($getNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'get num error', []);
                }

                // 扣除用户资产
                $beforeAmount = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                if ($beforeAmount < $amount) {
                    Db::rollback();
                    return $this->toData('1', 'assert not enough', []);
                }

                $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                    ->where('usable_num', '>=', $amount)->dec('usable_num', $amount)
                    ->inc('frozen_num', $amount)
                    ->update(['update_time' => $nowDate]);
                if ($updateNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'Update user amount error', []);
                }

                // 生成流水
                $insertStockLogArr = [
                    'user_id' => $userId,
                    'change_type' => 15, // 新股申购扣减费用
                    'stock_id' => $tableObj['stock_id'],
                    'before_num' => $beforeAmount,
                    'change_num' => '-' . $amount,
                    'order_id' => $orderNo,
                    'create_time' => $nowDate,
                    'update_time' => $nowDate
                ];
                $insertStockLogNum = Db::table($tableObj['log_table'])->insert($insertStockLogArr);
                if ($insertStockLogNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'create user log error', []);
                }

                // 扣除手续费
                if ($fee > 0) {
                    $beforeFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                    if ($beforeFee < $fee) {
                        Db::rollback();
                        return $this->toData('1', 'assert not enough', []);
                    }

                    $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                        ->where('usable_num', '>=', $fee)->dec('usable_num', $fee)
                        ->inc('frozen_num', $fee)
                        ->update(['update_time' => $nowDate]);
                    if ($updateNum <= 0) {
                        Db::rollback();
                        return $this->toData('1', 'Update user amount error', []);
                    }

                    // 生成流水
                    $insertStockLogArrFee = [
                        'user_id' => $userId,
                        'change_type' => 16, // 新股申购扣减费用
                        'stock_id' => $tableObj['stock_id'],
                        'before_num' => $beforeFee,
                        'change_num' => '-' . $fee,
                        'order_id' => $orderNo,
                        'create_time' => $nowDate,
                        'update_time' => $nowDate
                    ];
                    $insertStockLogNumFee = Db::table($tableObj['log_table'])->insert($insertStockLogArrFee);
                    if ($insertStockLogNumFee <= 0) {
                        Db::rollback();
                        return $this->toData('1', 'create user log error', []);
                    }
                }

                if ($preStock['open_status'] == 1) {
                    //未上市
                    $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 2, 'update_time' => $nowDate]);
                    if (!$bool) {
                        Db::rollback();
                        return $this->toData('1', 'update order error', []);
                    }

                } elseif ($preStock['open_status'] == 2) {
                    //已上市
                    $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 3, 'update_time' => $nowDate]);
                    if (!$bool) {
                        Db::rollback();
                        return $this->toData('1', 'update order error', []);
                    }

                    // 已上市 扣除手续费 冻结资金
                    $num = Db::table($tableObj['user_table'])->where('user_id', $userId)->where('stock_id', $tableObj['stock_id'])
                        ->dec('frozen_num', $hasOrder['get_fee'])
                        ->update(['update_time' => $nowDate]);
                    if ($num <= 0) {
                        Db::rollback();
                        trace('股票:' . $preStock['stock_code'] . ',扣除手续费失败,用户ID:' . $userId, 'error');
                    }
                    // 手续费流水
                    $tradeFee = new TradeFeeModel;
                    $tradeFee['user_id'] = $userId;
                    $tradeFee['account_type'] = $marketType;
                    $tradeFee['service_fee'] = $hasOrder['get_fee'];
                    $tradeFee['trade_type'] = 1;
                    $tradeFee['trade_no'] = $orderNo;
                    $tradeFee['create_time'] = date('Y-m-d H:i:s');
                    $bool = $tradeFee->save();
                    if (!$bool) {
                        Db::rollback();
                        trace('股票:' . $preStock['stock_code'] . ',生成手续费失败,用户ID:' . $userId, 'error');
                    }
                }
            } elseif ($preStock['sign_status'] == 2) {
                //未签名
                $amount = $hasOrder['amount'];
                $fee = $hasOrder['fee'];
                // 扣除用户资产
                $beforeAmount = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                if ($beforeAmount < $amount) {
                    Db::rollback();
                    return $this->toData('1', 'assert not enough', []);
                }

                $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                    ->where('usable_num', '>=', $amount)->dec('usable_num', $amount)
                    ->inc('frozen_num', $amount)
                    ->update(['update_time' => $nowDate]);
                if ($updateNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'Update user amount error', []);
                }

                // 生成流水
                $insertStockLogArr = [
                    'user_id' => $userId,
                    'change_type' => 15, // 新股申购扣减费用
                    'stock_id' => $tableObj['stock_id'],
                    'before_num' => $beforeAmount,
                    'change_num' => '-' . $amount,
                    'order_id' => $orderNo,
                    'create_time' => $nowDate,
                    'update_time' => $nowDate
                ];
                $insertStockLogNum = Db::table($tableObj['log_table'])->insert($insertStockLogArr);
                if ($insertStockLogNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'create user log error', []);
                }

                // 扣除手续费
                if ($fee > 0) {
                    $beforeFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                    if ($beforeFee < $fee) {
                        Db::rollback();
                        return $this->toData('1', 'assert not enough', []);
                    }

                    $updateNumFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                        ->where('usable_num', '>=', $fee)->dec('usable_num', $fee)
                        ->inc('frozen_num', $fee)
                        ->update(['update_time' => $nowDate]);
                    if ($updateNumFee <= 0) {
                        Db::rollback();
                        return $this->toData('1', 'Update user amount error', []);
                    }

                    // 生成流水
                    $insertStockLogArrFee = [
                        'user_id' => $userId,
                        'change_type' => 16, // 新股申购扣减费用
                        'stock_id' => $tableObj['stock_id'],
                        'before_num' => $beforeFee,
                        'change_num' => '-' . $fee,
                        'order_id' => $orderNo,
                        'create_time' => $nowDate,
                        'update_time' => $nowDate
                    ];
                    $insertStockLogNumFee = Db::table($tableObj['log_table'])->insert($insertStockLogArrFee);
                    if ($insertStockLogNumFee <= 0) {
                        Db::rollback();
                        return $this->toData('1', 'create user log error', []);
                    }
                }
                $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 1, 'update_time' => $nowDate]);
                if (!$bool) {
                    Db::rollback();
                    return $this->toData('1', 'update order error', []);
                }

            } else {
                Db::rollback();
                return $this->toData('1', 'Params error4', []);
            }
            Db::commit();

            //已上市IPO 订单通知交易 转持仓
            if ($preStock->open_status == 2){
                Queue::push('app\admin\job\SendGo', [
                    'type' => 'last_trade',
                    'id' => $preStock['id'],
                    'stock_code' => $preStock['stock_code'],
                    'order_no' => $orderNo,
                    'market_type' => $marketType,
                ], 'sendGo');
            }

            return $this->toData('0', 'SUCCESS', []);
        } catch (\Exception $exception) {
            Db::rollback();
            return $this->toData('1', 'System error110', [$exception->getMessage(),$exception->getTrace()]);
        }
    }
    public function postPay($marketType, $param, $userId){
        try {
            if (empty($param['id']) || empty($param['stock_code']) || !is_numeric($param['id'])) {
                return $this->toData('1', 'Params error2', []);
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $preStock = Db::table($tableObj['stock_table'])->where('stock_code', $param['stock_code'])
                ->where('status', 1)
                ->where('is_delete', 1)
                ->where('is_post_pay', 2)
//                ->whereTime('pay_deadline_time', '>=', $nowDate)
                ->find();
            if (empty($preStock)) {
                return $this->toData('1', 'Payment deadline exceeded', []);
            }
            if(strtotime($preStock['pay_deadline_time']) < time()){
                return $this->toData('1', 'The order has passed the payment deadline', []);
            }

            $hasOrder = Db::table($tableObj['order_table'])->where('user_id', $userId)->where('id', $param['id'])->where('pay_type', 2)->whereIn('status', [5,6])->find();
            if (empty($hasOrder)) {
                return $this->toData('1', 'Params error3', []);
            }

            $orderNo = $hasOrder['order_no'];
            Db::startTrans();

            if ($preStock['sign_status'] == 1) {
                //已签名
                $amount = $hasOrder['get_amount'];
                $fee = $hasOrder['get_fee'];
                $getNum = $hasOrder['get_num'];
            }else{
                //未签名
                $amount = $hasOrder['amount'];
                $fee = $hasOrder['fee'];
                $getNum = $hasOrder['num'];
            }
            if ($getNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'get num error', []);
            }

            // 扣除用户资产
            $beforeAmount = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
            if ($beforeAmount < $amount) {
                Db::rollback();
                return $this->toData('1', 'assert not enough', []);
            }
            $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                ->where('usable_num', '>=', $amount)->dec('usable_num', $amount)
                ->inc('frozen_num', $amount)
                ->update(['update_time' => $nowDate]);
            if ($updateNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'Update user amount error', []);
            }
            // 生成流水
            $insertStockLogArr = [
                'user_id' => $userId,
                'change_type' => 15, // 新股申购扣减费用
                'stock_id' => $tableObj['stock_id'],
                'before_num' => $beforeAmount,
                'change_num' => '-' . $amount,
                'order_id' => $orderNo,
                'create_time' => $nowDate,
                'update_time' => $nowDate
            ];
            $insertStockLogNum = Db::table($tableObj['log_table'])->insert($insertStockLogArr);
            if ($insertStockLogNum <= 0) {
                Db::rollback();
                return $this->toData('1', 'create user log error', []);
            }

            // 扣除手续费
            if ($fee > 0) {
                $beforeFee = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)->value('usable_num');
                if ($beforeFee < $fee) {
                    Db::rollback();
                    return $this->toData('1', 'assert not enough', []);
                }

                $updateNum = Db::table($tableObj['user_table'])->where('stock_id', $tableObj['stock_id'])->where('user_id', $userId)
                    ->where('usable_num', '>=', $fee)->dec('usable_num', $fee)
                    ->inc('frozen_num', $fee)
                    ->update(['update_time' => $nowDate]);
                if ($updateNum <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'Update user amount error', []);
                }
                // 生成流水
                $insertStockLogArrFee = [
                    'user_id' => $userId,
                    'change_type' => 16, // 新股申购扣减费用
                    'stock_id' => $tableObj['stock_id'],
                    'before_num' => $beforeFee,
                    'change_num' => '-' . $fee,
                    'order_id' => $orderNo,
                    'create_time' => $nowDate,
                    'update_time' => $nowDate
                ];
                $insertStockLogNumFee = Db::table($tableObj['log_table'])->insert($insertStockLogArrFee);
                if ($insertStockLogNumFee <= 0) {
                    Db::rollback();
                    return $this->toData('1', 'create user log error', []);
                }
            }

            if ($preStock['open_status'] == 1 && $preStock['sign_status'] == 1) {
                //未上市
                $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 2, 'update_time' => $nowDate]);
                if (!$bool) {
                    Db::rollback();
                    return $this->toData('1', 'update order error', []);
                }
            } elseif ($preStock['open_status'] == 2 && $preStock['sign_status'] == 1) {
                //已上市
                $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 3, 'update_time' => $nowDate]);
                if (!$bool) {
                    Db::rollback();
                    return $this->toData('1', 'update order error', []);
                }
                // 已上市 扣除手续费 冻结资金
                $num = Db::table($tableObj['user_table'])->where('user_id', $userId)->where('stock_id', $tableObj['stock_id'])
                    ->dec('frozen_num', $hasOrder['get_fee'])
                    ->update(['update_time' => $nowDate]);
                if ($num <= 0) {
                    Db::rollback();
                    trace('股票:' . $preStock['stock_code'] . ',扣除手续费失败,用户ID:' . $userId, 'error');
                }
                // 手续费流水
                $tradeFee = new TradeFeeModel;
                $tradeFee['user_id'] = $userId;
                $tradeFee['account_type'] = $marketType;
                $tradeFee['service_fee'] = $hasOrder['get_fee'];
                $tradeFee['trade_type'] = 1;
                $tradeFee['trade_no'] = $orderNo;
                $tradeFee['create_time'] = date('Y-m-d H:i:s');
                $bool = $tradeFee->save();
                if (!$bool) {
                    Db::rollback();
                    trace('股票:' . $preStock['stock_code'] . ',生成手续费失败,用户ID:' . $userId, 'error');
                }
            }

            if ($preStock['sign_status'] == 2){
                $bool = Db::table($tableObj['order_table'])->where('id', $param['id'])->update(['status' => 1, 'update_time' => $nowDate]);
                if (!$bool) {
                    Db::rollback();
                    return $this->toData('1', 'update order error', []);
                }
            }


            Db::commit();
            return $this->toData('0', 'SUCCESS', []);
        } catch (\Exception $exception) {
            Db::rollback();
            return $this->toData('1', 'System error', [$exception->getMessage(),$exception->getTrace()]);
        }
    }

    // 申购记录
    public function list($marketType, $param, $userId)
    {
        try {
            if (empty($param['page']) || !is_numeric($param['page']) || empty($param['limit']) || !is_numeric($param['limit'])) {
                $param['page'] = 1;
                $param['limit'] = 20;
            }

            if (empty($param['status'])) {
                return $this->toData('1', 'Params error');
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $nowDate = date('Y-m-d H:i:s');

            $statusArr = explode(",", $param['status']);
            $list = Db::table($tableObj['order_table'])->whereIn('status', $statusArr)->where('user_id', $userId)->order('update_time', 'desc')->page($param['page'], $param['limit'])->select();
            $total = Db::table($tableObj['order_table'])->whereIn('status', $statusArr)->where('user_id', $userId)->count();
            $rows = [];
            if (!$list->isEmpty()) {
                $stockIdList = [];
                foreach ($list as $item) {
                    $stockIdList[] = $item['pre_stock_id'];
                }

                $stockList = Db::table($tableObj['stock_table'])->where('id', 'in', $stockIdList)->column(['*'], 'id');

                // 计算手续费
                $purchaseFee = FeeSettingModel::where('market_type', $marketType)->value('purchase_fee');
                foreach ($list as $item) {
                    $stock = $stockList[$item['pre_stock_id']] ?? [];
                    $openTime = $stock['open_time'] ?? '';
                    $openStatus = $stock['open_status'] ?? '0';

                    // 是否延期开盘
                    $is_defer = '0';
                    if ($openTime && $openTime < $nowDate && $openStatus == 1) {
                        $is_defer = '1';
                    }
                    $arr = [
                        'id' => $item['id'],
                        'order_no' => $item['order_no'],
                        'stock_code' => $stock['stock_code'] ?? '-',
                        'stock_name' => $stock['stock_name'] ?? '-',
                        'get_time' => $stock['get_time'] ?? '-',
                        'open_time' => $stock['open_time'] ?? '-',
                        'num' => $item['num'],
                        'get_num' => $item['get_num'],
                        'price' => $item['price'],
                        'amount' => $item['amount'],
                        'get_amount' => $item['get_amount'],
                        'create_time' => $item['create_time'],
                        'fee' => $item['fee'],
                        'get_fee' => $item['get_fee'],
                        'status' => $item['status'],
                        'tape' => $stock['tape'] ?? '-',
                        'stock_type' => $stock['stock_type'] ?? '-',
                        'is_defer' => $is_defer,
                        'stock_data' => $stock,
                        'pay_deadline_time' => $stock['pay_deadline_time'] ?? '-',
                    ];

                    if ($item['pay_type'] == 2 && $item['status'] == 5 && empty($item['get_time'])) {
                        //后支付
                        $arr['amount'] = bcmul($item['get_num'], $item['price'], 18);
                        if ($purchaseFee <= 0) {
                            $arr['fee'] = 0;
                        } else {
                            $arr['fee'] = bcmul($arr['amount'], $purchaseFee, 18);
                        }
                    }
                    $rows[] = $arr;
                }
            }

            $extend = (new adminIPOService)->getStockTape($marketType);
            return $this->toData('0', 'SUCCESS', ['list' => $rows, 'total' => $total, 'extend' => [
                'tape_list' => $extend['tape'],
                'stock_type_list' => $extend['type'],
            ]]);
        } catch (\Exception $exception) {
            return $this->toData('1', 'System error', []);
        }
    }

    // 申购订单详情
    public function detail($marketType, $param, $userId)
    {
        try {
            if (empty($param['id']) || !is_numeric($param['id'])) {
                return $this->toData('1', 'Params error', []);
            }

            $tableObj = (new adminIPOService)->getStockModel($marketType);
            $order = Db::table($tableObj['order_table'])->where('user_id', $userId)->where('id', $param['id'])->find();
            if (empty($order)) {
                return $this->toData('1', 'Params error', []);
            }

            $stock = Db::table($tableObj['stock_table'])->where('id', $order['pre_stock_id'])->find();
            if (empty($stock)) {
                return $this->toData('1', 'Params error', []);
            }

            $is_defer = '0';
            if ($stock['open_status'] == 1) {
                $is_defer = '1';
            }

            $data = [
                'logo' => $stock['logo'],
                'stock_code' => $stock['stock_code'],
                'stock_name' => $stock['stock_name'],
                'stock_type' => $stock['stock_type'],
                'sign_status' => $stock['sign_status'],
                'num' => $order['num'],
                'get_num' => $order['get_num'],
                'amount' => $order['amount'],
                'get_amount' => $order['get_amount'],
                'price' => $order['price'],
                'fee' => $order['fee'],
                'order_no' => $order['order_no'],
                'get_fee' => $order['get_fee'],
                'create_time' => $order['create_time'],
                'get_time' => $order['get_time'],
                'open_time' => $stock['open_time'],
                'tape' => $stock['tape'],
                'is_defer' => $is_defer,
                'stock_data' => $stock,
                'pay_deadline_time' => $stock['pay_deadline_time'],
                'status' => $order['status']
            ];

            $extend = (new adminIPOService)->getStockTape($marketType);
            return $this->toData('0', 'SUCCESS', ['data' => $data, 'extend' => [
                'tape_list' => $extend['tape'],
                'stock_type_list' => $extend['type'],
            ]]);
        } catch (\Exception $exception) {
            return $this->toData('1', 'System error', [$exception->getMessage(),$exception->getTrace()]);
        }
    }


}