mirror of
https://github.com/crmeb/CRMEB.git
synced 2025-12-11 18:32:50 +00:00
933 lines
40 KiB
PHP
933 lines
40 KiB
PHP
<?php
|
||
// +----------------------------------------------------------------------
|
||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||
// +----------------------------------------------------------------------
|
||
// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
|
||
// +----------------------------------------------------------------------
|
||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||
// +----------------------------------------------------------------------
|
||
// | Author: CRMEB Team <admin@crmeb.com>
|
||
// +----------------------------------------------------------------------
|
||
declare (strict_types=1);
|
||
|
||
namespace app\services\activity\combination;
|
||
|
||
use app\dao\activity\combination\StorePinkDao;
|
||
use app\jobs\PinkJob;
|
||
use app\services\BaseServices;
|
||
use app\services\order\StoreOrderDeliveryServices;
|
||
use app\services\order\StoreOrderRefundServices;
|
||
use app\services\order\StoreOrderServices;
|
||
use app\services\other\PosterServices;
|
||
use app\services\other\QrcodeServices;
|
||
use app\services\system\attachment\SystemAttachmentServices;
|
||
use app\services\user\UserServices;
|
||
use crmeb\exceptions\ApiException;
|
||
use crmeb\services\CacheService;
|
||
use crmeb\services\app\MiniProgramService;
|
||
use app\services\other\UploadService;
|
||
use Guzzle\Http\EntityBody;
|
||
|
||
/**
|
||
*
|
||
* Class StorePinkServices
|
||
* @package app\services\activity
|
||
* @method getPinkCount(array $where)
|
||
* @method int count(array $where = []) 获取指定条件下的条数
|
||
* @method getPinkOkSumTotalNum()
|
||
* @method isPink(int $id, int $uid) 是否能继续拼团
|
||
* @method getPinkUserOne(int $id) 拼团
|
||
* @method getCount(array $where) 获取某些条件总数
|
||
* @method value(array $where, string $field)
|
||
* @method getColumn(array $where, string $field, ?string $key)
|
||
* @method update(array $where, array $data)
|
||
*/
|
||
class StorePinkServices extends BaseServices
|
||
{
|
||
|
||
/**
|
||
* StorePinkServices constructor.
|
||
* @param StorePinkDao $dao
|
||
*/
|
||
public function __construct(StorePinkDao $dao)
|
||
{
|
||
$this->dao = $dao;
|
||
}
|
||
|
||
/**
|
||
* @param array $where
|
||
* @return array
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function systemPage(array $where)
|
||
{
|
||
$where['k_id'] = 0;
|
||
[$page, $limit] = $this->getPageValue();
|
||
$list = $this->dao->getList($where, $page, $limit);
|
||
foreach ($list as &$item) {
|
||
$item['count_people'] = $this->dao->count(['k_id' => $item['id']]) + 1;
|
||
$item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', (int)$item['add_time']) : '';
|
||
$item['_stop_time'] = $item['stop_time'] ? date('Y-m-d H:i:s', (int)$item['stop_time']) : '';
|
||
}
|
||
$count = $this->dao->count($where);
|
||
return compact('list', 'count');
|
||
}
|
||
|
||
/**
|
||
* 拼团列表头部
|
||
* @return array
|
||
*/
|
||
public function getStatistics()
|
||
{
|
||
$res = [
|
||
['col' => 6, 'count' => $this->dao->count(), 'name' => '参与人数(人)', 'className' => 'iconfaqirenshu'],
|
||
['col' => 6, 'count' => $this->dao->count(['k_id' => 0, 'status' => 2]), 'name' => '成团数量(个)', 'className' => 'iconshengyukucun'],
|
||
];
|
||
return compact('res');
|
||
}
|
||
|
||
/**
|
||
* 参团人员
|
||
* @param int $id
|
||
* @return array
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function getPinkMember(int $id)
|
||
{
|
||
return $this->dao->getList(['k_id' => $id]);
|
||
}
|
||
|
||
/**
|
||
* 拼团退款
|
||
* @param $order
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function setRefundPink($order)
|
||
{
|
||
$res = true;
|
||
if ($order['pink_id']) {
|
||
$id = $order['pink_id'];
|
||
} else {
|
||
return true;
|
||
}
|
||
//正在拼团 团长
|
||
$count = $this->dao->getOne(['id' => $id, 'uid' => $order['uid']]);
|
||
//正在拼团 团员
|
||
$countY = $this->dao->getOne(['k_id' => $id, 'uid' => $order['uid']]);
|
||
if (!$count && !$countY) {
|
||
return $res;
|
||
}
|
||
if ($count) {//团长
|
||
//判断团内是否还有其他人 如果有 团长为第二个进团的人
|
||
$kCount = $this->dao->getPinking(['k_id' => $id]);
|
||
if ($kCount) {
|
||
$res11 = $this->dao->update($id, ['k_id' => $kCount['id']], 'k_id');
|
||
$res12 = $this->dao->update($kCount['id'], ['stop_time' => $count['add_time'] + 86400, 'k_id' => 0]);
|
||
$res1 = $res11 && $res12;
|
||
$res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'k_id' => $kCount['id'], 'is_refund' => $kCount['id'], 'status' => 3]);
|
||
$res3 = app()->make(StoreOrderServices::class)->update(['pink_id' => $id], ['pink_id' => $kCount['id']]);
|
||
} else {
|
||
$res1 = $res3 = true;
|
||
$res2 = $this->dao->update($id, ['stop_time' => time() - 1, 'is_refund' => $id, 'status' => 3]);
|
||
}
|
||
//修改结束时间为前一秒 团长ID为0
|
||
$res = $res1 && $res2 && $res3;
|
||
} else if ($countY) {//团员
|
||
$res = $this->dao->update($countY['id'], ['stop_time' => time() - 1, 'is_refund' => $id, 'status' => 3]);
|
||
}
|
||
return $res;
|
||
}
|
||
|
||
/**
|
||
* 拼团详情查看拼团列表
|
||
* @param int $id
|
||
* @param bool $type
|
||
* @return array
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function getPinkList(int $id, bool $type)
|
||
{
|
||
$where['cid'] = $id;
|
||
$where['k_id'] = 0;
|
||
$where['is_refund'] = 0;
|
||
$where['status'] = 1;
|
||
$pinkList = $this->dao->pinkList($where);
|
||
$ids = array_column($pinkList, 'id');
|
||
$orderIdKey = array_column($pinkList, 'order_id_key');
|
||
$refunList = [];
|
||
if ($orderIdKey) {
|
||
$refunList = app()->make(StoreOrderRefundServices::class)->getColumn([['store_order_id', 'in', $orderIdKey]], 'id', 'store_order_id');
|
||
}
|
||
if ($refunList) {
|
||
$list = [];
|
||
foreach ($pinkList as $item) {
|
||
if (!isset($refunList[$item['order_id_key']])) {
|
||
$list[] = $item;
|
||
}
|
||
}
|
||
} else {
|
||
$list = $pinkList;
|
||
}
|
||
$counts = $this->dao->getPinkPeopleCount($ids);
|
||
if ($type) {
|
||
$pinkAll = [];
|
||
foreach ($list as &$v) {
|
||
$v['count'] = $v['people'] - $counts[$v['id']];
|
||
$v['h'] = date('H', (int)$v['stop_time']);
|
||
$v['i'] = date('i', (int)$v['stop_time']);
|
||
$v['s'] = date('s', (int)$v['stop_time']);
|
||
$pinkAll[] = $v['id'];//开团团长ID
|
||
$v['stop_time'] = (int)$v['stop_time'];
|
||
$v['avatar'] = set_file_url($v['avatar']);
|
||
}
|
||
return [$list, $pinkAll];
|
||
}
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* 获取成团列表信息
|
||
* @param int $uid
|
||
* @return array
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function getPinkOkList(int $uid)
|
||
{
|
||
$list = $this->dao->successList($uid);
|
||
$msg = [];
|
||
foreach ($list as &$item) {
|
||
if (isset($item['nickname'])) $msg[] = $item['nickname'] .= '拼团成功';
|
||
}
|
||
return $msg;
|
||
}
|
||
|
||
/**
|
||
* 查找拼团信息
|
||
* @param $pink
|
||
* @return array
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function getPinkMemberAndPinkK($pink)
|
||
{
|
||
//查找拼团团员和团长
|
||
if ($pink['k_id']) {
|
||
$pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['k_id']]);
|
||
$pinkT = $this->dao->getPinkUserOne($pink['k_id']);
|
||
} else {
|
||
$pinkAll = $this->dao->getPinkUserList(['k_id' => $pink['id']]);
|
||
$pinkT = $pink;
|
||
}
|
||
$count = count($pinkAll) + 1;
|
||
$count = $pinkT['people'] - $count;
|
||
$idAll = [];
|
||
$uidAll = [];
|
||
//收集拼团用户id和拼团id
|
||
foreach ($pinkAll as $k => $v) {
|
||
$idAll[$k] = $v['id'];
|
||
$uidAll[$k] = $v['uid'];
|
||
}
|
||
$idAll[] = $pinkT['id'];
|
||
$uidAll[] = $pinkT['uid'];
|
||
return [$pinkAll, $pinkT, $count, $idAll, $uidAll];
|
||
}
|
||
|
||
/**
|
||
* 拼团失败
|
||
* @param $pinkAll
|
||
* @param $pinkT
|
||
* @param $pinkBool
|
||
* @param bool $isRunErr
|
||
* @param bool $isIds
|
||
* @return array|int
|
||
*/
|
||
public function pinkFail($pinkAll, $pinkT, $pinkBool, $isRunErr = true, $isIds = false)
|
||
{
|
||
/** @var StoreOrderServices $orderService */
|
||
$orderService = app()->make(StoreOrderServices::class);
|
||
/** @var StoreOrderRefundServices $orderRefundService */
|
||
$orderRefundService = app()->make(StoreOrderRefundServices::class);
|
||
$pinkIds = [];
|
||
try {
|
||
if ($pinkT['stop_time'] < time()) {//拼团时间超时 退款
|
||
$virtual = $this->virtualCombination($pinkT['id']);
|
||
if ($virtual) return 1;
|
||
$pinkBool = -1;
|
||
array_push($pinkAll, $pinkT);
|
||
$oids = array_column($pinkAll, 'order_id_key');
|
||
$orders = $orderService->getColumn([['id', 'in', $oids]], '*', 'id');
|
||
$refundData = [
|
||
'refund_reason' => '拼团时间超时',
|
||
'refund_explain' => '拼团时间超时',
|
||
'refund_img' => json_encode([]),
|
||
];
|
||
foreach ($pinkAll as $v) {
|
||
if (isset($orders[$v['order_id_key']]) && $order = $orders[$v['order_id_key']]) {
|
||
$res1 = $res2 = true;
|
||
if (!in_array($order['refund_status'], [1, 2])) {
|
||
$res1 = $orderRefundService->applyRefund((int)$order['id'], (int)$order['uid'], $order, [], 1, (float)$order['pay_price'], $refundData, 1);
|
||
}
|
||
$res2 = $this->dao->getCount([['uid', '=', $v['uid']], ['is_tpl', '=', 0], ['k_id|id', '=', $pinkT['id']]]);
|
||
if ($res1 && $res2) {
|
||
if ($isIds) array_push($pinkIds, $v['id']);
|
||
$this->orderPinkAfterNo($pinkT['uid'], $pinkT['id'], false, $orders[$v['order_id_key']]['is_channel']);
|
||
} else {
|
||
if ($isRunErr) return $pinkBool;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ($isIds) return $pinkIds;
|
||
return $pinkBool;
|
||
} catch (\Exception $e) {
|
||
return $pinkBool;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 失败发送消息和修改状态
|
||
* @param $uid
|
||
* @param $pid
|
||
* @param bool $isRemove
|
||
* @param $channel
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function orderPinkAfterNo($uid, $pid, $isRemove = false, $channel)
|
||
{
|
||
$pink = $this->dao->getOne([['id|k_id', '=', $pid], ['uid', '=', $uid]], '*', ['getProduct']);
|
||
if ($isRemove) {
|
||
event('NoticeListener', [['uid' => $uid, 'pink' => $pink, 'user_type' => $channel], 'send_order_pink_clone']);
|
||
} else {
|
||
event('NoticeListener', [['uid' => $uid, 'pink' => $pink, 'user_type' => $channel], 'send_order_pink_fial']);
|
||
}
|
||
$this->dao->update([['id|k_id', '=', $pid]], ['status' => 3, 'stop_time' => time()]);
|
||
}
|
||
|
||
|
||
/**
|
||
* 判断拼团状态
|
||
* @param $pinkId
|
||
* @return bool
|
||
*/
|
||
public function isPinkStatus($pinkId)
|
||
{
|
||
if (!$pinkId) return false;
|
||
$stopTime = $this->dao->value(['id' => $pinkId], 'stop_time');
|
||
if ($stopTime < time()) return true; //拼团结束
|
||
else return false;//拼团未结束
|
||
}
|
||
|
||
/**
|
||
* 获取拼团order_id
|
||
* @param int $id
|
||
* @param int $uid
|
||
* @return mixed
|
||
*/
|
||
public function getCurrentPink(int $id, int $uid)
|
||
{
|
||
$oid = $this->dao->value(['id' => $id, 'uid' => $uid], 'order_id_key');
|
||
if (!$oid) $oid = $this->dao->value(['k_id' => $id, 'uid' => $uid], 'order_id_key');
|
||
/** @var StoreOrderServices $orderService */
|
||
$orderService = app()->make(StoreOrderServices::class);
|
||
return $orderService->value(['id' => $oid], 'order_id');
|
||
}
|
||
|
||
/**
|
||
* 拼团成功
|
||
* @param $uidAll
|
||
* @param $idAll
|
||
* @param $uid
|
||
* @param $pinkT
|
||
* @return int
|
||
*/
|
||
public function pinkComplete($uidAll, $idAll, $uid, $pinkT)
|
||
{
|
||
$pinkBool = 6;
|
||
try {
|
||
if (!$this->dao->getCount([['id', 'in', $idAll], ['is_refund', '=', 1]])) {
|
||
$this->dao->update([['id', 'in', $idAll]], ['stop_time' => time(), 'status' => 2]);
|
||
if (in_array($uid, $uidAll)) {
|
||
if ($this->dao->getCount([['uid', 'in', $uidAll], ['is_tpl', '=', 0], ['k_id|id', '=', $pinkT['id']]]))
|
||
$this->orderPinkAfter($uidAll, $pinkT['id']);
|
||
$pinkBool = 1;
|
||
} else $pinkBool = 3;
|
||
}
|
||
return $pinkBool;
|
||
} catch (\Exception $e) {
|
||
return $pinkBool;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 拼团成功修改
|
||
* @param $uidAll
|
||
* @param $pid
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function orderPinkAfter($uidAll, $pid)
|
||
{
|
||
//发送消息之前去除虚拟用户
|
||
foreach ($uidAll as $key => $uid) {
|
||
if ($uid == 0) unset($uidAll[$key]);
|
||
}
|
||
/** @var StoreCombinationServices $storeCombinationServices */
|
||
$storeCombinationServices = app()->make(StoreCombinationServices::class);
|
||
$title = $storeCombinationServices->value(['id' => $this->dao->value(['id' => $pid], 'cid')], 'title');
|
||
$pinkList = $this->dao->getColumn([['id|k_id', '=', $pid], ['uid', '<>', 0]], '*', 'uid');
|
||
$pinkT_name = $this->dao->value(['id' => $pid], 'nickname');
|
||
$order_ids = array_column($pinkList, 'order_id');
|
||
/** @var StoreOrderServices $orderService */
|
||
$orderService = app()->make(StoreOrderServices::class);
|
||
$order_channels = $orderService->getColumn([['order_id', 'in', $order_ids]], 'is_channel', 'order_id');
|
||
if (!$pinkList) return false;
|
||
foreach ($pinkList as $item) {
|
||
$item['nickname'] = $pinkT_name;
|
||
//用户发送消息
|
||
event('NoticeListener', [
|
||
[
|
||
'list' => $item,
|
||
'title' => $title,
|
||
'user_type' => $order_channels[$item['order_id']],
|
||
'url' => '/pages/users/order_details/index?order_id=' . $item['order_id']
|
||
], 'order_user_groups_success']);
|
||
}
|
||
$this->dao->update([['uid', 'in', $uidAll], ['id|k_id', '=', $pid]], ['is_tpl' => 1]);
|
||
|
||
//拼团卡密和优惠券商品,成团后发放
|
||
$orderInfos = $orderService->getColumn([['order_id', 'in', $order_ids]], '*', 'order_id');
|
||
foreach ($orderInfos as $orderInfo) {
|
||
if ($orderInfo['virtual_type'] > 0) {
|
||
$orderInfo['cart_id'] = json_decode($orderInfo['cart_id'], true);
|
||
/** @var StoreOrderDeliveryServices $orderDeliveryServices */
|
||
$orderDeliveryServices = app()->make(StoreOrderDeliveryServices::class);
|
||
$orderDeliveryServices->virtualSend($orderInfo);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 创建拼团
|
||
* @param $order
|
||
* @return mixed
|
||
*/
|
||
public function createPink(array $orderInfo)
|
||
{
|
||
/** @var StoreCombinationServices $services */
|
||
$services = app()->make(StoreCombinationServices::class);
|
||
$product = $services->getOne(['id' => $orderInfo['combination_id']], 'effective_time,title,people');
|
||
if (!$product) {
|
||
return false;
|
||
}
|
||
/** @var UserServices $userServices */
|
||
$userServices = app()->make(UserServices::class);
|
||
$userInfo = $userServices->get($orderInfo['uid']);
|
||
if ($orderInfo['pink_id']) {
|
||
//拼团存在
|
||
$res = false;
|
||
$pink['uid'] = $orderInfo['uid'];//用户id
|
||
$pink['nickname'] = $userInfo['nickname'];
|
||
$pink['avatar'] = $userInfo['avatar'];
|
||
if ($this->isPinkBe($pink, $orderInfo['pink_id'])) return false;
|
||
$pink['order_id'] = $orderInfo['order_id'];//订单id 生成
|
||
$pink['order_id_key'] = $orderInfo['id'];//订单id 数据库id
|
||
$pink['total_num'] = $orderInfo['total_num'];//购买个数
|
||
$pink['total_price'] = $orderInfo['pay_price'];//总金额
|
||
$pink['k_id'] = $orderInfo['pink_id'];//拼团id
|
||
foreach ($orderInfo['cartInfo'] as $v) {
|
||
$pink['cid'] = $v['combination_id'];//拼团商品id
|
||
$pink['pid'] = $v['product_id'];//商品id
|
||
$pink['people'] = $product['people'];//几人拼团
|
||
$pink['price'] = $v['productInfo']['price'];//单价
|
||
$pink['stop_time'] = 0;//结束时间
|
||
$pink['add_time'] = time();//开团时间
|
||
$res = $this->save($pink);
|
||
}
|
||
// 拼团团成功发送模板消息
|
||
event('NoticeListener', [['orderInfo' => $orderInfo, 'title' => $product['title'], 'pink' => $pink], 'can_pink_success']);
|
||
|
||
//处理拼团完成
|
||
list($pinkAll, $pinkT, $count, $idAll, $uidAll) = $this->getPinkMemberAndPinkK($pink);
|
||
if ($pinkT['status'] == 1) {
|
||
if (!$count)//组团完成
|
||
$this->pinkComplete($uidAll, $idAll, $pink['uid'], $pinkT);
|
||
else
|
||
$this->pinkFail($pinkAll, $pinkT, 0);
|
||
}
|
||
|
||
if ($res) return true;
|
||
else return false;
|
||
} else {
|
||
//创建拼团
|
||
$res = false;
|
||
$pink['uid'] = $orderInfo['uid'];//用户id
|
||
$pink['nickname'] = $userInfo['nickname'];
|
||
$pink['avatar'] = $userInfo['avatar'];
|
||
$pink['order_id'] = $orderInfo['order_id'];//订单id 生成
|
||
$pink['order_id_key'] = $orderInfo['id'];//订单id 数据库id
|
||
$pink['total_num'] = $orderInfo['total_num'];//购买个数
|
||
$pink['total_price'] = $orderInfo['pay_price'];//总金额
|
||
$pink['k_id'] = 0;//拼团id
|
||
/** @var StoreOrderServices $orderServices */
|
||
$orderServices = app()->make(StoreOrderServices::class);
|
||
foreach ($orderInfo['cartInfo'] as $v) {
|
||
$pink['cid'] = $v['combination_id'];//拼团商品id
|
||
$pink['pid'] = $v['product_id'];//商品id
|
||
$pink['people'] = $product['people'];//几人拼团
|
||
$pink['price'] = $v['productInfo']['price'];//单价
|
||
$pink['stop_time'] = time() + $product->effective_time * 3600;//结束时间
|
||
$pink['add_time'] = time();//开团时间
|
||
$res1 = $this->dao->save($pink);
|
||
$res2 = $orderServices->update($orderInfo['id'], ['pink_id' => $res1['id']]);
|
||
$res = $res1 && $res2;
|
||
$pink['id'] = $res1['id'];
|
||
}
|
||
|
||
PinkJob::dispatchSecs((int)(($product->effective_time * 3600) + 60), [$pink['id']]);
|
||
// 开团成功发送模板消息
|
||
event('NoticeListener', [['orderInfo' => $orderInfo, 'title' => $product['title'], 'pink' => $pink], 'open_pink_success']);
|
||
|
||
if ($res) return true;
|
||
else return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 是否拼团
|
||
* @param array $data
|
||
* @param int $id
|
||
* @return int
|
||
*/
|
||
public function isPinkBe(array $data, int $id)
|
||
{
|
||
$data['id'] = $id;
|
||
$count = $this->dao->getCount($data);
|
||
if ($count) return $count;
|
||
$data['k_id'] = $id;
|
||
$count = $this->dao->getCount($data);
|
||
if ($count) return $count;
|
||
else return 0;
|
||
}
|
||
|
||
/**
|
||
* 取消拼团
|
||
* @param int $uid
|
||
* @param int $cid
|
||
* @param int $pink_id
|
||
* @param null $nextPinkT
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function removePink(int $uid, int $cid, int $pink_id, $nextPinkT = null)
|
||
{
|
||
$pinkT = $this->dao->getOne([
|
||
['uid', '=', $uid],
|
||
['id', '=', $pink_id],
|
||
['cid', '=', $cid],
|
||
['k_id', '=', 0],
|
||
['is_refund', '=', 0],
|
||
['status', '=', 1],
|
||
['stop_time', '>', time()],
|
||
]);
|
||
if (!$pinkT) throw new ApiException(410314);
|
||
list($pinkAll, $pinkT, $count, $idAll, $uidAll) = $this->getPinkMemberAndPinkK($pinkT);
|
||
if (count($pinkAll)) {
|
||
$count = $pinkT['people'] - ($this->dao->count(['k_id' => $pink_id, 'is_refund' => 0]) + 1);
|
||
if ($count) {
|
||
//拼团未完成,拼团有成员取消开团取 紧跟团长后拼团的人
|
||
if (isset($pinkAll[0])) $nextPinkT = $pinkAll[0];
|
||
} else {
|
||
//拼团完成
|
||
$this->PinkComplete($uidAll, $idAll, $uid, $pinkT);
|
||
throw new ApiException(410316);
|
||
}
|
||
}
|
||
/** @var StoreOrderServices $orderService */
|
||
$orderService = app()->make(StoreOrderServices::class);
|
||
/** @var StoreOrderRefundServices $orderRefundService */
|
||
$orderRefundService = app()->make(StoreOrderRefundServices::class);
|
||
//取消开团
|
||
$order = $orderService->get($pinkT['order_id_key']);
|
||
$refundData = [
|
||
'refund_reason' => '用户手动取消拼团',
|
||
'refund_explain' => '用户手动取消拼团',
|
||
'refund_img' => json_encode([]),
|
||
];
|
||
$res1 = $orderRefundService->applyRefund((int)$order['id'], (int)$order['uid'], $order, [], 1, (float)$order['pay_price'], $refundData, 1);
|
||
$res2 = $this->dao->getCount([['uid', '=', $pinkT['uid']], ['k_id|id', '=', $pinkT['id']]]);
|
||
if ($res1 && $res2) {
|
||
$this->orderPinkAfterNo($pinkT['uid'], $pinkT['id'], true, $order->is_channel);
|
||
}
|
||
//当前团有人的时候
|
||
if (is_array($nextPinkT)) {
|
||
$this->dao->update($nextPinkT['id'], ['k_id' => 0, 'status' => 1, 'stop_time' => $pinkT['stop_time']]);
|
||
$this->dao->update($pinkT['id'], ['k_id' => $nextPinkT['id']], 'k_id');
|
||
$orderService->update($nextPinkT['order_id'], ['pink_id' => $nextPinkT['id']], 'order_id');
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 获取拼团海报
|
||
* @param $pinkId
|
||
* @param $from
|
||
* @param $user
|
||
* @return string
|
||
*/
|
||
public function getPinkPoster($pinkId, $from, $user)
|
||
{
|
||
$pinkInfo = $this->dao->get((int)$pinkId);
|
||
/** @var StoreCombinationServices $combinationService */
|
||
$combinationService = app()->make(StoreCombinationServices::class);
|
||
$storeCombinationInfo = $combinationService->getOne(['id' => $pinkInfo['cid']], '*', ['getPrice']);
|
||
$data['title'] = $storeCombinationInfo['title'];
|
||
$data['image'] = $storeCombinationInfo['image'];
|
||
$data['price'] = $pinkInfo['price'];
|
||
$data['label'] = $pinkInfo['people'] . '人团';
|
||
if ($pinkInfo['k_id']) $pinkAll = $this->getPinkMember($pinkInfo['k_id']);
|
||
else $pinkAll = $this->getPinkMember($pinkInfo['id']);
|
||
$count = count($pinkAll);
|
||
$data['msg'] = '原价¥' . $storeCombinationInfo['product_price'] . ' 还差' . ($pinkInfo['people'] - $count) . '人拼团成功';
|
||
|
||
/** @var SystemAttachmentServices $systemAttachmentServices */
|
||
$systemAttachmentServices = app()->make(SystemAttachmentServices::class);
|
||
|
||
try {
|
||
$siteUrl = sys_config('site_url');
|
||
if ($from == 'routine') {
|
||
//小程序
|
||
$name = $pinkId . '_' . $user['uid'] . '_' . $user['is_promoter'] . '_pink_share_routine.jpg';
|
||
$imageInfo = $systemAttachmentServices->getInfo(['name' => $name]);
|
||
if (!$imageInfo) {
|
||
$valueData = 'id=' . $pinkId;
|
||
/** @var UserServices $userServices */
|
||
$userServices = app()->make(UserServices::class);
|
||
if ($userServices->checkUserPromoter((int)$user['uid'], $user)) {
|
||
$valueData .= '&pid=' . $user['uid'];
|
||
}
|
||
$res = MiniProgramService::appCodeUnlimitService($valueData, 'pages/activity/goods_combination_status/index', 280);
|
||
if (!$res) throw new ApiException(410167);
|
||
$uploadType = (int)sys_config('upload_type', 1);
|
||
$upload = UploadService::init();
|
||
$res = (string)EntityBody::factory($res);
|
||
$res = $upload->to('routine/activity/pink/code')->validate()->setAuthThumb(false)->stream($res, $name);
|
||
if ($res === false) {
|
||
throw new ApiException($upload->getError());
|
||
}
|
||
$imageInfo = $upload->getUploadInfo();
|
||
$imageInfo['image_type'] = $uploadType;
|
||
if ($imageInfo['image_type'] == 1) $remoteImage = PosterServices::remoteImage($siteUrl . $imageInfo['dir']);
|
||
else $remoteImage = PosterServices::remoteImage($imageInfo['dir']);
|
||
if (!$remoteImage['status']) throw new ApiException($remoteImage['msg']);
|
||
$systemAttachmentServices->save([
|
||
'name' => $imageInfo['name'],
|
||
'att_dir' => $imageInfo['dir'],
|
||
'satt_dir' => $imageInfo['thumb_path'],
|
||
'att_size' => $imageInfo['size'],
|
||
'att_type' => $imageInfo['type'],
|
||
'image_type' => $imageInfo['image_type'],
|
||
'module_type' => 2,
|
||
'time' => time(),
|
||
'pid' => 1,
|
||
'type' => 1
|
||
]);
|
||
$url = $imageInfo['dir'];
|
||
} else $url = $imageInfo['att_dir'];
|
||
$data['url'] = $url;
|
||
if ($imageInfo['image_type'] == 1)
|
||
$data['url'] = $siteUrl . $url;
|
||
$posterImage = PosterServices::setShareMarketingPoster($data, 'routine/activity/pink/poster');
|
||
if (!is_array($posterImage)) throw new ApiException(410172);
|
||
$systemAttachmentServices->save([
|
||
'name' => $posterImage['name'],
|
||
'att_dir' => $posterImage['dir'],
|
||
'satt_dir' => $posterImage['thumb_path'],
|
||
'att_size' => $posterImage['size'],
|
||
'att_type' => $posterImage['type'],
|
||
'image_type' => $posterImage['image_type'],
|
||
'module_type' => 2,
|
||
'time' => $posterImage['time'],
|
||
'pid' => 1,
|
||
'type' => 1
|
||
]);
|
||
if ($posterImage['image_type'] == 1) $posterImage['dir'] = $siteUrl . $posterImage['dir'];
|
||
$routinePosterImage = set_http_type($posterImage['dir'], 0);//小程序推广海报
|
||
return $routinePosterImage;
|
||
} else if ($from == 'wechat') {
|
||
//公众号
|
||
$name = $pinkId . '_' . $user['uid'] . '_' . $user['is_promoter'] . '_pink_share_wap.jpg';
|
||
$imageInfo = $systemAttachmentServices->getInfo(['name' => $name]);
|
||
if (!$imageInfo) {
|
||
$codeUrl = set_http_type($siteUrl . '/pages/activity/goods_combination_status/index?id=' . $pinkId . '&spread=' . $user['uid'], 1);//二维码链接
|
||
$imageInfo = PosterServices::getQRCodePath($codeUrl, $name);
|
||
if (is_string($imageInfo)) {
|
||
throw new ApiException(410167);
|
||
}
|
||
$systemAttachmentServices->save([
|
||
'name' => $imageInfo['name'],
|
||
'att_dir' => $imageInfo['dir'],
|
||
'satt_dir' => $imageInfo['thumb_path'],
|
||
'att_size' => $imageInfo['size'],
|
||
'att_type' => $imageInfo['type'],
|
||
'image_type' => $imageInfo['image_type'],
|
||
'module_type' => 2,
|
||
'time' => $imageInfo['time'],
|
||
'pid' => 1,
|
||
'type' => 1
|
||
]);
|
||
$url = $imageInfo['dir'];
|
||
} else $url = $imageInfo['att_dir'];
|
||
$data['url'] = $url;
|
||
if ($imageInfo['image_type'] == 1) $data['url'] = $siteUrl . $url;
|
||
$posterImage = PosterServices::setShareMarketingPoster($data, 'wap/activity/pink/poster');
|
||
if (!is_array($posterImage)) throw new ApiException(410172);
|
||
$systemAttachmentServices->save([
|
||
'name' => $posterImage['name'],
|
||
'att_dir' => $posterImage['dir'],
|
||
'satt_dir' => $posterImage['thumb_path'],
|
||
'att_size' => $posterImage['size'],
|
||
'att_type' => $posterImage['type'],
|
||
'image_type' => $posterImage['image_type'],
|
||
'module_type' => 2,
|
||
'time' => $posterImage['time'],
|
||
'pid' => 1,
|
||
'type' => 1
|
||
]);
|
||
if ($posterImage['image_type'] == 1) $posterImage['dir'] = $siteUrl . $posterImage['dir'];
|
||
$wapPosterImage = set_http_type($posterImage['dir'], 1);//公众号推广海报
|
||
return $wapPosterImage;
|
||
}
|
||
throw new ApiException(100100);
|
||
} catch (\Exception $e) {
|
||
throw new ApiException($e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 修改到期的拼团状态
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
* @throws \think\exception\DbException
|
||
*/
|
||
public function statusPink()
|
||
{
|
||
$pinkListEnd = $this->dao->pinkListEnd();
|
||
foreach ($pinkListEnd as $key => $pink) {
|
||
[$pinkAll, $pinkT, $count, $idAll, $uidAll] = $this->getPinkMemberAndPinkK($pink);
|
||
$this->pinkFail($pinkAll, $pinkT, 0);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 拼团成功
|
||
* @param array $pinkRegimental 成功的团长编号
|
||
* @return bool
|
||
* @throws \Exception
|
||
*/
|
||
public function successPinkEdit(array $pinkRegimental)
|
||
{
|
||
if (!count($pinkRegimental)) return true;
|
||
foreach ($pinkRegimental as $key => &$item) {
|
||
$pinkList = $this->dao->getColumn(['k_id' => $item], 'id', 'id');
|
||
$pinkList[] = $item;
|
||
$pinkList = implode(',', $pinkList);
|
||
$this->dao->update([['id', 'in', $pinkList]], ['stop_time' => time(), 'status' => 2]);
|
||
$pinkUidList = $this->dao->getColumn([['id', 'in', $pinkList], ['is_tpl', '=', 0]], 'uid', 'uid');
|
||
if (count($pinkUidList)) $this->orderPinkAfter($pinkUidList, $item);//发送模板消息
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 拼团失败
|
||
* @param array $pinkRegimental 失败的团长编号
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
* @throws \think\exception\DbException
|
||
*/
|
||
public function failPinkEdit(array $pinkRegimental)
|
||
{
|
||
if (!count($pinkRegimental)) return true;
|
||
foreach ($pinkRegimental as $key => &$item) {
|
||
$pinkList = $this->dao->getColumn(['k_id' => $item], 'id', 'id');
|
||
$pinkList[] = $item;
|
||
$pinkList = implode(',', $pinkList);
|
||
$refundPinkList = $this->dao->getColumn([['id', 'in', $pinkList]], 'order_id,uid', 'id');
|
||
if ($refundPinkList) {
|
||
/** @var StoreOrderRefundServices $orderRefundService */
|
||
$orderRefundService = app()->make(StoreOrderRefundServices::class);
|
||
$refundData = [
|
||
'refund_reason' => '拼团时间超时',
|
||
'refund_explain' => '拼团时间超时',
|
||
'refund_img' => json_encode([]),
|
||
];
|
||
foreach ($refundPinkList as &$items) {
|
||
$orderRefundService->applyRefund((int)$items['id'], (int)$items['uid'], $items, [], 1, (float)$items['pay_price'], $refundData, 1);//申请退款
|
||
}
|
||
}
|
||
$this->dao->update([['id', 'in', $pinkList]], ['status' => 3]);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 虚拟拼团
|
||
* @param $pinkId
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function virtualCombination($pinkId, $operator = 'auto')
|
||
{
|
||
$pinkInfo = $this->dao->get($pinkId);
|
||
$people = $pinkInfo['people'];
|
||
$count = $this->dao->count(['k_id' => $pinkId]) + 1;
|
||
$percent1 = bcdiv((string)$count, (string)$people, 2) * 100;
|
||
/** @var StoreCombinationServices $services */
|
||
$services = app()->make(StoreCombinationServices::class);
|
||
$percent2 = $services->value(['id' => $pinkInfo['cid']], 'virtual');
|
||
if ($percent1 >= $percent2 || $operator == 'admin') {
|
||
$time = time();
|
||
$num = $people - $count;
|
||
$data = [];
|
||
for ($i = 0; $i < $num; $i++) {
|
||
$data[$i]['uid'] = 0;
|
||
$data[$i]['nickname'] = substr(md5(time() . rand(1000, 9999)), 0, 12);
|
||
$data[$i]['avatar'] = sys_config('h5_avatar');
|
||
$data[$i]['order_id'] = 0;
|
||
$data[$i]['order_id_key'] = 0;
|
||
$data[$i]['total_num'] = 0;
|
||
$data[$i]['total_price'] = 0;
|
||
$data[$i]['cid'] = $pinkInfo['cid'];
|
||
$data[$i]['pid'] = $pinkInfo['pid'];
|
||
$data[$i]['people'] = $people;
|
||
$data[$i]['price'] = 0;
|
||
$data[$i]['add_time'] = $time;
|
||
$data[$i]['stop_time'] = $time;
|
||
$data[$i]['k_id'] = $pinkInfo['id'];
|
||
$data[$i]['is_tpl'] = 1;
|
||
$data[$i]['is_refund'] = 0;
|
||
$data[$i]['status'] = 2;
|
||
$data[$i]['is_virtual'] = 1;
|
||
}
|
||
//添加虚拟团员
|
||
$this->dao->saveAll($data);
|
||
//更改团员状态为拼团成功
|
||
$this->dao->update($pinkId, ['stop_time' => $time, 'status' => 2], 'k_id');
|
||
//更改团长为拼团成功
|
||
$this->dao->update($pinkId, ['stop_time' => $time, 'status' => 2]);
|
||
$uidAll = $this->dao->getColumn([['id|k_id', '=', $pinkId]], 'uid');
|
||
$this->orderPinkAfter($uidAll, $pinkId);
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取拼团海报详情信息
|
||
* @param int $id
|
||
* @param $user
|
||
* @return mixed
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function posterInfo(int $id, $user)
|
||
{
|
||
$pinkInfo = $this->dao->get($id);
|
||
/** @var StoreCombinationServices $combinationService */
|
||
$combinationService = app()->make(StoreCombinationServices::class);
|
||
$storeCombinationInfo = $combinationService->getOne(['id' => $pinkInfo['cid']], '*', ['getPrice']);
|
||
$data['title'] = $storeCombinationInfo['title'];
|
||
$data['url'] = '';
|
||
$data['image'] = $storeCombinationInfo['image'];
|
||
$data['price'] = $pinkInfo['price'];
|
||
$data['label'] = $pinkInfo['people'] . '人团';
|
||
if ($pinkInfo['k_id']) $pinkAll = $this->getPinkMember($pinkInfo['k_id']);
|
||
else $pinkAll = $this->getPinkMember($pinkInfo['id']);
|
||
$count = count($pinkAll);
|
||
$data['msg'] = '原价¥' . $storeCombinationInfo['product_price'] . ' 还差' . ($pinkInfo['people'] - $count) . '人拼团成功';
|
||
|
||
/** @var SystemAttachmentServices $systemAttachmentServices */
|
||
$systemAttachmentServices = app()->make(SystemAttachmentServices::class);
|
||
|
||
try {
|
||
$siteUrl = sys_config('site_url');
|
||
if (request()->isRoutine()) {
|
||
//小程序
|
||
$name = $id . '_' . $user['uid'] . '_' . $user['is_promoter'] . '_pink_share_routine.jpg';
|
||
$imageInfo = $systemAttachmentServices->getInfo(['name' => $name]);
|
||
if (!$imageInfo) {
|
||
$valueData = 'id=' . $id;
|
||
/** @var UserServices $userServices */
|
||
$userServices = app()->make(UserServices::class);
|
||
if ($userServices->checkUserPromoter((int)$user['uid'], $user)) {
|
||
$valueData .= '&pid=' . $user['uid'];
|
||
}
|
||
$res = MiniProgramService::appCodeUnlimitService($valueData, 'pages/activity/goods_combination_status/index', 280);
|
||
if (!$res) throw new ApiException(410167);
|
||
$uploadType = (int)sys_config('upload_type', 1);
|
||
$upload = UploadService::init();
|
||
$res = $upload->to('routine/activity/pink/code')->validate()->setAuthThumb(false)->stream($res, $name);
|
||
if ($res === false) {
|
||
throw new ApiException($upload->getError());
|
||
}
|
||
$imageInfo = $upload->getUploadInfo();
|
||
$imageInfo['image_type'] = $uploadType;
|
||
if ($imageInfo['image_type'] == 1) $remoteImage = PosterServices::remoteImage($siteUrl . $imageInfo['dir']);
|
||
else $remoteImage = PosterServices::remoteImage($imageInfo['dir']);
|
||
if (!$remoteImage['status']) throw new ApiException($remoteImage['msg']);
|
||
$systemAttachmentServices->save([
|
||
'name' => $imageInfo['name'],
|
||
'att_dir' => $imageInfo['dir'],
|
||
'satt_dir' => $imageInfo['thumb_path'],
|
||
'att_size' => $imageInfo['size'],
|
||
'att_type' => $imageInfo['type'],
|
||
'image_type' => $imageInfo['image_type'],
|
||
'module_type' => 2,
|
||
'time' => time(),
|
||
'pid' => 1,
|
||
'type' => 1
|
||
]);
|
||
$url = $imageInfo['dir'];
|
||
} else $url = $imageInfo['att_dir'];
|
||
$data['url'] = $url;
|
||
if ($imageInfo['image_type'] == 1)
|
||
$data['url'] = $siteUrl . $url;
|
||
} else {
|
||
if (sys_config('share_qrcode', 0) && request()->isWechat()) {
|
||
/** @var QrcodeServices $qrcodeService */
|
||
$qrcodeService = app()->make(QrcodeServices::class);
|
||
$data['url'] = $qrcodeService->getTemporaryQrcode('pink-' . $id, $user['uid'])->url;
|
||
}
|
||
}
|
||
} catch (\Throwable $e) {
|
||
}
|
||
return $data;
|
||
}
|
||
}
|