15090180611 e9bbe382a2 用户端:付费单策略内取消自动退款
活动取消已下单自动取消并退全款流程
订单未支付自动取消定时任务
活动更新状态定时任务
活动结算单生成和结算单解冻定时任务
2025-04-11 18:17:29 +08:00

366 lines
10 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\order;
use app\common\model\BaseModel;
use app\common\model\school\activity\Activity;
use app\common\model\user\withdrawal\UserwithdrawalLog;
use think\Model;
use traits\model\SoftDelete;
class SettleLog extends BaseModel
{
use SoftDelete;
// 表名
protected $name = 'school_activity_settle_log';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = 'deletetime';
// 追加属性
protected $append = [
'status_text',
'settletime_text',
'canceltime_text',
'unfreezetime_text'
];
public function getStatusList()
{
return ['1' => __('Status 1'), '2' => __('Status 2'), '3' => __('Status 3'), '-1' => __('Status -1')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getSettletimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['settletime']) ? $data['settletime'] : '');
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;
}
public function getUnfreezetimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['unfreezetime']) ? $data['unfreezetime'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
protected function setSettletimeAttr($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);
}
protected function setUnfreezetimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function order()
{
return $this->belongsTo(Order::class, 'activity_order_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function log()
{
return $this->belongsTo(UserwithdrawalLog::class, 'withdrawal_log_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function touser()
{
return $this->belongsTo('app\common\model\User', 'to_user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function payuser()
{
return $this->belongsTo('app\common\model\User', 'pay_user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
/**
* 检测订单结算
*/
public static function timeoutSettleActivityCheck($activity_id,$trans = false){
$count = 0;
if ($trans) {
self::beginTrans();
}
try {
$orders = Order::where("payprice",">",0) //支付单
->where("pay_type",'wechat') //微信支付
->where("sub_refundprice",">",0) //剩余未退大于0
->where("activity_id",$activity_id) //当前活动
->where("status","in",["-3","9","6"])
->select();
foreach ($orders as $order){
//剩余金额大于手续费的订单,并且未插入此结算单的
$sub_refundprice = bcsub($order["sub_refundprice"],$order["fee_price"]);
if($sub_refundprice > 0){
$log = self::where("activity_order_id",$order["id"])->where("status","not in",["-1"])->find();
if(!$log){
(new self)->generatorLog($order["id"]);
}
}
}
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $count;
}
/**
* 检测订单结算
*/
public function timeoutSettleCheck($trans = false){
$count = 0;
if ($trans) {
self::beginTrans();
}
try {
//查询更新所有活动状态
Activity::timeoutCheck();
//延后时间(秒)
$delay = config("site.activity_end_settle") ?: 0;
$time = time();
//查询处于可结算状态的订单(活动结束时间戳 延后时间 =超时可以结算的活动)
$time = $time - $delay;
$activityList = Activity::where("status",'5')->where("end_time",'<',$time)->select();
foreach ($activityList as $activity){
//对活动订单进行结算记录插入
$this->timeoutSettleActivityCheck($activity["id"]);
}
//检测更新所有结算订状态
SettleLog::timeoutCheck(null,null);
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $count;
}
/** 生成结算记录
* @param $order_id
* @param $trans
* @return true
* @throws \Exception
*/
public function generatorLog($order_id,$trans=false){
$order = Order::where("id" ,$order_id)->find();
if(!$order) return false;
//免费的忽略
if($order->payprice <= 0) return false;
$detail = $order->detail;
if(!$detail) return false;
$data = [
"activity_order_id" => $order_id,
"withdrawal_log_id" =>0,
"to_user_id" => $detail->user_id,
"pay_user_id" => $order->user_id,
"status" =>'1',
"unfreezetime" => $detail->settlement_time,
"order_price" => $order->payprice,
"sub_refundprice" =>$order->sub_refundprice,
"fee_scale" => $order->fee_scale,
"fee_price" => $order->fee_price,
"settle_price" => bcsub($order->sub_refundprice,$order->fee_price,2)
];
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
$res =self::where([
"activity_order_id" => $order_id,
"status" =>'1',
"to_user_id" => $detail->user_id,
])->find();
//保存
if(!$res)$res = self::create($data);
//记录状态检测
$this->settleCheck($res["id"]);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $res;
}
/** 结算冻结状态更新
* @param $log_id
* @param $trans
* @return true
* @throws \Exception
*/
public function settleCheck($log,$trans=false){
if(is_string($log)||is_numeric($log))$log = self::where("id" ,$log)->where("status",'1')->find();
if(!$log) return false;
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
$time = time();
if($log->unfreezetime < $time){
//更新状态
$res = self::where("id" ,$log["id"])->update(["status" =>'2']);
}
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $res;
}
/**
* 超时检测
*/
public static function timeoutCheck($activity_order_id=null,$to_user_id=null,$trans = false){
$count = 0;
$model = self::where("status",'1');
if($activity_order_id)$model = $model->where("activity_order_id",$activity_order_id);
if($to_user_id)$model = $model->where("to_user_id",$to_user_id);
//得到所有过期的队列
$list = $model->select();
if ($trans) {
self::beginTrans();
}
try {
foreach ($list as $log)
{
//更新结算状态
(new self)->settleCheck($log,$trans=false);
$count++;
}
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $count;
}
/**
* 批量关闭
*/
public static function allClose($activity_order_id=null,$to_user_id=null,$trans = false){
$count = 0;
$model = self::where("status",'2');
if($activity_order_id)$model = $model->where("activity_order_id",$activity_order_id);
if($to_user_id)$model = $model->where("to_user_id",$to_user_id);
//得到所有过期的队列
$list = $model->select();
if ($trans) {
self::beginTrans();
}
try {
foreach ($list as $log)
{
$log["status"] = "-1";
$log["canceltime"] = time();
$log->save();
$count++;
}
if ($trans) {
self::commitTrans();
}
} catch (\Exception $e) {
if ($trans) {
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $count;
}
}