admin/addon/futures/model/Futures.php

511 lines
20 KiB
PHP

<?php
namespace addon\futures\model;
use addon\futures\model\Futures as FuturesModel;
use addon\message\model\Message;
use app\model\member\MemberAccount;
use app\model\system\Config as ConfigModel;
use app\model\BaseModel;
use Psr\SimpleCache\InvalidArgumentException;
use think\facade\Cache;
use think\facade\Db;
class Futures extends BaseModel
{
/**
* 获取列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @param string $alias
* @param array $join
* @return array
*/
public function getPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = 'a.*', $alias = 'a', $join = [])
{
$list = model('futures')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 详情
* @param $id
* @param $site_id
* @return array
*/
public function detail($id, $site_id)
{
$condition = [
['a.id', '=', $id],
['a.site_id', '=', $site_id]
];
// 获取内容
$field = [
'seller.username as seller_username',
'old_seller.nickname as seller_nickname',
'seller.headimg as seller_headimg',
'g.goods_name',
'g.goods_image',
'g.goods_content',
'g.market_price',
'g.unit',
'a.service_price',
'a.real_income',
'a.site_id',
'a.seller_uid',
'a.member_id',
'a.goods_id',
'a.id',
'a.total',
'a.unit_price',
'a.order_id',
'a.price',
'a.status',
'a.release_time',
'a.sell_time',
'a.created_time',
'a.take_time',
'o.order_no',
'o.buyer_message',
'seller.nickname as buyer_name'
];
// 表关联
$join = [
['member seller', 'seller.member_id = a.seller_uid', 'left'],// 获取卖家信息
['member buyer', 'buyer.member_id = a.member_id', 'left'],// 获取买家信息
['goods g', 'g.goods_id = a.goods_id', 'left'],// 获取商品信息
['order o', 'o.order_id = a.order_id', 'left'],// 获取商品信息
['futures f', 'f.id = a.old_futures_id', 'left'],// 获取旧订单信息
['member old_seller', 'old_seller.member_id = f.seller_uid', 'left'],// 获取旧卖家信息
];
$detail = model('futures')->getInfo($condition, $field, 'a', $join);
return $this->success($detail);
}
/**
* 增加库存
* @param $data
* @return array
* @throws InvalidArgumentException
*/
public function add($data)
{
$id = model('futures')->add($data);
if (!($id > 0)) {
return $this->error('', '添加失败');
}
return $this->success($id);
}
/**
* 发布
* @param $id
* @param $price
* @return array
* @throws InvalidArgumentException
*/
public function release($id, $price)
{
$date = model('futures')->getInfo([['id', '=', $id]]);
if (empty($date) || $date['status'] !== 1) {
return $this->error('', '发布失败-db');
}
model('futures')->startTrans();
try {
$basics = $this->getBasicsConfig($date['site_id'])['data']['value'];
$service_price = $date['unit_price'] * $basics['service_price'] / 100; //更改为买入价格
$technical_range = $service_price * $basics['technical_range'] / 100;
if (model('member')->getValue(['member_id' => $date['seller_uid']], 'balance_money') < $service_price) {
return error(-800, '您余额不足!');
}
//拆单
$futuresInfo = $this->detail($id, $date['site_id'])['data'];
$futuresInfo['status'] = 2;
$futuresInfo['start_price'] = $date['start_price'];
$release_time= time() + $basics['release_wait'] * 24 * 60 * 60;// 配置上线延迟时间
if(Db::name('futures_user')->where('member_id', '=',$futuresInfo['seller_uid'])->cache($futuresInfo['seller_uid'].'is_special')->value('is_special')==1){
$release_time=time();
} //排除特殊用户时间限制
if ($price >= $date['start_price'] * $futuresInfo['total']) {
$futuresInfo['total'] *= 2;
if ($futuresInfo['total'] > pow(2, $basics['order_total_double_times'])) {// 配置单订单商品最大裂变次数
//拆单
$res=$this->SplitOrder($id, $price, $futuresInfo, $basics);
if($res['code']>=0){
$futuresInfo['status'] = 8;
model('futures')->update([
'status' => $futuresInfo['status'],
'release_time' => $release_time, // 配置上线延迟时间
], [['id', '=', $id]]);
model('futures')->commit();
}
return $res;
}
}
model('futures')->update([
'status' => $futuresInfo['status'],
'release_time' => $release_time,// 配置上线延迟时间
'price' => $price,
'total' => $futuresInfo['total'],
'service_price' => $service_price,
'real_income' => $price,
], [['id', '=', $id]]);
//扣除服务费
$memberAccountModel = new MemberAccount();
$memberAccountModel->addMemberAccount($date['site_id'], $date['seller_uid'], 'balance_money', -$technical_range, 'service_price', $date['id'], '服务费', $date['id']);
$memberAccountModel->addMemberAccount($date['site_id'], $date['seller_uid'], 'balance_money', -($service_price - $technical_range), 'service_price', $date['id'], '商家分账', $date['id']);
model('futures')->commit();
return $this->success();
} catch (\Exception $e) {
model('futures')->rollback();
return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
}
}
/***
* 拆分订单
* @param $id
* @param $price
* @param $futuresInfo
* @param $basics
* @return array
* @throws InvalidArgumentException
*/
private function SplitOrder($id, $price, $futuresInfo, $basics)
{
model('futures')->startTrans();
try {
$splitOrderNum = $basics['split_order_num'];
$futuresInfo['total']/=2;
for ($i = 0; $i < $splitOrderNum; $i++) {
$tempArr=[
'site_id' => $futuresInfo['site_id'],
'seller_uid' => $futuresInfo['seller_uid'],
'member_id' => $futuresInfo['seller_uid'],
'old_futures_id' => $id,
'goods_id' => $futuresInfo['goods_id'],
'start_price' => $futuresInfo['start_price'],
'is_grow' => 1,
'total' => intval($futuresInfo['total']) / $splitOrderNum,
'unit_price' =>floatval($futuresInfo['unit_price']) / $splitOrderNum,
'status' => 1,
'order_id' => $futuresInfo['order_id'],
'created_time' => time()
];
$newSmallFuturesId = $this->add($tempArr)['data'];
$this->release($newSmallFuturesId, $price/$splitOrderNum);
}
model('futures')->commit();
return $this->success();
} catch (\Exception $e) {
model('futures')->rollback();
return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
}
}
/**
* 下架到库存
* @return array
*/
public function stock($id)
{
$date = model('futures')->getInfo([['id', '=', $id]]);
if (empty($date) || $date['status'] !== 2) {
return $this->error('', '下架失败');
}
model('futures')->update([
'status' => 1,
'release_time' => 0,
], [['id', '=', $id]]);
//扣除服务费
$memberAccountModel = new MemberAccount();
$memberAccountModel->addMemberAccount($date['site_id'], $date['seller_uid'], 'balance_money', $date['service_price'], 'service_price', $date['id'], '退回服务费与商家分账', $date['id']);
Cache::store('redis_concurrent')->delete('addon_futures_' . $id);
return $this->success();
}
/**
* 提货
* @param $id
* @return array
* @throws InvalidArgumentException
*/
public function pickUp($id)
{
$date = model('futures')->getInfo([['id', '=', $id]]);
if (empty($date) || $date['status'] !== 1) {
return $this->error($date, '提货失败');
}
$member_address = input('member_address', []);
$member_address = isset($member_address) && !empty($member_address) ? json_decode($member_address, true) : [];
if (empty($member_address)) {
return $this->error($date, '提货失败-无收获地址');
}
model('futures')->update([
'status' => 5,
], [['id', '=', $id]]);
$order_info = [
'name' => $member_address['name'] ?? '',
'mobile' => $member_address['mobile'] ?? '',
'telephone' => $member_address['telephone'] ?? '',
'province_id' => $member_address['province_id'] ?? '',
'city_id' => $member_address['city_id'] ?? '',
'district_id' => $member_address['district_id'] ?? '',
'community_id' => $member_address['community_id'] ?? '',
'address' => $member_address['address'] ?? '',
'full_address' => $member_address['full_address'] ?? '',
'longitude' => $member_address['longitude'] ?? '',
'latitude' => $member_address['latitude'] ?? '',
'promotion_type' => 'futures_tihuo',
];
model('order')->update($order_info, [['order_id', '=', $date['order_id']]]);
$basics = $this->getBasicsConfig($date['site_id'])['data']['value'];
// 提货用来减少用户买入限制
Db::name('futures_user')
->where('member_id', $date['member_id'])
->update([
'business_num' => Db::raw('business_num-' . $basics['order_restrictions_num']),
]);
return $this->success();
}
/**
* 订单创建
* @return array
*/
public function orderCreate($id, $order_id, $member_id)
{
if(Cache::store('redis_concurrent')->get('addon_futures_' . $id)){
return $this->error('', '你太慢了已被抢购');
}
$date = model('futures')->getInfo([['id', '=', $id]]);
if (empty($date) || ($date['status'] !== 2 && $date['status'] !== 7)) {
return $this->error($date, '下单失败-1001');
}
model('futures')->update(
[
'status' => 6,
'created_time' => time(),
'member_id' => $member_id,
'order_id' => $order_id,
],
[['id', '=', $id]]);
//增加用户已下单次数
Db::name('futures_user')
->where('member_id', $member_id)
->update([
'business_num' => Db::raw('business_num +1'),
'total_business_num' => Db::raw('total_business_num +1'),
]);
(new Message())->addMessage($date['site_id'], '订单创建', 1, $member_id, $id);
Cache::store('redis_concurrent')->tag('addon_futures_goods')->set('addon_futures_' . $id, '1');
return $this->success();
}
/**
* 订单完成
* @return array
*/
public function orderComplete($id, $order_id)
{
$date = model('futures')->getInfo([['id', '=', $id]]);
if (empty($date) || $date['status'] !== 6) {
return $this->error($date, '完成失败');
}
$date = model('futures')->getInfo([['id', '=', $id]]);
model('futures')->update([
'status' => 3,
'sell_time' => time()
], [['id', '=', $id]]);
$this->add(
[
'order_id' => $order_id,
'site_id' => $date['site_id'],
'seller_uid' => $date['member_id'],
'member_id' => $date['member_id'],
'old_futures_id' => $id,
'goods_id' => (int)$date['goods_id'],
'total' => (int)$date['total'],
'unit_price' => $date['price'],
'start_price' => $date['start_price'],
'status' => 1,
'created_time' => time()
]
);
(new Message())->addMessage($date['site_id'], '订单完成', 1, $date['member_id'], $id);
(new Message())->addMessage($date['site_id'], '订单售卖完成', 1, $date['seller_uid'], $id);
// 给用户增加余额
$memberAccountModel = new MemberAccount();
$memberAccountModel->addMemberAccount($date['site_id'], $date['seller_uid'], 'balance_money', $date['price'], 'sell', $date['id'], '售卖产品', $date['id']);
$futuresModel = new FuturesModel;
$basics = $futuresModel->getBasicsConfig($date['site_id'])['data']['value'];
if ($basics['give_integral'] > 0) { //首单赠送积分
if (model('futures')->getCount(['seller_uid' => $date['member_id']]) == 1) {
$memberAccountModel->addMemberAccount($date['site_id'], $date['member_id'], 'point', $basics['give_integral'], 'sell', $date['id'], '秒杀首单赠送积分', $date['id']);
}
}
$point = $date['price'] * $basics['order_give_points_ratio'] / 100;
//赠送积分
$memberAccountModel->addMemberAccount($date['site_id'], $date['member_id'], 'point', intval($point), 'sell', $date['id'], '秒杀赠送积分', $date['id']);
Cache::store('redis_concurrent')->delete('addon_futures_' . $id);
return $this->success();
}
/**
* 订单取消
* @return array
*/
public function orderClose($id)
{
$date = model('futures')->getInfo([['id', '=', $id]]);
///将未被抢购方法抢购区
// model('futures')->update(['status' => 7], [
// ['status', '=', 2],
// ['release_time', '<', time()],
// ]);
if (empty($date) || $date['status'] !== 6) {
return $this->error($date, '取消失败');
}
// if(!Cache::store('redis_concurrent')->delete('addon_futures_pay_'.$id)){
// return $this->error('','取消失败');
// }
// Cache::store('redis_concurrent')->delete('addon_futures_pay_' . $id);
model('futures')->update(['status' => 7,'member_id'=>$date['seller_uid']], [['id', '=', $id]]);
// 订单取消后 添加违规次数
Db::name('futures_user')
->where('member_id', $date['member_id'])
->update([
'violation_num' => Db::raw('violation_num+1'),
'total_violation_num' => Db::raw('total_violation_num+1'),
]);
Db::name('futures_user_violation_records')
->insert([
'site_id' => $date['site_id'],
'member_id' => $date['member_id'],
'futures_id' => $id,
'created_time' => time(),
]);
// 判断:如果当前次数已经到达限制 进行惩罚操作
$futuresUserInfo = Db::name('futures_user')
->field('violation_num,site_id,punish_time')
->where('member_id', $date['member_id'])
->find();
$basics = (new Futures())->getBasicsConfig($futuresUserInfo['site_id'])['data']['value'];
$punish_money=$basics['punish_money'];
if($punish_money){
//扣除服务费
$memberAccountModel = new MemberAccount();
$memberAccountModel->addMemberAccount($date['site_id'], $date['member_id'], 'balance_money', -$punish_money, 'service_price', $id, '服务罚金', $id);
}else{
$violationHour = $basics['violation_hour'] ?? 0;
$violationUnpaid = $basics['violation_unpaid'] ?? 0;
if ($violationUnpaid > 0 && $futuresUserInfo['violation_num'] >= $violationUnpaid) {
$startTime = $futuresUserInfo['punish_time'] > time() ? $futuresUserInfo['punish_time'] : time();
Db::name('futures_user')
->where('member_id', $date['member_id'])
->update([
'punish_time' => strtotime("+{$violationHour} hours", $startTime),// 添加惩罚时间
'violation_num' => Db::raw("violation_num - {$violationUnpaid}")// 减少违规次数
]);
}
}
Cache::store('redis_concurrent')->tag('addon_futures_goods')->clear();//删除缓存
(new Message())->addMessage($date['site_id'], '订单取消', 1, $date['member_id'], $id);
return $this->success();
}
/**
* 写入基本设置
* @param $data
* @param $is_use
* @param $site_id
* @return array
*/
public function setBasicsConfig($data, $is_use, $site_id)
{
$config = new ConfigModel();
$miaosha_start_time_arr = array_column($data['times'], 'miaosha_start_time');
array_multisort($miaosha_start_time_arr, SORT_ASC, $data['times']);
return $config->setConfig($data, '秒杀基本配置', $is_use, [['site_id', '=', $site_id], ['app_module', '=', 'shop'], ['config_key', '=', 'MIAOSHA_BASICS_CONFIG']]);
}
/**
* 读取基本设置
* @param $site_id
* @return array
*/
public function getBasicsConfig($site_id)
{
$config = new ConfigModel();
return $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', 'shop'], ['config_key', '=', 'MIAOSHA_BASICS_CONFIG']]);
}
/**
* 判断当前时间是否在秒杀开启时间,并区分有无钻石用户
* @param $site_id
* @param $member_id
* @param $status
* @return array
*/
public function checkTimes($site_id, $member_id, $status = 2)
{
switch ($status) {
case '2':
$startTimeKey = 'miaosha_start_time';
$endTimeKey = 'miaosha_end_time';
$fenxiao = model('member')->getInfo([['member_id', '=', $member_id]]);
if (!empty($fenxiao) && $fenxiao['diamond'] > 0) {
$startTimeKey = 'miaosha_early_start_time';
}
break;
case '7':
$startTimeKey = 'jianlou_start_time';
$endTimeKey = 'jianlou_end_time';
break;
default:
return $this->error('', '参数不合法');
}
$nowTime = time() - strtotime("today");
$is_read = FALSE;
$nowtimes = [];
$basics = $this->getBasicsConfig($site_id)['data']['value'];
if (empty($basics['times'])) {
return $this->error('', '暂无秒杀活动');
}
$recentlyTimes = [];
foreach ($basics['times'] as $times) {
if ($times[$startTimeKey] <= $nowTime && $times[$endTimeKey] >= $nowTime) {
$is_read = TRUE;
$nowtimes = [
'original' => $times,
'start_time' => $times[$startTimeKey],
'end_time' => $times[$endTimeKey]
];
break;
}
if (empty($recentlyTimes) && $times['miaosha_start_time'] >= $nowTime) {
$recentlyTimes = $times;
foreach ($recentlyTimes as $timeKey => $time) {
$recentlyTimes[$timeKey] += strtotime(date("Y-m-d", time()));
}
}
}
if (empty($recentlyTimes)) {
$recentlyTimes = $basics['times'][0];
foreach ($recentlyTimes as $timeKey => $time) {
$recentlyTimes[$timeKey] += strtotime(date("Y-m-d", time())) + 24 * 60 * 60;
}
}
if (!$is_read) {
return error(-801, '未到秒杀时间', $recentlyTimes);
}
//判断是否是提前秒杀
$nowtimes['is_early'] = FALSE;
if ($times['miaosha_early_start_time'] <= $nowTime && $times['miaosha_start_time'] >= $nowTime) {
$nowtimes['is_early'] = TRUE;
}
return $this->success($nowtimes);
}
}