作者 lihan

后台我的订单管理,订单确认页面全部完整接口逻辑,提交订单的余额支付和后续处理完整逻辑,以及下单时的完整校验,外加各种判断

@@ -15,6 +15,33 @@ class OrderController extends AdminBaseController @@ -15,6 +15,33 @@ class OrderController extends AdminBaseController
15 15
16 public function index() 16 public function index()
17 { 17 {
18 - 18 + $where = [];
  19 + $order_sn = request()->param('order_sn');
  20 + if ($order_sn != null) {
  21 + $where['order_sn'] = ['like', "%$order_sn%"];
  22 + }
  23 + $status = request()->param('status');
  24 + if ($status != null) {
  25 + $where['status'] = ['eq', $status];
  26 + }
  27 + $res = Db::name('order_info')->alias('o')
  28 + ->field('o.order_sn,o.id as oid,a.name,s.start_time,s.end_time,o.status,u.user_nickname')
  29 + ->join('activity a', 'a.id=o.activity_id')
  30 + ->join('activity_schedule s', 's.id=o.schedule_id')
  31 + ->join('user u', 'u.id=o.user_id')
  32 + ->where($where)
  33 + ->order('add_time DESC')
  34 + ->paginate(20, false, ['query' => request()->param()]);
  35 + foreach ($res as $k => $v) {
  36 + $v['status'] = getOrderStatusText($v['status']);
  37 + $res[$k] = $v;
  38 + }
  39 + return $this->fetch('', [
  40 + 'posts' => $res,
  41 + 'page' => $res->render(),
  42 + 'order_sn' => $order_sn,
  43 + 'status' => $status
  44 + ]);
19 } 45 }
  46 +
20 } 47 }
1 <?php 1 <?php
2 namespace app\order\controller; 2 namespace app\order\controller;
3 use app\coupons\model\CouponModel; 3 use app\coupons\model\CouponModel;
  4 +use app\order\model\OrderModel;
4 use cmf\controller\HomeBaseController; 5 use cmf\controller\HomeBaseController;
5 use think\Db; 6 use think\Db;
6 7
@@ -36,9 +37,10 @@ class OrderController extends HomeBaseController @@ -36,9 +37,10 @@ class OrderController extends HomeBaseController
36 $coupons = new CouponModel; 37 $coupons = new CouponModel;
37 $couponsList = $coupons->orderCoupon($post['activity_id'], $post['schedule_id'], $post['num'], session('user.id')); 38 $couponsList = $coupons->orderCoupon($post['activity_id'], $post['schedule_id'], $post['num'], session('user.id'));
38 $schedule = Db::name('activity_schedule') 39 $schedule = Db::name('activity_schedule')
39 - ->field('id as schedule_id,start_time,end_time,maximum,real_join_num,addition_join_num') 40 + ->field('id as schedule_id,start_time,end_time,maximum,real_join_num,addition_join_num,price')
40 ->where(['activity_id' => $post['activity_id']]) 41 ->where(['activity_id' => $post['activity_id']])
41 ->select(); 42 ->select();
  43 + $total = 0;
42 foreach ($schedule as $k => $v) { 44 foreach ($schedule as $k => $v) {
43 $v['start_time'] = date('Y.m.d', $v['start_time']); 45 $v['start_time'] = date('Y.m.d', $v['start_time']);
44 $v['end_time'] = date('Y.m.d', $v['end_time']); 46 $v['end_time'] = date('Y.m.d', $v['end_time']);
@@ -47,12 +49,22 @@ class OrderController extends HomeBaseController @@ -47,12 +49,22 @@ class OrderController extends HomeBaseController
47 unset($v['real_join_num']); 49 unset($v['real_join_num']);
48 unset($v['addition_join_num']); 50 unset($v['addition_join_num']);
49 unset($v['maximum']); 51 unset($v['maximum']);
  52 + if ($v['schedule_id'] == $post['schedule_id']) {
  53 + $v['checked'] = 1;
  54 + $v['num'] = $post['num'];
  55 + $total = $v['price'] * $post['num'];
  56 + } else {
  57 + $v['checked'] = 0;
  58 + }
  59 + unset($v['price']);
50 $schedule[$k] = $v; 60 $schedule[$k] = $v;
51 } 61 }
52 $result = [ 62 $result = [
53 - 'activity' => Db::name('activity')->field('id as activity,name')->where(['id' => $post['activity_id']])->find(), 63 + 'activity' => Db::name('activity')->field('id as activity_id,name, is_down_payment as type')->where(['id' => $post['activity_id']])->find(),
54 'schedule' => $schedule, 64 'schedule' => $schedule,
55 - 'coupons' => $couponsList 65 + 'coupons' => $couponsList,
  66 + 'down_price' => Db::name('activity')->where(['id' => $post['activity_id']])->value('down_price') * $post['num'],
  67 + 'total' => $total
56 ]; 68 ];
57 echo json_encode(['data' => $result]); 69 echo json_encode(['data' => $result]);
58 exit(); 70 exit();
@@ -70,7 +82,7 @@ class OrderController extends HomeBaseController @@ -70,7 +82,7 @@ class OrderController extends HomeBaseController
70 * @param name:num type:int require:1 default:2 desc:上一页选中的购买数量 82 * @param name:num type:int require:1 default:2 desc:上一页选中的购买数量
71 * @param name:escort type:char require:1 default:同行人id字符串(逗号分隔) desc:1,2,3 83 * @param name:escort type:char require:1 default:同行人id字符串(逗号分隔) desc:1,2,3
72 * @param name:payment type:int require:1 default:支付方式 desc:0余额,1微信,2支付宝 84 * @param name:payment type:int require:1 default:支付方式 desc:0余额,1微信,2支付宝
73 - * @param name:discount_coupon_id type:int require:1 default:1 desc:优惠券id 85 + * @param name:discount_coupon_id type:int require:1 default:112 desc:优惠券id
74 * @param name:room type:char require:1 default:1 desc:房间信息 86 * @param name:room type:char require:1 default:1 desc:房间信息
75 * @param name:desc type:text require:1 default:1 desc:商家备注 87 * @param name:desc type:text require:1 default:1 desc:商家备注
76 */ 88 */
@@ -89,12 +101,12 @@ class OrderController extends HomeBaseController @@ -89,12 +101,12 @@ class OrderController extends HomeBaseController
89 $data['order_type'] = $activity['is_down_payment']; 101 $data['order_type'] = $activity['is_down_payment'];
90 $data['is_use_discount_coupon'] = (empty($post['discount_coupon_id'])) ? 0 : 1; 102 $data['is_use_discount_coupon'] = (empty($post['discount_coupon_id'])) ? 0 : 1;
91 $data['discount_coupon_id'] = $post['discount_coupon_id']; 103 $data['discount_coupon_id'] = $post['discount_coupon_id'];
  104 + $data['payment'] = $post['payment'];
92 $data['status'] = 0; 105 $data['status'] = 0;
93 - if ($data['order_type'] == 0) {  
94 - $data['payment1'] = $post['payment'];  
95 - } else {  
96 - $post['payment2'] = $post['payment'];  
97 - } 106 + $data['room'] = $post['room'];
  107 + $data['desc'] = $post['desc'];
  108 + $final_price = $this->getFinalPrice($data['activity_id'], $data['schedule_id'], $post['num'], $data['discount_coupon_id']);
  109 + $this->checkOrder($data['schedule_id'], $data['payment'], $post['escort'], $post['num'], $final_price);
98 Db::startTrans(); 110 Db::startTrans();
99 if (Db::name('order_info')->insert($data)) { 111 if (Db::name('order_info')->insert($data)) {
100 $oid = Db::name('order_info')->getLastInsID(); 112 $oid = Db::name('order_info')->getLastInsID();
@@ -110,18 +122,19 @@ class OrderController extends HomeBaseController @@ -110,18 +122,19 @@ class OrderController extends HomeBaseController
110 ]; 122 ];
111 } 123 }
112 if (Db::name('order_detail')->insertAll($detail)) { 124 if (Db::name('order_detail')->insertAll($detail)) {
113 - Db::commit();  
114 - //选择支付方式0,1,2  
115 - //余额支付  
116 - if ($post['payment'] == 0) {  
117 -  
118 - } elseif ($post['payment'] == 1) {  
119 -  
120 - } elseif ($post['payment'] == 2) {  
121 -  
122 - } else {  
123 - echo json_encode(['msg' => '请选择支付方式', 'code' => 40000]);  
124 - exit(); 125 + //插入订单记录表(包含订单总价)
  126 + $log = [
  127 + 'oid' => $oid,
  128 + 'order_amount' => $final_price,
  129 + 'type' => $data['order_type']
  130 + ];
  131 + if (Db::name('order_log')->insert($log)) {
  132 + Db::commit();
  133 + $model = new OrderModel;
  134 + if ($model->orderCallBack($oid)) {
  135 + echo json_encode(['msg' => '下单成功', 'code' => 20000]);
  136 + exit();
  137 + }
125 } 138 }
126 } 139 }
127 } else { 140 } else {
@@ -136,4 +149,65 @@ class OrderController extends HomeBaseController @@ -136,4 +149,65 @@ class OrderController extends HomeBaseController
136 } 149 }
137 } 150 }
138 151
  152 + /**
  153 + * 计算订单最终价格
  154 + * @param $activityId
  155 + * @param $scheduleId
  156 + * @param $num
  157 + * @param null $discountCouponId
  158 + * @return float|int|mixed
  159 + * @throws \think\db\exception\DataNotFoundException
  160 + * @throws \think\db\exception\ModelNotFoundException
  161 + * @throws \think\exception\DbException
  162 + */
  163 + private function getFinalPrice($activityId, $scheduleId, $num, $discountCouponId = null)
  164 + {
  165 + $info = Db::name('activity')->field('is_down_payment,down_price')->where(['id' => $activityId])->find();
  166 + //如果有定金则支付定金*数量
  167 + if ($info['is_down_payment'] == 1) {
  168 + $sum = $info['down_price'] * $num;
  169 + } //如果没有定金则支付批次金额*数量
  170 + else {
  171 + $price = Db::name('activity_schedule')->where(['activity_id' => $activityId, 'id' => $scheduleId])->value('price');
  172 + $sum = $price * $num;
  173 + }
  174 + //如果有使用优惠券
  175 + if (!empty($discountCouponId)) {
  176 + //判断该优惠券是否已使用
  177 + $coupons = Db::name('discount_coupon')->field('status,reduce,overflow')->where(['id' => $discountCouponId])->find();
  178 + if ($coupons['status'] == 1) {
  179 + //是否符合满减
  180 + if ($sum >= $coupons['overflow']) {
  181 + $sum -= $coupons['reduce'];
  182 + }
  183 + }
  184 + }
  185 + return $sum;
  186 + }
  187 +
  188 + private function checkOrder($scheduleId, $payment = 0, $escort, $num, $finalPrice)
  189 + {
  190 + //判断支付方式
  191 + if ($payment != 0 && $payment != 1 && $payment != 2) {
  192 + echo json_encode(['msg' => '请选择支付方式', 'code' => 40000]);
  193 + exit();
  194 + }
  195 + //判断活动是否过期
  196 + if (Db::name('activity_schedule')->where(['id' => $scheduleId])->value('deadline') < time()) {
  197 + echo json_encode(['msg' => '本次活动已过期,请重新选择', 'code' => 40000]);
  198 + exit();
  199 + }
  200 + //判断用户余额能否支持余额支付
  201 + if (Db::name('user')->where(['id' => session('user.id')])->value('balance') < $finalPrice) {
  202 + echo json_encode(['msg' => '您的余额不足,请选择其他支付方式', 'code' => 40000]);
  203 + exit();
  204 + }
  205 + //判断出行人与购买数量是否匹配
  206 + $escortNum = (strlen($escort) == 1) ? 1 : count(explode(',', $escort));
  207 + if ($escortNum != $num) {
  208 + echo json_encode(['msg' => '购买数量需与出行人数量一致', 'code' => 40000]);
  209 + exit();
  210 + }
  211 + }
  212 +
139 } 213 }
@@ -11,18 +11,102 @@ use think\Db; @@ -11,18 +11,102 @@ use think\Db;
11 11
12 class OrderModel extends Model 12 class OrderModel extends Model
13 { 13 {
14 -  
15 //暂定 14 //暂定
16 - public function orderList($status, $orderSn) 15 + public function getOrderListByUserId($status, $orderSn, $userId)
17 { 16 {
18 - $where = []; 17 + $where['user_id'] = ['eq', $userId];
19 if ($orderSn != null) { 18 if ($orderSn != null) {
20 $where['order_sn'] = ['like', "%$orderSn%"]; 19 $where['order_sn'] = ['like', "%$orderSn%"];
21 } 20 }
22 - if ($status !== false) { 21 + if ($status != null) {
23 $where['status'] = ['eq', $status]; 22 $where['status'] = ['eq', $status];
24 } 23 }
25 - return Db::name('order_info')->where($where)->select(); 24 + $res = Db::name('order_info')->alias('o')
  25 + ->field('o.id as oid,o.order_sn,a.name,a.thumb,o.status')
  26 + ->join('activity a', 'a.id=o.activity_id')
  27 + ->where($where)
  28 + ->order('add_time DESC')
  29 + ->select()
  30 + ->toArray();
  31 + foreach ($res as $k => $v) {
  32 + $v['status_text'] = getOrderStatusText($v['status']);
  33 + $res[$k] = $v;
  34 + }
  35 + return $res;
  36 + }
  37 +
  38 + //通用订单回调类(未完待续。。。)
  39 + //余额扣除(如果余额支付->钱包记录)->优惠券变为已使用(如果使用优惠券)->改变订单状态(必然)->相应批次库存减少(必然)
  40 + public function orderCallBack($oid)
  41 + {
  42 + $orderInfo = Db::name('order_info')->alias('o')
  43 + ->field('o.user_id,o.is_use_discount_coupon,discount_coupon_id,o.status,o.payment,o.order_type,o.activity_id,o.schedule_id,l.order_amount')
  44 + ->join('order_log l', 'l.oid=o.id')
  45 + ->where(['o.id' => $oid])
  46 + ->find();
  47 + Db::startTrans();
  48 + $go = 'rollback';
  49 + if ($orderInfo['payment'] == 0) {
  50 + if (Db::name('user')->where(['id' => $orderInfo['user_id']])->setDec('balance', $orderInfo['order_amount'])) {
  51 + $wallet = [
  52 + 'user_id' => $orderInfo['user_id'],
  53 + 'type' => 0,
  54 + 'cost' => $orderInfo['order_amount'],
  55 + 'create_time' => time()
  56 + ];
  57 + if (Db::name('my_wallet')->insert($wallet)) {
  58 + $go = 'commit';
  59 + } else {
  60 + return false;
  61 + }
  62 + } else {
  63 + return false;
  64 + }
  65 + }
  66 + if ($orderInfo['is_use_discount_coupon'] == 1 && !empty($orderInfo['discount_coupon_id'])) {
  67 + $coupons = [
  68 + 'id' => $orderInfo['discount_coupon_id'],
  69 + 'use_time' => time(),
  70 + 'status' => 2
  71 + ];
  72 + if (Db::name('discount_coupon')->update($coupons)) {
  73 + $go = 'commit';
  74 + } else {
  75 + return false;
  76 + }
  77 + }
  78 + //订单状态无定金直接变为3,有定金变为1
  79 + if ($orderInfo['status'] == 0) {
  80 + if ($orderInfo['order_type'] == 0) {
  81 + $status = 3;
  82 + } elseif ($orderInfo['order_type'] == 1) {
  83 + $status = 1;
  84 + } else {
  85 + $status = 0;
  86 + }
  87 + $order = [
  88 + 'id' => $oid,
  89 + 'status' => $status
  90 + ];
  91 + if (Db::name('order_info')->update($order)) {
  92 + //相应批次报名数增加
  93 + $dec = Db::name('order_detail')->where(['oid' => $oid])->count();
  94 + if (Db::name('activity_schedule')->where(['id' => $orderInfo['schedule_id']])->setInc('real_join_num', $dec)) {
  95 + $go = 'commit';
  96 + } else {
  97 + return false;
  98 + }
  99 + } else {
  100 + return false;
  101 + }
  102 + }
  103 + if ($go == 'commit') {
  104 + Db::commit();
  105 + return true;
  106 + } else {
  107 + Db::rollback();
  108 + return false;
  109 + }
26 } 110 }
27 111
28 } 112 }
@@ -11,6 +11,7 @@ use app\coupons\model\CouponModel; @@ -11,6 +11,7 @@ use app\coupons\model\CouponModel;
11 use cmf\controller\HomeBaseController; 11 use cmf\controller\HomeBaseController;
12 use Think\Db; 12 use Think\Db;
13 use app\coupons\model\DiscountCouponModel; 13 use app\coupons\model\DiscountCouponModel;
  14 +use app\order\model\OrderModel;
14 15
15 /** 16 /**
16 * @title 个人中心模块 17 * @title 个人中心模块
@@ -27,6 +28,20 @@ class CenterController extends HomeBaseController @@ -27,6 +28,20 @@ class CenterController extends HomeBaseController
27 } 28 }
28 29
29 /** 30 /**
  31 + * @title 个人中心首页
  32 + * @description 默认访问接口
  33 + * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ
  34 + * @url /user/Center/index
  35 + * @method GET
  36 + */
  37 + public function index()
  38 + {
  39 + $userInfo = Db::name('user')->field('user_nickname,avatar')->where(['id' => session('user.id')])->find();
  40 + echo json_encode(['user_info' => $userInfo, 'code' => 20000]);
  41 + exit();
  42 + }
  43 +
  44 + /**
30 * @title 我的资料 45 * @title 我的资料
31 * @description 默认访问接口(post方式更改用户信息需要填写参数,post以外是模板渲染用户信息) 46 * @description 默认访问接口(post方式更改用户信息需要填写参数,post以外是模板渲染用户信息)
32 * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ 47 * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ
@@ -144,4 +159,33 @@ class CenterController extends HomeBaseController @@ -144,4 +159,33 @@ class CenterController extends HomeBaseController
144 exit(); 159 exit();
145 } 160 }
146 161
  162 + /**
  163 + * @title 订单列表
  164 + * @description 默认访问接口
  165 + * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ
  166 + * @url /user/Center/orderList
  167 + * @method POST
  168 + *
  169 + * @param name:status type:int require:1 default: desc:订单状态
  170 + * @param name:order_sn type:char require:1 default:201809091314 desc:订单号
  171 + * @return version:版本号
  172 + * @return code:错误码
  173 + */
  174 + public function orderList()
  175 + {
  176 + $request = request();
  177 + $order['status'] = $request->param('status');
  178 + $order['order_sn'] = $request->param('order_sn');
  179 + $model = new OrderModel;
  180 + $list = $model->getOrderListByUserId($order['status'], $order['order_sn'], session('user.id'));
  181 + if (!empty($list)) {
  182 + echo json_encode(['order_list' => $list, 'code' => 20000]);
  183 + exit();
  184 + } else {
  185 + echo json_encode(['msg' => '暂无数据', 'code' => 40000]);
  186 + exit();
  187 + }
  188 +
  189 + }
  190 +
147 } 191 }
  1 +<include file="public@header"/>
  2 +</head>
  3 +<body>
  4 +<div class="wrap js-check-wrap">
  5 + <ul class="nav nav-tabs">
  6 + <li class="active"><a href="javascript:;">全部订单</a></li>
  7 + </ul>
  8 +
  9 + <form class="well form-inline margin-top-20" method="post" action="{:url('Order/index')}">
  10 + 状态:
  11 + <select class="form-control" name="status" style="width: 140px;">
  12 + <option value='0' <if condition="$status eq '0'">selected</if>>全部</option>
  13 + <option value='1' <if condition="$status eq '1'">selected</if>>待付定金</option>
  14 + <option value='2' <if condition="$status eq '2'">selected</if>>已付定金</option>
  15 + <option value='3' <if condition="$status eq '3'">selected</if>>待付尾款</option>
  16 + <option value='4' <if condition="$status eq '4'">selected</if>>已付尾款</option>
  17 + <option value='5' <if condition="$status eq '5'">selected</if>>待评价</option>
  18 + <option value='6' <if condition="$status eq '6'">selected</if>>已完成</option>
  19 + <option value='7' <if condition="$status eq '7'">selected</if>>已取消</option>
  20 + </select> &nbsp;&nbsp;
  21 + 订单号:
  22 + <input type="text" class="form-control" name="order_sn" style="width: 200px;"
  23 + value="{$order_sn|default=''}" placeholder="请输入关键字...">
  24 + <input type="submit" class="btn btn-primary" value="搜索"/>
  25 + <a class="btn btn-danger" href="{:url('Order/index')}">清空</a>
  26 + </form>
  27 +
  28 + <form class="js-ajax-form" action="" method="post">
  29 + <table class="table table-hover table-bordered table-list">
  30 + <tr>
  31 + <th>序号</th>
  32 + <th>订单号</th>
  33 + <th>用户昵称</th>
  34 + <th>活动名称</th>
  35 + <th>批次时间</th>
  36 + <th>订单状态</th>
  37 + <th>操作</th>
  38 + </tr>
  39 + <volist name="posts" id="vo" key="k">
  40 + <tr>
  41 + <td>{$k}</td>
  42 + <td>{$vo.order_sn}</td>
  43 + <td>{$vo.user_nickname}</td>
  44 + <td>{$vo.name}</td>
  45 + <td>{$vo.start_time|date='Y.m.d', ###} 至 {$vo.end_time|date='Y.m.d', ###}</td>
  46 + <td>{$vo.status}</td>
  47 + <td>查看</td>
  48 + </tr>
  49 + </volist>
  50 + </table>
  51 + <ul class="pagination">{$page|default=''}</ul>
  52 + </form>
  53 +</div>
  54 +<script src="__STATIC__/js/admin.js"></script>
  55 +</body>
  56 +</html>
@@ -1888,3 +1888,17 @@ function getMonthEnglishWords($index) @@ -1888,3 +1888,17 @@ function getMonthEnglishWords($index)
1888 return $arr[$index]; 1888 return $arr[$index];
1889 } 1889 }
1890 1890
  1891 +function getOrderStatusText($status) {
  1892 + $text=[
  1893 + 0 => '未支付',
  1894 + 1 => '待付定金',
  1895 + 2 => '已付定金',
  1896 + 3 => '待付尾款',
  1897 + 4 => '已付尾款',
  1898 + 5 => '待评价',
  1899 + 6 => '已完成',
  1900 + 7 => '已取消'
  1901 + ];
  1902 + return $text[$status];
  1903 +}
  1904 +