15090180611 a9a4ebe154 退款流程: 后台最终处理挂起订单流程,
售后单超时自动挂起
售后同意结算单收益释放(余留未退金额情况下
后台帮商户售后功能
后台帮用户取消和申请售后功能
后台用户维度查看提现,结算,订单记录
结算单,活动单,活动,提现记录增加 万以上数据导出excel
2025-04-16 18:02:31 +08:00

1441 lines
47 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\model\school\activity;
use app\common\library\Virtual;
use app\common\model\BaseModel;
use app\common\model\school\activity\order\Order;
use app\common\model\school\activity\order\OrderCode;
use app\common\model\school\classes\Collect;
use app\common\model\User;
use think\Model;
use traits\model\SoftDelete;
class Activity extends BaseModel
{
use SoftDelete;
// 表名
protected $name = 'school_activity';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = 'deletetime';
// 追加属性
protected $append = [
'start_time_text',
'end_time_text',
'sign_start_time_text',
'sign_end_time_text',
'status_text',
'cancel_type_text',
'recommend_text',
'hot_text',
'new_text',
'add_type_text',
'feel_text',
'auth_status_text',
'auth_time_text',
'canceltime_text'
];
public function getImagesAttr($value, $data)
{
$imagesArray = [];
if (!empty($value)) {
$imagesArray = explode(',', $value);
foreach ($imagesArray as &$v) {
$v = cdnurl($v, true);
}
return $imagesArray;
}
return $imagesArray;
}
public function setImagesAttr($value, $data)
{
$imagesArray = $value;
if (!empty($value) && is_array($value)) {
//转成逗号拼接字符串
$imagesArray = implode(',', $value);
}
return $imagesArray;
}
public function getDistanceTextAttr($value, $data) {
$distance_text = '';
$distance = $data['distance'] ?? 0;
switch (true) {
case $distance >= 1000;
$distance_text = round(($distance / 1000), 2) . 'km';
break;
default :
$distance_text = $distance . 'm';
break;
}
return $distance_text;
}
protected static function init()
{
self::afterInsert(function ($row) {
if (empty($row['weigh'])) {
$pk = $row->getPk();
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
}
});
}
public function getStatusList()
{
return ['1' => __('Status 1'), '2' => __('Status 2'), '3' => __('Status 3'), '4' => __('Status 4'), '5' => __('Status 5'), '-1' => __('Status -1')];
}
public function getCancelTypeList()
{
return ['1' => __('Cancel_type 1'), '2' => __('Cancel_type 2')];
}
public function getRecommendList()
{
return ['0' => __('Recommend 0'), '1' => __('Recommend 1')];
}
public function getHotList()
{
return ['0' => __('Hot 0'), '1' => __('Hot 1')];
}
public function getNewList()
{
return ['0' => __('New 0'), '1' => __('New 1')];
}
public function getAddTypeList()
{
return ['1' => __('Add_type 1'), '2' => __('Add_type 2')];
}
public function getFeelList()
{
return ['0' => __('Feel 0'), '1' => __('Feel 1')];
}
public function getAuthStatusList()
{
return ['0' => __('Auth_status 0'), '1' => __('Auth_status 1'), '2' => __('Auth_status 2')];
}
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 getSignStartTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['sign_start_time']) ? $data['sign_start_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getSignEndTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['sign_end_time']) ? $data['sign_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 getCancelTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['cancel_type']) ? $data['cancel_type'] : '');
$list = $this->getCancelTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getRecommendTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['recommend']) ? $data['recommend'] : '');
$list = $this->getRecommendList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getHotTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['hot']) ? $data['hot'] : '');
$list = $this->getHotList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getNewTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['new']) ? $data['new'] : '');
$list = $this->getNewList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAddTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['add_type']) ? $data['add_type'] : '');
$list = $this->getAddTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getFeelTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['feel']) ? $data['feel'] : '');
$list = $this->getFeelList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAuthStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['auth_status']) ? $data['auth_status'] : '');
$list = $this->getAuthStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAuthTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['auth_time']) ? $data['auth_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getCanceltimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['canceltime']) ? $data['canceltime'] : '');
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 setSignStartTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setSignEndTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
protected function setAuthTimeAttr($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 user()
{
return $this->belongsTo('app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function admin()
{
return $this->belongsTo('app\admin\model\Admin', 'admin_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public static function activitySale($activity_id,$add_num=0)
{
return Order::where("activity_id",$activity_id)->where("status","not in",["-3","5","6"])->sum("num") + $add_num;
}
/** 更新或新增后判断
* @param $classes_activity_id
* @return void
*/
public function update_classes($classes_activity_id){
$this->updateStatus($classes_activity_id);
}
/** 更新或新增前判断
* @param $classes_activity_id
* @return void
*/
public function update_check(&$params,$row=null){
if($row){
//统一时间格式成时间戳
if( is_string($row["start_time"]))$row["start_time"]=strtotime($row["start_time"]);
if( is_string($row["end_time"]))$row["end_time"]=strtotime($row["end_time"]);
if( is_string($row["sign_start_time"]))$row["sign_start_time"]=strtotime($row["sign_start_time"]);
if( is_string($row["sign_end_time"]))$row["sign_end_time"]=strtotime($row["sign_end_time"]);
}
//开始和结束时间不能为空
$time = $params["time"];
if(empty($time))throw new \Exception("{$params["title"]}请选择开始和结束时间".$time);
$split_line = " - ";
$time_arr = explode($split_line,$time);
$params["start_time"] = $time_arr[0] ;
$params["end_time"] = $time_arr[1];
unset($params["time"]);
$start_time = $params["start_time"];
$end_time = $params["end_time"];
if(empty($start_time) || empty($end_time)){
throw new \Exception("{$params["title"]}请选择开始和结束时间".$time);
}
//转化时间戳
$start_time = $params["start_time"] && !is_numeric($params["start_time"]) ? strtotime($params["start_time"]) : $params["start_time"];
$end_time = $params["end_time"] && !is_numeric($params["end_time"]) ? strtotime($params["end_time"]) : $params["end_time"];
//结束时间不能小于开始时间
if($end_time<=$start_time){
throw new \Exception("{$params["title"]}结束时间不能小于开始时间");
}
//开始和结束时间不能为空
$time = $params["sign_time"];
if(empty($time))throw new \Exception("{$params["title"]}请选择报名开始和结束时间".$time);
$split_line = " - ";
$time_arr = explode($split_line,$time);
$params["sign_start_time"] = $time_arr[0] ;
$params["sign_end_time"] = $time_arr[1];
unset($params["sign_time"]);
$sign_start_time = $params["sign_start_time"];
$sign_end_time = $params["sign_end_time"];
if(empty($sign_start_time) || empty($sign_end_time)){
throw new \Exception("{$params["title"]}请选择报名开始和结束时间".$time);
}
//转化时间戳
$sign_start_time = $params["sign_start_time"] && !is_numeric($params["sign_start_time"]) ? strtotime($params["sign_start_time"]) : $params["sign_start_time"];
$sign_end_time = $params["sign_end_time"] && !is_numeric($params["sign_end_time"]) ? strtotime($params["sign_end_time"]) : $params["sign_end_time"];
//结束时间不能小于开始时间
if($sign_end_time<=$sign_start_time){
throw new \Exception("{$params["title"]}报名结束时间不能小于开始时间");
}
//两个时间区间段之间不能有任何交集 $start_time $end_time $sign_start_time $sign_end_time
//直接判断两个时间段之间是否有交集分几种情况1.两个时间段有交集 2.两个时间段没有交集 3.第一个时间段在第二个时间段内 4.第二个时间段在第一个时间段内 只有情况2合理
if(($start_time<=$sign_start_time && $sign_start_time<=$end_time) ||
($start_time<=$sign_end_time && $sign_end_time<=$end_time) ||
($sign_start_time<=$start_time && $end_time<=$sign_end_time) ||
($sign_start_time>=$start_time && $sign_end_time<=$end_time)){
throw new \Exception("{$params["title"]}报名时间段和开始时间段有交叉请修改");
}
//报名时间必须早于开始时间
if($sign_start_time>$start_time){
throw new \Exception("{$params["title"]}报名时间必须早于开始时间");
}
//新增时,报名时间需晚于当前时间
$now_time = time();
if(!$row && $now_time>$sign_start_time){
throw new \Exception("{$params["title"]}报名时间必须是未来时间!");
}
//活动开始和结束时间不能跨天
if(date('Y-m-d',$start_time)!=date('Y-m-d',$end_time)){
throw new \Exception("{$params["title"]}活动开始和结束时间不能跨天");
}
//settlement_time 最后结算时间等于活动结束时间往后延长n秒n取配置
$activity_end_settle = config("site.activity_end_settle") ?:0;
$params["settlement_time"] = $end_time + $activity_end_settle;
$rule = [
'user_id'=>'require',
'title'=>'require',
'images'=>'require',
// 'headimage' => 'require',
'address' => 'require',
'address_detail' => 'require',
'longitude' => 'require',
'latitude' => 'require',
// 'province' => 'require',
// 'city' => 'require',
// 'district' => 'require',
// 'address_city' => 'require',
// 'type' => 'require',
'stock' => 'require',
// 'address_type' => 'require',
'content' => 'require',
'cate_ids' => 'require',
'price' => 'require',
'start_time' => 'require',
'end_time' => 'require',
'sign_start_time' => 'require',
'sign_end_time' => 'require',
// 'refund_id' => 'require',
];
$rule_msg = [
"user_id.require"=>'发布用户必填',
"title.require"=>'标题必填',
"images.require"=>'轮播图必填',
// "headimage.require"=>'课程头图必填',
'address.require' => '地址必填',
'address_detail.require' => '详细地址必填',
'longitude.require' => '经度必填',
'latitude.require' => '纬度必填',
// 'province.require' => '省编号必填',
// 'city.require' => '市编号必填',
// 'district.require' => '县区编号必填',
//
// 'address_city.require' => '城市选择必填',
// 'type.require' => '地点类型必填',
'stock.require'=> '活动限制人数必填',
// 'address_type.require'=> '地址类型必填',
'content.require'=> '课程详情必填',
'cate_ids.require'=> '平台分类必填',
'price.require'=> '售价必填',
'start_time.require' => '活动开始时间必填',
'end_time.require' => '活动结束时间必填',
'sign_start_time.require' => '报名开始时间必填',
'sign_end_time.require' => '报名结束时间必填',
// 'refund_id.require' => '退款策略必填',
];
self::check($params,$rule,$rule_msg);
if($params["price"]>0){
if(empty($params["refund_id"])) throw new \Exception("退款策略必填");
$refund_id = $params["refund_id"];
$refund = Refund::where("id",$refund_id) ->find();
if(!$refund){
throw new \Exception("退款策略不存在");
}
$paid_activity_min_price = config("site.paid_activity_min_price");
if($params["price"]<$paid_activity_min_price){
throw new \Exception("活动售价不能低于".$paid_activity_min_price."");
}
}
if($params["price"]<0)$params["price"]=0;
$user_id = $params["user_id"];
$user = User::where("id",$user_id)->find();
if(!$user){
throw new \Exception("发布用户不存在");
}
if($row){
//修改
$title = self::where("id","<>",$row["id"])->where("status","not in","-1,5")->where("title",$params["title"])->find();
if($title) throw new \Exception("活动名不允许重复");
}else{
//新增
//不在已结束和已取消的活动名title不允许重复
$title = self::where("status","not in","-1,5")->where("title",$params["title"])->find();
if($title) throw new \Exception("活动名不允许重复");
}
//如果价格为零,记录免费状态
if($params["price"]==0){
$params["feel"] = '1';
}else{
$params["feel"] = '0';
//得到当前的微信手续费百分比
$activity_withdrawal_scale = config("site.activity_withdrawal_scale");
$activity_withdrawal_scale_100 = bcmul($activity_withdrawal_scale,100,2);
//当前售价对应手续费不得低于0.01
//计算当前售价手续费
$fee = bcmul($params["price"],$activity_withdrawal_scale,3);
if($fee<0.01){
throw new \Exception("当前售价手续费{$fee}{$activity_withdrawal_scale_100}%低于0.01,请提高售价或设为免费!");
}
}
$now_time = time();
//根据时间区间设定录入的活动初始状态1=未开始,2=报名中,3=待开始,4=进行中,5=已结束
//时间在报名开始时间之前为1=未开始
//时间在报名区间之内为2=报名中
//时间在开始时间之前在报名结束时间之后为3=待开始
//时间在开始时间之后在结束时间之前为4=进行中
//时间在结束时间之后为5=已结束
//已取消则不更新状态
if(!$row || $row["status"]!='-1'){
if($now_time<$sign_start_time){
$params["status"] = '1';
} else if($now_time>=$sign_start_time && $now_time<=$sign_end_time){
$params["status"] = '2';
} else if($now_time>$sign_end_time && $now_time<$start_time){
$params["status"] = '3';
} else if($now_time>=$start_time && $now_time<=$end_time){
$params["status"] = '4';
} else if($now_time>$end_time){
$params["status"] = '5';
}
}
if(isset($params["auth_status"])){
if(!in_array($params["auth_status"],[1,2])) throw new \Exception("{$params["title"]}请填写审核结果");
$params["auth_time"] = time();
if($params["auth_status"] == 2 && empty($params["reason"])) throw new \Exception("{$params["title"]}请填写审核失败原因");
//后台新增: 新增审核失败,状态则为已取消
if($params["auth_status"] == 2){
// $params["status"] = '-1';
// $params["cancel_type"] = '1';
if(!$row){
//新增审核
}else{
//编辑审核
if($row["auth_status"] != 0 && $row["auth_status"] != $params["auth_status"]){
throw new \Exception("{$params["title"]}您已审核不允许修改审核结果");
}
}
}
$auth = \app\admin\library\Auth::instance();
//审核id为后台登录id
$params["admin_id"] = $auth->id;
}else{
//前台提交
// $params["auth_status"] = 0;
}
//判断新增身份
if(!$row){
if(isset($params["auth_status"])){
//总后台
$params["add_type"] = '2';
$params["add_id"] = $params["admin_id"];
}else{
//用户
$params["add_type"] = '1';
$params["add_id"] = $params["user_id"];
}
}
if(!isset($params["auth_status"]) &&$row){
//用户端不允许修改
throw new \Exception("{$params["title"]}审核通过的活动只允许手动关闭,不允许修改!");
}
if(!isset($params["auth_status"])){
//前台提交
$params["auth_status"] = 0;
}
$params["fee_scale"] = config("site.activity_withdrawal_scale");
}
/** 删除前判断
* @param $id
* @param $params
* @param $row
* @return void
*/
public function updateCheck($id,$params=[],$row=null){
}
/**
* 获取所有活动列表
*/
public static function getVaildList($params) {
extract($params);
$a = (new self)->getWithAlisaName().'.';
$with = ['user'];
// if (isset($has_shop) && $has_shop) {
// $with[] = 'shop';
// }
$cate_list = Cate::where("status",'1')->column("name","id");
// $label_list = Label::where("status",'1')->column("name","id");
// $type_list = Type::where("status",'1')->column("name","id");
$selfetch = self::with($with);
$order = $order?? 'normal';
$per_page = $limit ?? 10;
$field = "{$a}start_time,{$a}end_time,{$a}sign_start_time,{$a}sign_end_time,{$a}id,{$a}user_id,{$a}title,{$a}images,{$a}province,{$a}city,{$a}district,{$a}address,{$a}address_detail,{$a}longitude,{$a}latitude,{$a}sale,{$a}stock,{$a}price,{$a}status,{$a}weigh,{$a}recommend,{$a}hot,{$a}new,{$a}cancel_type,{$a}createtime,{$a}feel,{$a}sign_num,{$a}verification_num,{$a}views,{$a}auth_status,{$a}reason,{$a}auth_time";
//得到距离
if (isset($latitude) && isset($longitude) && $latitude && $longitude) {
$field .= ', '.getDistanceBuilder($latitude, $longitude,$a);
}else{
$field .= ', 0 as distance';
}
//得到每个
$selfetch = $selfetch->field($field);
if (isset($keywords) && $keywords) {
$selfetch = $selfetch->where("{$a}title|{$a}address|{$a}address_detail|{$a}address_city", 'like', '%' . $keywords . '%');
}
if(isset($start_time) && isset($end_time) && ($end_time || $start_time)) {
if($start_time){
$selfetch = $selfetch->where("{$a}start_time", '>=', $start_time);
}
if($end_time){
$selfetch = $selfetch->where("{$a}end_time", '<=', $end_time);
}
}
if(isset($sign_start_time) && isset($sign_end_time) && ($sign_end_time || $sign_start_time)) {
if($sign_start_time){
$selfetch = $selfetch->where("{$a}sign_start_time", '>=', $sign_start_time);
}
if($sign_end_time){
$selfetch = $selfetch->where("{$a}sign_end_time", '<=', $sign_end_time);
}
}
// is_expire 是否查过期1只查过期,2只查不过期,0全查
if(isset($is_expire) && $is_expire) {
if($is_expire == 1){
$selfetch = $selfetch->where("{$a}end_time", '<', time());
}else{
$selfetch = $selfetch->where("{$a}end_time", '>=', time());
}
}
// if (isset($manystore_id) && $manystore_id) {
// $selfetch = $selfetch->where("{$a}manystore_id", 'in', ''.$manystore_id);
// }
//
// if (isset($shop_id) && $shop_id) {
// $selfetch = $selfetch->where("{$a}shop_id", 'in', ''.$shop_id);
// }
if (isset($user_id) && $user_id) {
$selfetch = $selfetch->where("{$a}user_id", 'in', ''.$user_id);
}
if (isset($my) && $my && isset($my_user_id) && $my_user_id) {
$selfetch = $selfetch->where("{$a}user_id", 'in', ''.$my_user_id);
}
if($my ==1 && empty($my_user_id)){
$selfetch = $selfetch->where("{$a}user_id", 'in', [-3]);
}
// if (isset($teacher_id) && $teacher_id) {
// $selfetch = $selfetch->where("{$a}teacher_id", 'in', ''.$teacher_id);
// }
// if (isset($type) && $type) {
// $selfetch = $selfetch->where("{$a}type", 'in', ''.$type);
// }
// if (isset($address_type) && $address_type) {
// $selfetch = $selfetch->where("{$a}address_type", 'in', ''.$address_type);
// }
if (isset($recommend) && $recommend) {
$selfetch = $selfetch->where("{$a}recommend", 'in', ''.$recommend);
}
if (isset($hot) && $hot) {
$selfetch = $selfetch->where("{$a}hot", 'in', ''.$hot);
}
if (isset($new) && $new) {
$selfetch = $selfetch->where("{$a}new", 'in', ''.$new);
}
if (isset($feel) && $feel) {
$selfetch = $selfetch->where("{$a}feel", 'in', ''.$feel);
}
// //设置订单信息
if(isset($auth_status) && $auth_status !=='' && $auth_status !==null){
$selfetch = $selfetch->where("{$a}auth_status", 'in', ''.$auth_status);
}
//设置订单信息
if(isset($status) && $status !=='' && $status !==null){
$selfetch = $selfetch->where("{$a}status", 'in', ''.$status);
}
//区域搜索
if (isset($province) && $province) {
$selfetch = $selfetch->where("{$a}province", 'in', ''.$province);
}
if (isset($city) && $city) {
$selfetch = $selfetch->where("{$a}city", 'in', ''.$city);
}
if (isset($district) && $district) {
$selfetch = $selfetch->where("{$a}district", 'in', ''.$district);
}
// if (isset($self_label_tag) && $self_label_tag) {
// $self_label_tag = implode("|",explode(',',$self_label_tag));
// $selfetch = $selfetch->whereRaw(" {$a}self_label_tag REGEXP '({$self_label_tag})'");
// }
//
// if (isset($classes_type) && $classes_type) {
// $classes_type = implode("|",explode(',',$classes_type));
// $selfetch = $selfetch->whereRaw(" {$a}classes_type REGEXP '({$classes_type})'");
// }
if (isset($cate_ids) && $cate_ids) {
$cate_ids = implode("|",explode(',',$cate_ids));
$selfetch = $selfetch->whereRaw(" {$a}cate_ids REGEXP '({$cate_ids})'");
}
//
// if (isset($classes_label_ids) && $classes_label_ids) {
// $classes_label_ids = implode("|",explode(',',$classes_label_ids));
// $selfetch = $selfetch->whereRaw(" {$a}classes_label_ids REGEXP '({$classes_label_ids})'");
// }
$collect_classes_lib_ids = [-1];
//需登录查询条件:
if(isset($my_user_id) && $my_user_id){
//得到我收藏的课程ids
$collect_classes_lib_ids = Collect::where("user_id",$my_user_id)->column("classes_activity_id");
//专查我的收藏
if(isset($collect) && $collect){
$selfetch = $selfetch->where("{$a}id","in",$collect_classes_lib_ids);
}
}
if(isset($order) && $order == "distance"){
$selfetch = $selfetch->where("{$a}longitude","not null")
->where("{$a}latitude","not null")
->where("{$a}longitude","<>","")
->where("{$a}latitude","<>","")
->where("{$a}longitude","<>","null")
->where("{$a}latitude","<>","null");
}
//排序
switch ($order) {
case "normal": //综合排序(推薦優先)
$selfetch = $selfetch->order("{$a}recommend desc,{$a}hot desc,{$a}new desc,{$a}weigh desc,{$a}start_time desc,{$a}id desc");
break;
case "distance": //距离优先 权重
$selfetch = $selfetch->order("distance asc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "hot": //熱門优先
$selfetch = $selfetch->order("{$a}hot desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "new": //平台最新优先
$selfetch = $selfetch->order("{$a}new desc,{$a}id desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "recommend": //推薦优先
$selfetch = $selfetch->order("{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "sale": //銷量优先
$selfetch = $selfetch->order("{$a}sale desc,{$a}verification_num desc,{$a}sign_num desc,{$a}recommend desc,{$a}weigh desc");
break;
case "views": //浏览量优先
$selfetch = $selfetch->order("{$a}views desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc");
break;
case "collect": //收藏量优先
$selfetch = $selfetch->order("{$a}collect desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc");
break;
default:
throw new \Exception("不支持的排序类型");
}
if(isset($nearby) && $nearby) {
// throw new \Exception("现版本不支持");
$selfetch = $selfetch->having("distance <= {$nearby}");
}
$selfetch = $selfetch->page($page,$limit)->select();
foreach ($selfetch as $row) {
// $row->getRelation('manystore')->visible(['nickname']);
$row->getRelation('user')->visible(['nickname','avatar']);
}
$rows = $selfetch;
// $total = $selfetch->total();
//额外附加数据
foreach ($rows as &$row) { //迭代器魔术方法遍历,填值自动引用传值
//设置是否已收藏
$row->is_collect = in_array($row->id,$collect_classes_lib_ids) ? 1 : 0;
if($row->is_collect){
$row["collect"] = Collect::where("user_id",$my_user_id)->where("classes_activity_id",$row->id)->find();
}
$classes_cate_ids = $row['cate_ids'];
$classes_cate = [];
foreach (explode(",", $classes_cate_ids) as $classes_cate_id){
if(isset($cate_list[$classes_cate_id]))$classes_cate[] = $cate_list[$classes_cate_id];
}
$row['classes_cate'] = $classes_cate;
$row['join_info'] = self::getJoininfo( $row["id"],$row["stock"],10);
}
$result = array("data" => $rows);
return $result;
}
/** 课程详情
* @param $id
* @throws \think\exception\DbException
*/
public function detail($id,$user_id=0,$oper_type='user',$trans=false){
//更新课程状态
$this->updateStatus($id);
$self = $this->get($id,['user']);
//只查user的名字
// $self->getRelation('user')->visible(['nickname']);
//是否收藏
$self['is_collect'] = 0;
//是否购买
$self['have_buy'] = 0;
if($user_id){
//判断是否收藏
$self['is_collect'] = Collect::where("user_id",$user_id)->where("classes_activity_id",$id)->count() ? 1:0 ;
//判断用户是否已报名
$self['have_buy'] = Order::where("activity_id",$id)
->where("user_id",$user_id)
->where("status","not in",["-3","6","9"])
->count() ? 1 : 0 ;
}
//
$this->setViews($id,$user_id,$oper_type,$user_id,$trans);
$self->getRelation('user')->visible(['nickname','realname','mobile','avatar']);
//参与人数 = 虚拟人数 + 平台人数
$cate_list = Cate::where("status",'1')->column("name","id");
$classes_cate_ids = $self['cate_ids'];
$classes_cate = [];
foreach (explode(",", $classes_cate_ids) as $classes_cate_id){
if(isset($cate_list[$classes_cate_id]))$classes_cate[] = $cate_list[$classes_cate_id];
}
$self['classes_cate'] = $classes_cate;
$self['sign_time'] = "{$self["sign_start_time_text"]} - {$self["sign_end_time_text"]}";
$self['time'] = "{$self["start_time_text"]} - {$self["end_time_text"]}";
$self['join_info'] = self::getJoininfo($id,$self["stock"],10);
//退款政策
$self['refund_info'] = Refund::where("id",$self["refund_id"])->find();
return $self;
}
/**设置浏览量
* @param $id
* @param int $user_id
* @param bool $check
* @param bool $trans
* @throws \Exception
*/
public function setViews($id,$user_id,$oper_type='user',$oper_id=0,$trans=false){
$classes_lib = self::where("id",$id)->find();
if(!$classes_lib)throw new \Exception("找不到活动!");
//判断逻辑
if($trans){
self::beginTrans();
}
try{
//事务逻辑
$classes_lib->views = $classes_lib->views + 1;
//查询是否已收藏
$classes_lib->save();
//调用事件
$data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id];
\think\Hook::listen('new_activity_view_after', $data);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $classes_lib;
}
/**设置收藏
* @param $id
* @param int $user_id
* @param int $collect 0取消收藏 1收藏
* @param bool $check
* @param bool $trans
* @throws \Exception
*/
public function collect($id,$user_id,$collect,$oper_type='user',$oper_id=0,$trans=false){
$classes_lib = self::where("id",$id)->find();
if(!$classes_lib)throw new \Exception("找不到活动!");
//判断逻辑
if($trans){
self::beginTrans();
}
try{
//事务逻辑
$where = [
"user_id"=>$user_id,
"classes_activity_id"=>$id,
// "weigh"=>$classes_lib["weigh"],
];
//查询是否已收藏
$res1 = Collect::where($where)->find();
if($collect){
if(!$res1){
$where["weigh"] = $classes_lib["weigh"];
//未收藏,添加收藏
$res1 = new Collect();
$res1->allowField(true)->save($where);
}
self::update_classes($classes_lib["id"]);
//调用事件
$data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id];
\think\Hook::listen('new_activity_collect_success_after', $data);
}else{
unset($where["weigh"]);
//取消收藏
$res1 = Collect::where($where)->delete();
self::update_classes($classes_lib["id"]);
//调用事件
$data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id];
\think\Hook::listen('new_activity_collect_cancel_after', $data);
}
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
$where["is_collect"] = $collect;
return $where;
}
//更新活动状态
public function updateStatus($id,$trans=false){
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
$row = self::get($id);
if(!$row)return false;
$now_time = time();
$sign_start_time = $row["sign_start_time"];
$sign_end_time = $row["sign_end_time"];
$start_time = $row["start_time"];
$end_time = $row["end_time"];
//根据时间区间设定录入的活动初始状态1=未开始,2=报名中,3=待开始,4=进行中,5=已结束
//时间在报名开始时间之前为1=未开始
//时间在报名区间之内为2=报名中
//时间在开始时间之前在报名结束时间之后为3=待开始
//时间在开始时间之后在结束时间之前为4=进行中
//时间在结束时间之后为5=已结束
//已取消则不更新状态
$params = [];
if(!$row || $row["status"]!='-1'){
if($now_time<$sign_start_time){
$params["status"] = '1';
} else if($now_time>=$sign_start_time && $now_time<=$sign_end_time){
$params["status"] = '2';
} else if($now_time>$sign_end_time && $now_time<$start_time){
$params["status"] = '3';
} else if($now_time>=$start_time && $now_time<=$end_time){
$params["status"] = '4';
} else if($now_time>$end_time){
$params["status"] = '5';
}
}
//更新销量
$params["sale"] = self::activitySale($id);
//统计课程总报名和总核销
$params["sign_num"] = Order::where("activity_id",$id)->where("status","not in",["-3","5","6"])->sum("num");
$params["verification_num"] = OrderCode::where("activity_id",$id)->where("status","=","6")->count();
//设置课程收藏
$params["collect"] = Collect::where("classes_activity_id",$id)->count();
if($params){
$res = $row->allowField(true)->save($params);
}
//如果活动状态是已结束,则完成所有未核销或者未核销完的订单
//if(in_array($order["status"],["2",'3']) && (in_array($order["server_status"],['0'])) && !$order['finishtime']){
if($row["status"]=='5'){
$order_list = Order::where("status" ,"in",["2","3"])->where(["activity_id"=>$id,"server_status"=>"0"])->select();
foreach ($order_list as $order){
//执行订单完成
Order::updateFinish($order->order_no);
}
}
//将课程信息和课时信息同步到所有已下单的订单信息中
self::orderInfoSync($id);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $row;
}
public static function orderInfoSync($classes_lib_id){
$classes_lib = self::get($classes_lib_id);
if($classes_lib){
//查询所有课程订单更新课程单信息
$order = \app\common\model\school\activity\order\OrderDetail::where("activity_id",$classes_lib_id)->select();
foreach ($order as $row){
$update = $classes_lib->toArray();
$update_data = $row->checkAssemblyParameters($update,["id","price","status","createtime","updatetime"]);
$row->save($update_data);
}
// \app\common\model\school\activity\order\Order::where("activity_id",$classes_lib_id)->update(["fee_scale"=>$classes_lib["fee_scale"]]);
}
}
/** 新增活动
* @param $params
* @param $trans
* @return $this
* @throws \Exception
*/
public function add($params,$user_id,$oper_type='user',$oper_id=0,$trans=false){
if (empty($params)) {
throw new \Exception(__('Parameter %s can not be empty', ''));
}
if($user_id)$params["user_id"] = $user_id;
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
// //是否采用模型验证
// if ($this->modelValidate) {
// $name = str_replace("\\model\\", "\\validate\\", get_class($this));
// $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
// $this->validateFailException()->validate($validate);
// }
$row = new self;
$this->update_check($params,null);
$result = $row->allowField(true)->save($params);
$this->update_classes($row["id"]);
$row->reason = "";
//调用审核事件触发
$data = ['activity' => $row,"user_id"=>$params["user_id"],"oper_type"=>$oper_type,"oper_id"=>$oper_id];
\think\Hook::listen('new_activity_auth_need_after', $data);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $row;
}
/**
* 超时检测
*/
public static function timeoutCheck($trans = false){
$count = 0;
//得到所有过期的队列
$list = self::where("status",'not in',['-1'])->select();
if ($trans) {
self::beginTrans();
}
try {
foreach ($list as $activity)
{
//更新课程状态
(new self)->updateStatus($activity["id"]);
$count++;
}
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $count;
}
/*** 下单详情
* @param $id
* @param $limit
* @return void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getJoininfo($id,$stock,$limit=10)
{
$users = [];
//人数
$people_number = Order::where("activity_id",$id)->where("status","in",[2,3,4,9])->order("id","desc")->sum("num");
//查询已支付用户列表取前10 -3=已取消,0=待支付,2=已报名,3=核销中,4=售后中,5=退款结算中,6=已退款,9=已完成
$user_ids = Order::where("activity_id",$id)->where("status","in",[2,3,4,9])->order("id","desc")->limit($limit)->column("user_id");
if($user_ids){
$users = User::where("id","in",$user_ids)->field("id,nickname,avatar")->select();
}
//百分比:人数$people_number 除以 库存$stock * 100 百分比取整,需判断掉除零异常
$percent = 0;
try{
$percent = intval(($people_number/$stock)*100);
}catch (\Exception $e){
$percent = 0;
}
return compact("users","people_number","percent","stock");
}
/** 取消活动
* @param $id
* @param $check
* @param $oper_type
* @param $oper_id
* @param $trans
* @return true
* @throws \Exception
*/
public function cancel($id,$cancel_type ="2",$check=false,$oper_type='user',$oper_id=0,$trans=false){
//判断逻辑
$row = self::where("id",$id)->where("status","in",["1","2","3","4"])->find();
if(!$row) throw new \Exception("活动已取消或已结束");
if($check) {
if($oper_type=='user' && $row["user_id"] != $oper_id) throw new \Exception("您无权取消该活动");
}
if($trans){
self::beginTrans();
}
$res = true;
try{
//更新活动状态
$row["status"] = "-1";
$row["cancel_type"] = $cancel_type;
$row["canceltime"] = time();
$row->save();
//执行取消事件
$data = ['activity' => $row,"user_id"=>$row["user_id"],"oper_type"=>$oper_type,"oper_id"=>$oper_id];
\think\Hook::listen('new_activity_cancel_success_after', $data);
//自动退款检测:如果有订单,则自动取消
$this->orderAllCancel($id);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $row;
}
public function orderAllCancel($activity_id,$trans=false){
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
//查询待支付订单,执行订单取消
$orders = Order::where("activity_id",$activity_id)->where("status","in",['0'])->select();
foreach ($orders as $order){
(new Order)->freeCancel($order['id'],0,false,'admin',0);
}
//查询所有免费订单,执行取消
$orders = Order::where("activity_id",$activity_id)->where("payprice",0)->where("status","in",['0','2','3',"9"])->select();
foreach ($orders as $order){
(new Order)->freeCancel($order['id'],0,false,'admin',0);
}
//查询所有付费订单,执行退款取消
$orders = Order::where("activity_id",$activity_id)->where("payprice",">",0)->where("status","in",["2","3","9"])->select();
foreach ($orders as $order){
(new Order)->paidCancel($order['id'],0,false,'admin',0,true);
}
//处于售后中的直接售后同意按全款退?
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $res;
}
public function getActivityAuthIds($user_id,$vaild=false)
{
if(!$vaild){
$activity_ids = self::where("user_id",$user_id)->column("id");
}else{
//只要审核通过且未结束和取消的
$activity_ids = self::where("user_id",$user_id)->where("auth_status","in",["1"])->where("status","in",["1","2","3","4"])->column("id");
}
return $activity_ids;
}
public static function getActivityInfo($user_id)
{
//我参与的活动数量
$join_num = Order::where("user_id",$user_id)->where("status","in",["2","3","9"])->count("activity_id");
//我发布的活动数量
$release_num = self::where("user_id",$user_id)->where("status","not in",["-1"])->count();
return compact("join_num","release_num");
}
public static function getPath($id){
return Virtual::getPath("activity",["activity_id"=>$id]);
}
public static function getMiniQrcodeLink($id){
return Virtual::getMiniQrcodeLink("activity",["activity_id"=>$id]);
}
}