DiverseYouthNightSchool/application/common/model/school/classes/hourorder/Order.php

653 lines
22 KiB
PHP

<?php
namespace app\common\model\school\classes\hourorder;
use app\common\model\school\classes\ClassesLib;
use app\common\model\school\classes\ClassesSpec;
use app\common\model\User;
use bw\Common;
use fast\Random;
use think\Cache;
use think\Model;
use traits\model\SoftDelete;
use app\common\model\BaseModel;
class Order extends BaseModel
{
use SoftDelete;
// 表名
protected $name = 'school_classes_hour_order';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = 'deletetime';
// 追加属性
protected $append = [
'start_time_text',
'end_time_text',
'status_text',
'reservation_time_text',
'finish_time_text',
'cancel_time_text'
];
public function getStatusList()
{
return ['-3' => __('Status -3'),'-1' => __('Status -1'), '0' => __('Status 0'), '3' => __('Status 3')];
}
public function getStartTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['start_time']) ? $data['start_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getEndTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['end_time']) ? $data['end_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getReservationTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['reservation_time']) ? $data['reservation_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getFinishTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['finish_time']) ? $data['finish_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getCancelTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['cancel_time']) ? $data['cancel_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
protected function setStartTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setEndTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setReservationTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setFinishTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setCancelTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function classesorder()
{
return $this->belongsTo('app\common\model\school\classes\order\Order', 'classes_order_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function spec()
{
return $this->belongsTo('app\common\model\school\classes\ClassesSpec', 'classes_lib_spec_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function user()
{
return $this->belongsTo('app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function detail()
{
return $this->belongsTo('app\common\model\school\classes\order\OrderDetail', 'classes_order_detail_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function lib()
{
return $this->belongsTo(ClassesLib::class, 'classes_lib_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
/**得到基础条件
* @param $status
* @param null $model
* @param string $alisa
*/
public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false)
{
if (!$model) {
$model = new static;
if ($alisa&&!$with) $model = $model->alias($alisa);
}
if ($alisa) $alisa = $alisa . '.';
$tableFields = (new static)->getTableFields();
foreach ($tableFields as $fields)
{
if(in_array($fields, ['status','classes_lib_id']))continue;
// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
if (isset($whereData[$fields]) && $whereData[$fields]){
if(is_array($whereData[$fields])){
$model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]);
}else{
$model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
}
}
}
if (isset($whereData['status'])) $model = $model->where("{$alisa}status", 'in', $whereData['status']);
if (isset($whereData['not_status'])) $model = $model->where("{$alisa}status", 'not in', $whereData['not_status']);
if (isset($whereData['keywords'])&&$whereData['keywords']) $model = $model->where("{$alisa}order_no|{$alisa}id", '=', $whereData['keywords']);
if (isset($whereData['time'])&&$whereData['time']){
$model = $model->time($whereData['time']);
}
if (isset($whereData['user_id']) && $whereData['user_id']) $model = $model->where("{$alisa}user_id", '=', $whereData['user_id']);
if (isset($whereData['classes_lib_ids']) && $whereData['classes_lib_ids']) $model = $model->where("{$alisa}classes_lib_id", 'in', $whereData['classes_lib_ids']);
if (isset($whereData['classes_lib_id']) && $whereData['classes_lib_id']) $model = $model->where("{$alisa}classes_lib_id", 'in', $whereData['classes_lib_id']);
return $model;
}
/**展示订单信息
* @param $order_no
* @param $price_info
* @return array
*/
public static function showInfo($order_no, $price_info = []){
$data = [];
$data['order_no'] =$order_no;
$data['order_info'] = self::getDetail($order_no);
return array_merge($data,$price_info);
}
/**得到订单详情
* @param $order_no
*/
public static function getDetail($order_no,$classes_lib_id = [],$classes_lib_ids = []){
$model = self::where('order_no|id',$order_no);
if($classes_lib_id)$model = $model->where("classes_lib_id","in",$classes_lib_id);
if($classes_lib_ids)$model = $model->where("classes_lib_id","in",$classes_lib_ids);
$data = $model->find();
if(!$data) return $data;
//加载订单详情
$data->detail->teacher;
//订单用户
$data->user->visible(['id','nickname','mobile','avatar','realname']);
//订单机构
$data->classesorder;
// //得到二维码
// $data->code_url = Common::getQrcode([
// 'text' => $data['code'],
// 'size' => 200,
// ]);
// $data->one_code_url = Common::getBarcode([
// 'text' => $data['code'],
// 'size' => 200,
// ]);
return $data;
}
public static function allList($user_id,$page, $limit,$keywords,$status,$classes_order_id=0,$classes_lib_id = []){
$with_field = [
'user'=>['nickname','mobile','avatar','realname'],
'base'=>['*'],
'classesorder'=>['*'],
'detail'=>['*'],
];
$CANCEL = '-3';
$NOAUDIT = '-1';
$HAVE = '0';
$FINISH = '3';
$alisa = (new self)->getWithAlisaName();
$sort = "field({$alisa}.status,'{$NOAUDIT}','{$HAVE}','{$FINISH}','{$CANCEL}') asc,{$alisa}.id desc";
$serch_where = ['status'=>$status,'user_id'=>$user_id,'keywords'=>$keywords,'classes_order_id'=>$classes_order_id,'classes_lib_id'=>$classes_lib_id];
// if($type)$serch_where['type'] = $type;
return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field);
}
public static function baseCount($where = []){
$CANCEL = '-3';
$NOAUDIT = '-1';
$HAVE = '0';
$FINISH = '3';
$cancel_number = self::getBaseWhere(array_merge(['status'=>$CANCEL],$where))->count();
$noaudit_number = self::getBaseWhere(array_merge(['status'=>$NOAUDIT],$where))->count();
$have_number = self::getBaseWhere(array_merge(['status'=>$HAVE],$where))->count();
$finish_number = self::getBaseWhere(array_merge(['status'=>$FINISH],$where))->count();
return compact('cancel_number','noaudit_number','have_number','finish_number');
}
/**订单数量统计
* @param int $user_id
* @return array
*/
public static function orderCount($user_id = 0,$classes_order_id=0,$classes_lib_id=[]){
return self::baseCount(['user_id'=>$user_id,'classes_order_id'=>$classes_order_id,"classes_lib_id"=>$classes_lib_id]);
}
public static function workList($page, $limit,$keywords,$status,$classes_order_id=0,$user_id=0,$classes_lib_id = [],$classes_lib_ids = []){
$with_field = [
'user'=>['nickname','mobile','avatar','realname'],
'base'=>['*'],
'classesorder'=>['*'],
'detail'=>['*'],
];
$CANCEL = '-3';
$NOAUDIT = '-1';
$HAVE = '0';
$FINISH = '3';
$alisa = (new self)->getWithAlisaName();
$sort = "field({$alisa}.status,'{$NOAUDIT}','{$HAVE}','{$FINISH}','{$CANCEL}') asc,{$alisa}.id desc";
$serch_where = ['status'=>$status,'user_id'=>$user_id,'keywords'=>$keywords,'classes_order_id'=>$classes_order_id,"classes_lib_id"=>$classes_lib_id,"classes_lib_ids"=>$classes_lib_ids];
// if($type)$serch_where['type'] = $type;
return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field);
}
/**订单数量统计
* @param int $user_id
* @return array
*/
public static function workCount($classes_lib_id = [],$classes_lib_ids = [],$classes_order_id=0){
return self::baseCount(['classes_lib_id'=>$classes_lib_id,'classes_order_id'=>$classes_order_id,"classes_lib_ids"=>$classes_lib_ids]);
}
/**
* 设置订单缓存
* @param $uid
* @param $data
* @return bool
*/
public static function setOrderCache($uid, $data)
{
//缓存名 = uid + order_no
$cacheNmae = 'classes_hourorder_cache' . $uid . $data['order_no'];
// 缓存在3600秒之后过期
return Cache::set($cacheNmae, $data, config("site.unpaid_order_expire_time"));
}
/**
* 得到订单缓存
* @param $uid
* @param $order_no
* @return mixed
*/
public static function getOrderCache($uid, $order_no)
{
//缓存名 = uid + order_no
$cacheNmae = 'classes_hourorder_cache' . $uid . $order_no;
// 缓存在3600秒之后过期
return Cache::get($cacheNmae);
}
/**
* 删除订单缓存
* @param $uid
* @param $order_no
* @return mixed
*/
public static function deleteOrderCache($uid, $order_no)
{
//缓存名 = uid + order_no
$cacheNmae = 'classes_hourorder_cache' . $uid . $order_no;
// 缓存在3600秒之后过期
return Cache::rm($cacheNmae);
}
/** 订单确认(订单计算)
* @param $user_id 下单用户
* @param $order_no 订单号(缓存标识)
* @param $classes_order_id 課程订单id
* @param $classes_lib_spec_id 課程课时规格id
* @param $param 額外参数(扩展用)
* @param bool $is_compute 是否重新计算订单
* @return array
*/
public function confirm($user_id, $classes_order_id,$order_no,$classes_lib_spec_id=0,$param=[], $is_compute = false)
{
if ($order_no && !$is_compute) {
//得到缓存
$data = self::getOrderCache($user_id, $order_no);
if (!$data) throw new \Exception('請您完善預約信息!');
$price_info = $data['price_info'];
} else {
//订单信息计算
// if(!$param) throw new \Exception('缺少必要信息');
$this->orderVaild($user_id,$classes_order_id,$order_no,$classes_lib_spec_id, $param);
//订单支付信息
$price_info = $this->getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param);
//生成订单号
if (!$order_no) $order_no = get_order_sn();
//生成缓存
$data = compact('user_id', 'classes_order_id','param', 'order_no', 'price_info','classes_lib_spec_id');
self::setOrderCache($user_id, $data);
}
\think\Hook::listen('classeshour_order_create_before', $data);
//下单数据展示
return $this->showInfo($order_no, $price_info);
}
/**订单校验
* @param $user_id 用户id
* @param $classes_order_id 课程订单id
* @param $order_no 订单号
* @param $param 表单扩展参数
* @return bool
*/
public function orderVaild($user_id,$classes_order_id,$order_no,$classes_lib_spec_id, $param,$check=false){
if(!$user_id||!$classes_order_id)throw new \Exception("缺少必要参数");
//默认校验订单是否已创建
if($check){
//判断订单是否已创建
$order_info = self::where(['order_no'=>$order_no])->find();
if($order_info) throw new \Exception("订单已生成,如需重新下单请退出页面重新进入!");
if(!$classes_lib_spec_id)throw new \Exception("请选择您要预约的课时信息!");
}
//校验订单参数
//课程是否存在并上架
$classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)
->where("user_id",$user_id)
->find();
if(!$classesOrder){
throw new \Exception("课程不存在!");
}
$detail = $classesOrder->detail;
if(!$detail)throw new \Exception("课程不存在!");
//是否还有次数
if($detail['sub_num']<=0) throw new \Exception("该课程已无剩余课时!");
//不是可用状态
if($classesOrder['status']!="3") throw new \Exception("该课程单当前状态不可操作!");
//售后中
if($classesOrder['server_status']=="3") throw new \Exception("该课程单正在售后中,请勿操作!");
//判断课时信息
if($classes_lib_spec_id){
$classes_lib_spec_info = ClassesSpec::where('id',$classes_lib_spec_id)
->where('classes_lib_id',$detail["classes_lib_id"])
->find();
if(!$classes_lib_spec_info)throw new \Exception("课时信息不正确!");
//课时已下架
if($classes_lib_spec_info['status']!='1') throw new \Exception("该课时已下架,请选择其他课时!");
}
// $classes_lib_info = ClassesLib::where('id',$classesOrder["classes_lib_id"])->find();
// if(!$classes_lib_info || $classes_lib_info['status']!='1') throw new \Exception("该课程不存在或已下架!");
//用户存不存在
$user_info = User::where('id',$user_id)->find();
if(!$user_info) throw new \Exception("用户不存在!");
return true;
}
//计算订单所需返回数据接口
public static function getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param=[],$other_params=[],$check = false){
//校验订单参数
//课程是否存在并上架
$classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)
->where("user_id",$user_id)
->find();
$detail = $classesOrder->detail;
$classes_lib_info = $detail;
$classes_lib_spec_info = null;
//判断课时信息
if($classes_lib_spec_id){
$classes_lib_spec_info = ClassesSpec::where('id',$classes_lib_spec_id)
->where('classes_lib_id',$detail["classes_lib_id"])
->find();
if($classes_lib_spec_info){
$classes_lib_spec_info = $classes_lib_spec_info->toArray();
}
}
//用户
$user_info = User::get($user_id);
$user_data = [
"nickname"=>$user_info["nickname"],
"realname"=>$user_info["realname"],
"avatar"=>$user_info["avatar"],
"mobile"=>$user_info["mobile"],
"money" =>$user_info["money"],
"score" =>$user_info["score"],
];
//组装订单下单数据
$order_data = [];
$order_data["user_id"] = $user_id;
$order_data["classes_order_id"] = $classes_order_id;
$order_data["classes_lib_spec_id"] = $classes_lib_spec_id;
$order_data["classes_order_detail_id"] = $detail["id"];
$order_data["classes_lib_id"] = $detail["classes_lib_id"];
$order_data["status"] = '-1';
$order_data["verification_user_id"] = 0;
$order_data["reservation_time"] = time();
$order_data["type"] = '1';
$order_data["reason"] = '';
$order_data["auth_status"] = '0';
return compact('order_data','classes_lib_info','user_data','classes_lib_spec_info');
}
/**
* 根据缓存创建订单
*/
public function cacheCreateOrder($order_no, $user_id,$remark="", $trans = false)
{
//得到缓存
$orderInfo = self::getOrderCache($user_id, $order_no); //得到下单信息
if (!$orderInfo) throw new \Exception('請您完善預約信息!');
if ($trans) {
self::beginTrans();
}
try {
//1订单执行创建
$this->createOrder($user_id,$orderInfo['classes_order_id'],$orderInfo['classes_lib_spec_id'],$order_no,$orderInfo['param'],$remark);
//5删除缓存
self::deleteOrderCache($user_id, $order_no);
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return self::showInfo($order_no);
}
/**得到可核销的订单
* @param $order_no
* @return array|false|\PDOStatement|string|Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getNoVerificationOrder($order_no){
$order = self::where('order_no|id',$order_no)->where("status","in",['0'])->find();
if(!$order)throw new \Exception("待核销订单不存在");
return $order;
}
/**得到可更新课时的订单
* @param $order_no
* @return array|false|\PDOStatement|string|Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getHaveUpdateOrder($order_no){
$order = self::where('order_no|id',$order_no)->where("status","in",['0','-1'])->find();
if(!$order)throw new \Exception("可更新课时订单不存在");
return $order;
}
//生成或更新课时
public static function buildLibSpec($order,$classes_lib_spec){
if(is_string($order)||is_numeric($order))$order = self::getHaveUpdateOrder($order);
if(is_string($classes_lib_spec)||is_numeric($classes_lib_spec))$classes_lib_spec = ClassesSpec::where('id',$classes_lib_spec)->where('classes_lib_id',$order["classes_lib_id"])->find();
if(!$classes_lib_spec)throw new \Exception("课时信息不正确!");
$classes_lib_spec_data = $classes_lib_spec->toArray();
$classes_lib_spec_data['classes_lib_spec_id'] = $classes_lib_spec_data['id'];
unset($classes_lib_spec_data['id']);
unset($classes_lib_spec_data['createtime']);
unset($classes_lib_spec_data['updatetime']);
unset($classes_lib_spec_data['deletetime']);
$order_detail_data = $order->toArray();
$order_detail_data = array_merge($order_detail_data,$classes_lib_spec_data);
$order->allowField(true)->save($order_detail_data);
return $order;
}
public function createOrder($user_id,$classes_order_id,$classes_lib_spec_id,$order_no,$param,$remark='',$other_params=[]){
$this->orderVaild($user_id,$classes_order_id, $order_no, $classes_lib_spec_id, $param,true);
//订单支付信息
$order_info = self::getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param,$other_params,true);
//组装订单数据
$order_data = $order_info['order_data'];
$order_data["order_no"] = $order_no;
//课时数据
$classes_lib_spec_info = $order_info['classes_lib_spec_info'];
$res1 = self::create($order_data);
if (!$res1) throw new \Exception('创建订单失败');
//课时规格更新
$order = self::buildLibSpec($res1,$classes_lib_spec_id);
//扣减课程数
//记录订单日志
OrderLog::log($res1['id'],"课时预约下单成功,等待机构老师审核",'user',$user_id);
//7事件
$data = ['order' => $res1];
\think\Hook::listen('classeshour_order_create_after', $data);
return $res1;
}
}