chore: 添加静态资源文件和版本配置文件
添加大量图片、字体、音频等静态资源文件,包括用户界面图片、模板文件和安装界面素材 添加系统版本配置文件(.version)和常量定义文件(.constant) 更新供应商依赖文件,包括Symfony VarDumper组件和相关许可证文件 添加验证码配置文件(captcha.php)和.gitignore规则
This commit is contained in:
496
app/services/order/OtherOrderServices.php
Normal file
496
app/services/order/OtherOrderServices.php
Normal file
@@ -0,0 +1,496 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\OtherOrderDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\statistic\TradeStatisticServices;
|
||||
use app\services\user\member\MemberShipServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class OtherOrderServices
|
||||
* @package app\services\order
|
||||
* @mixin OtherOrderDao
|
||||
*/
|
||||
class OtherOrderServices extends BaseServices
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 订单类型
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $type = [
|
||||
0 => '免费领取',
|
||||
1 => '购买会员卡',
|
||||
2 => '卡密激活',
|
||||
3 => '收银订单',
|
||||
4 => '赠送'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var OtherOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected OtherOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 生成会员购买订单数据
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function addOtherOrderData(array $data)
|
||||
{
|
||||
if (!$data) throw new ValidateException('数据不能为空');
|
||||
$add = [
|
||||
'uid' => $data['uid'],
|
||||
'store_id' => $data['store_id'] ?? 0,
|
||||
'staff_id' => $data['staff_id'] ?? 0,
|
||||
'type' => $data['type'] ?? 1,
|
||||
'order_id' => $data['order_id'],
|
||||
'channel_type' => $data['channel_type'],
|
||||
'pay_type' => $data['pay_type'] ?? 0,
|
||||
'member_type' => $data['member_type'] ?? 0,
|
||||
'member_price' => $data['member_price'] ?? 0.00,
|
||||
'pay_price' => $data['pay_price'] ?? 0.00,
|
||||
'code' => $data['member_code'] ?? '',
|
||||
'vip_day' => $data['vip_day'] ?? 0,
|
||||
'is_permanent' => $data['is_permanent'] ?? 0,
|
||||
'is_free' => $data['is_free'] ?? 0,
|
||||
'overdue_time' => $data['overdue_time'] ?? 0,
|
||||
'status' => 0,
|
||||
'paid' => $data['paid'] ?? 0,
|
||||
'pay_time' => $data['pay_time'] ?? 0,
|
||||
'money' => $data['money'] ?? 0,
|
||||
'add_time' => time(),
|
||||
];
|
||||
return $this->dao->save($add);
|
||||
}
|
||||
|
||||
/**
|
||||
* 能否领取免费
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function isCanGetFree(int $uid)
|
||||
{
|
||||
/** @var MemberShipServices $memberShipService */
|
||||
$memberShipService = app()->make(MemberShipServices::class);
|
||||
$freeDay = $memberShipService->getVipDay(['type' => "free"]);
|
||||
$freeConfig = [];
|
||||
$freeConfig['price'] = 0;
|
||||
$freeConfig['pre_price'] = 0;
|
||||
$freeConfig['title'] = "免费会员";
|
||||
$freeConfig['type'] = "free";
|
||||
$freeConfig['vip_day'] = $freeDay ? $freeDay : 0;
|
||||
$freeConfig['is_record'] = 0;
|
||||
$record = $this->dao->getOneByWhere(['uid' => $uid, 'is_free' => 1]);
|
||||
if ($record) {
|
||||
$freeConfig['is_record'] = 1;
|
||||
}
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$user = $userService->getUserCacheInfo($uid);
|
||||
$userInfo = [
|
||||
'uid' => $user['uid'],
|
||||
'nickname' => $user['nickname'],
|
||||
'avatar' => $user['avatar'],
|
||||
'phone' => $user['phone'],
|
||||
'now_money' => $user['now_money'],
|
||||
'is_ever_level' => $user['is_ever_level'],
|
||||
'is_money_level' => $user['is_money_level'],
|
||||
'overdue_time' => $user['overdue_time'],
|
||||
];
|
||||
/** @var TradeStatisticServices $tradeService */
|
||||
$tradeService = app()->make(TradeStatisticServices::class);
|
||||
$registerTime = $tradeService->TimeConvert(['start_time' => date('Y-m-d H:i:s', $user['add_time']), 'end_time' => date('Y-m-d H:i:s', time())]);
|
||||
$userInfo['register_days'] = $registerTime['days'];
|
||||
/** @var StoreOrderEconomizeServices $economizeService */
|
||||
$economizeService = app()->make(StoreOrderEconomizeServices::class);
|
||||
$userInfo['economize_money'] = $economizeService->sumEconomizeMoney($uid);
|
||||
$userInfo['shop_name'] = sys_config('site_name');
|
||||
$freeConfig['user_info'] = $userInfo;
|
||||
return $freeConfig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询会员卡订单数据
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOne(array $where, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne($where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
* @param int $uid
|
||||
* @param string $channelType 支付渠道
|
||||
* @param bool $memberType 会员卡类型
|
||||
* @param string $payPrice 支付金额
|
||||
* @param string $payType 支付方式
|
||||
* @param $type 订单类型
|
||||
* @param int $money
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function createOrder(int $uid, string $channelType, string $memberType, string $payPrice, string $payType, $type, $money = 0, int $store_id = 0, int $staff_id = 0)
|
||||
{
|
||||
/** @var StoreOrderCreateServices $storeOrderCreateService */
|
||||
$storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
|
||||
$orderInfo = [
|
||||
'uid' => $uid,
|
||||
'order_id' => $storeOrderCreateService->getNewOrderId('hy'),
|
||||
'pay_price' => $payPrice,
|
||||
'pay_type' => $payType,
|
||||
'channel_type' => $channelType,
|
||||
'member_code' => "",
|
||||
'store_id' => $store_id,
|
||||
'staff_id' => $staff_id,
|
||||
'overdue_time' => 0
|
||||
];
|
||||
if ($type != 3) { //区别 0:免费领取会员 1:购买会员 2:卡密领取会员 3:线下付款
|
||||
if (!$memberType) throw new ValidateException('memberType miss');
|
||||
[$memberPrice, $isFree, $isPermanent, $overdueTime, $newMemberRight] = $this->checkPayMemberType($uid, (int)$memberType);
|
||||
$orderInfo['member_price'] = $memberPrice;
|
||||
$orderInfo['money'] = $memberPrice;
|
||||
$orderInfo['vip_day'] = $newMemberRight['vip_day'];
|
||||
$orderInfo['member_type'] = $memberType;
|
||||
$orderInfo['overdue_time'] = $overdueTime;
|
||||
$orderInfo['is_permanent'] = $isPermanent;
|
||||
$orderInfo['is_free'] = $isFree;
|
||||
$orderInfo['type'] = $type;
|
||||
$changeType = "create_member_order";
|
||||
} else {
|
||||
$orderInfo['type'] = $type;
|
||||
$orderInfo['member_code'] = "";
|
||||
$changeType = "create_offline_scan_order";
|
||||
$orderInfo['money'] = $money ? $money : $payPrice;
|
||||
}
|
||||
$memberOrder = $this->addOtherOrderData($orderInfo);
|
||||
if (!$memberOrder) {
|
||||
throw new ValidateException('订单生成失败!');
|
||||
}
|
||||
/** @var OtherOrderStatusServices $statusService */
|
||||
$statusService = app()->make(OtherOrderStatusServices::class);
|
||||
$statusService->save([
|
||||
'oid' => $memberOrder['id'],
|
||||
'change_type' => $changeType,
|
||||
'change_message' => '订单生成',
|
||||
'change_time' => time(),
|
||||
'shop_type' => $type,
|
||||
]);
|
||||
return $memberOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 免费卡领取支付
|
||||
* @param $orderInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function zeroYuanPayment($orderInfo)
|
||||
{
|
||||
if ($orderInfo['paid']) {
|
||||
throw new ValidateException('该订单已支付!');
|
||||
}
|
||||
/** @var MemberShipServices $memberShipServices */
|
||||
$memberShipServices = app()->make(MemberShipServices::class);
|
||||
$member_type = $memberShipServices->value(['id' => $orderInfo['member_type']], 'type');
|
||||
if ($member_type != 'free') {
|
||||
throw new ValidateException('支付失败!');
|
||||
}
|
||||
$res = $this->paySuccess($orderInfo, 'yue');//余额支付成功
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员卡支付成功
|
||||
* @param array $orderInfo
|
||||
* @param string $paytype
|
||||
* @return bool
|
||||
*/
|
||||
public function paySuccess(array $orderInfo, string $paytype = PayServices::WEIXIN_PAY, array $other = [])
|
||||
{
|
||||
/** @var OtherOrderStatusServices $statusService */
|
||||
$statusService = app()->make(OtherOrderStatusServices::class);
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
/** @var MemberShipServices $memberShipServices */
|
||||
$memberShipServices = app()->make(MemberShipServices::class);
|
||||
$orderInfo['member_type'] = $memberShipServices->value(['id' => $orderInfo['member_type']], 'type');
|
||||
switch ($orderInfo['type']) {
|
||||
case 0 :
|
||||
case 1:
|
||||
case 2 :
|
||||
$res1 = $userServices->setMemberOverdueTime($orderInfo['vip_day'], $orderInfo['uid'], 1, $orderInfo['member_type']);
|
||||
break;
|
||||
case 3:
|
||||
$res1 = true;
|
||||
break;
|
||||
}
|
||||
// if ($paytype == PayServices::ALIPAY_PAY && isset($other['trade_no'])) {
|
||||
// $updata['trade_no'] = $other['trade_no'];
|
||||
// }
|
||||
$updata['trade_no'] = $other['trade_no'] ?? '';
|
||||
$updata['paid'] = 1;
|
||||
$updata['pay_type'] = $paytype;
|
||||
$updata['pay_time'] = time();
|
||||
$res2 = $this->dao->update($orderInfo['id'], $updata);
|
||||
$res3 = $statusService->save([
|
||||
'oid' => $orderInfo['id'],
|
||||
'change_type' => 'pay_success',
|
||||
'change_message' => '用户付款成功',
|
||||
'shop_type' => $orderInfo['type'],
|
||||
'change_time' => time()
|
||||
]);
|
||||
$orderInfo['pay_type'] = $paytype;
|
||||
$orderInfo['pay_time'] = time();
|
||||
|
||||
//支付成功后发送消息
|
||||
$orderInfo = $this->dao->get($orderInfo['id']);
|
||||
event('user.vipPay', [$orderInfo]);
|
||||
$res = $res1 && $res2 && $res3;
|
||||
return false !== $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param array $where
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(array $where, array $data)
|
||||
{
|
||||
return $this->dao->update($where, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买会员卡数据校验
|
||||
* @param int $uid
|
||||
* @param int $memberId
|
||||
* @param string $payPrice
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function checkPayMemberType(int $uid, int $memberId)
|
||||
{
|
||||
/** @var MemberShipServices $memberShipService */
|
||||
$memberShipService = app()->make(MemberShipServices::class);
|
||||
$memberInfo = $memberShipService->getMemberInfo($memberId);
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userInfo = $userService->get($uid);
|
||||
if ($userInfo['is_money_level'] > 0 && $userInfo['is_ever_level'] > 0) throw new ValidateException('您已是永久会员无需再购买!');
|
||||
$memberTypes = $memberInfo['type'] ?? '';
|
||||
$price = $memberInfo['pre_price'];
|
||||
if ($memberTypes == 'free' && $memberInfo['vip_day'] <= 0) throw new ValidateException('网络错误!');
|
||||
if ($userInfo['overdue_time'] > time()) {
|
||||
$time = $userInfo['overdue_time'];
|
||||
} else {
|
||||
$time = time();
|
||||
}
|
||||
switch ($memberTypes) {
|
||||
case "free"://免费会员
|
||||
$isCanGetFree = $this->isCanGetFree($uid);
|
||||
if ($isCanGetFree['is_record'] == 1) throw new ValidateException('您已经领取过免费会员!');
|
||||
$memberPrice = 0.00; //会员卡价格
|
||||
$isFree = 1;//代表免费
|
||||
$isPermanent = 0;//代表非永久
|
||||
$overdueTime = bcadd(bcmul(abs($memberInfo['vip_day']), "86400", 0), $time, 0);
|
||||
break;
|
||||
case "ever":
|
||||
$memberPrice = $price;
|
||||
$isFree = 0;
|
||||
$isPermanent = 1;
|
||||
$overdueTime = -1;
|
||||
break;
|
||||
default:
|
||||
$memberPrice = $price;
|
||||
$isFree = 0;
|
||||
$isPermanent = 0;
|
||||
$overdueTime = $memberShipService->getOverdueTime($uid, $memberId, $userInfo, $memberInfo);
|
||||
break;
|
||||
}
|
||||
return [$memberPrice, $isFree, $isPermanent, $overdueTime, $memberInfo];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据查询用户购买会员金额
|
||||
* @param array $where
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMemberMoneyByWhere(array $where, string $sumField, string $selectType, string $group = "")
|
||||
{
|
||||
switch ($selectType) {
|
||||
case "sum" :
|
||||
return $this->dao->getWhereSumField($where, $sumField);
|
||||
case "group" :
|
||||
return $this->dao->getGroupField($where, $sumField, $group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 线下收银列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getScanOrderList(array $where)
|
||||
{
|
||||
$where['type'] = 3;
|
||||
$where['paid'] = 1;
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
if ($where['add_time']) {
|
||||
[$startTime, $endTime] = explode('-', $where['add_time']);
|
||||
if ($startTime || $endTime) {
|
||||
$startTime = strtotime($startTime);
|
||||
$endTime = strtotime($endTime . ' 23:59:59');
|
||||
$where['add_time'] = [$startTime, $endTime];
|
||||
}
|
||||
}
|
||||
if ($where['name']) {
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userInfo = $userService->getUserInfoList(['nickname' => $where['name']], "uid");
|
||||
if ($userInfo) $where['uid'] = array_column($userInfo, 'uid');
|
||||
}
|
||||
$list = $this->dao->getScanOrderList($where, $page, $limit);
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
if ($list) {
|
||||
$userInfos = $userService->getColumn([['uid', 'IN', array_unique(array_column($list, 'uid'))]], 'uid,phone,nickname', 'uid');
|
||||
foreach ($list as &$v) {
|
||||
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
|
||||
$v['pay_time'] = $v['pay_time'] ? date('Y-m-d H:i:s', $v['pay_time']) : '';
|
||||
$v['phone'] = $userInfos[$v['uid']]['phone'] ?? '';
|
||||
$v['nickname'] = $userInfos[$v['uid']]['nickname'] ?? '';
|
||||
$v['pay_type'] = PayServices::PAY_TYPE[$v['pay_type']] ?? '其他方式';
|
||||
$v['true_price'] = bcsub($v['money'], $v['pay_price'], 2);
|
||||
}
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员记录
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getMemberRecord(array $where, int $limit = 0)
|
||||
{
|
||||
$where['type'] = [0, 1, 2, 4];
|
||||
if (isset($where['add_time']) && $where['add_time']) {
|
||||
$where['time'] = $where['add_time'];
|
||||
unset($where['add_time']);
|
||||
}
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$list = $this->dao->getMemberRecord($where, '*', ['user', 'staff'], $page, $limit);
|
||||
if ($list) {
|
||||
/** @var MemberShipServices $memberShipService */
|
||||
$memberShipService = app()->make(MemberShipServices::class);
|
||||
$shipInfo = $memberShipService->getColumn([], 'title,type', 'id');
|
||||
foreach ($list as &$v) {
|
||||
$v['overdue_time'] = $v['member_type'] == 'ever' || ($shipInfo[$v['member_type']]['type'] ?? '') == 'ever' ? '永久' : ($v['overdue_time'] ? date('Y-m-d H:i:s', $v['overdue_time']) : '');
|
||||
$v['vip_day'] = $v['member_type'] == 'ever' || ($shipInfo[$v['member_type']]['type'] ?? '') == 'ever' ? '永久' : $v['vip_day'];
|
||||
// 如果$v['member_type']不是数字
|
||||
if (!is_numeric($v['member_type'])) {
|
||||
if ($v['member_type'] == 'admin') $v['member_type'] = '赠送';
|
||||
if ($v['member_type'] == 'card') $v['member_type'] = '卡密兑换';
|
||||
} else {
|
||||
$v['member_type'] = $shipInfo[$v['member_type']]['title'] ?? '';
|
||||
}
|
||||
$v['pay_time'] = $v['pay_time'] ? date('Y-m-d H:i:s', $v['pay_time']) : '';
|
||||
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
|
||||
switch ($v['pay_type']) {
|
||||
case "yue" :
|
||||
$v['pay_type'] = "余额";
|
||||
break;
|
||||
case "weixin" :
|
||||
$v['pay_type'] = "微信";
|
||||
break;
|
||||
case "alipay" :
|
||||
$v['pay_type'] = "支付宝";
|
||||
break;
|
||||
case "admin" :
|
||||
$v['pay_type'] = "后台赠送";
|
||||
break;
|
||||
}
|
||||
if ($v['type'] == 0) $v['pay_type'] = "免费领取";
|
||||
if ($v['type'] == 2) {
|
||||
$v['pay_type'] = "卡密领取";
|
||||
$v['member_type'] = "卡密激活";
|
||||
}
|
||||
if ($v['type'] == 1 && $v['is_free'] == 1) $v['pay_type'] = "免费领取";
|
||||
$v['user']['overdue_time'] = isset($v['user']['overdue_time']) ? (date('Y-m-d', $v['user']['overdue_time']) == "1970-01-01" ? "" : date('Y-m-d H:i:s', $v['user']['overdue_time'])) : '';
|
||||
}
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店付费会员统计详情列表
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param array $time
|
||||
* @return array|array[]
|
||||
*/
|
||||
public function time(int $store_id, int $staff_id, array $time = [])
|
||||
{
|
||||
if (!$time) {
|
||||
return [[], []];
|
||||
}
|
||||
[$start, $stop, $front, $front_stop] = $time;
|
||||
$where = ['store_id' => $store_id, 'paid' => 1, 'type' => [0, 1, 2, 4]];
|
||||
if ($staff_id) {
|
||||
$where['staff_id'] = $staff_id;
|
||||
}
|
||||
$frontPrice = $this->dao->sum($where + ['time' => [$front, $front_stop]], 'pay_price', true);
|
||||
$nowPrice = $this->dao->sum($where + ['time' => [$start, $stop]], 'pay_price', true);
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getMemberRecord($where + ['time' => [$start, $stop]], 'id,order_id,uid,pay_price,add_time', ['userInfo'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
return [[$nowPrice, $frontPrice], $list];
|
||||
}
|
||||
|
||||
}
|
||||
44
app/services/order/OtherOrderStatusServices.php
Normal file
44
app/services/order/OtherOrderStatusServices.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\OtherOrderStatusDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class OtherOrderStatusServices
|
||||
* @package app\services\order
|
||||
* @mixin OtherOrderStatusDao
|
||||
*/
|
||||
class OtherOrderStatusServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var OtherOrderStatusDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected OtherOrderStatusDao $dao;
|
||||
|
||||
/**
|
||||
* 获取订单状态列表
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getStatusList(int $id)
|
||||
{
|
||||
return $this->dao->getStatusList(['oid' => $id], 0, 0);
|
||||
}
|
||||
}
|
||||
1293
app/services/order/StoreCartServices.php
Normal file
1293
app/services/order/StoreCartServices.php
Normal file
File diff suppressed because it is too large
Load Diff
694
app/services/order/StoreDeliveryOrderServices.php
Normal file
694
app/services/order/StoreDeliveryOrderServices.php
Normal file
@@ -0,0 +1,694 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreDeliveryOrderDao;
|
||||
use app\jobs\order\OrderStatusJob;
|
||||
use app\jobs\order\OrderTakeJob;
|
||||
use app\services\BaseServices;
|
||||
use app\services\other\CityAreaServices;
|
||||
use app\services\store\SystemStoreServices;
|
||||
use app\services\supplier\SystemSupplierServices;
|
||||
use crmeb\services\DeliverySevices;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use crmeb\traits\OptionTrait;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Log;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 发货单
|
||||
* Class StoreDeliveryOrderServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreDeliveryOrderDao
|
||||
*/
|
||||
class StoreDeliveryOrderServices extends BaseServices
|
||||
{
|
||||
use OptionTrait;
|
||||
|
||||
protected array $statusData = [
|
||||
2 => '待取货',
|
||||
3 => '配送中',
|
||||
4 => '已完成',
|
||||
-1 => '已取消',
|
||||
9 => '物品返回中',
|
||||
10 => '物品返回完成',
|
||||
100 => '骑士到店',
|
||||
];
|
||||
|
||||
/**
|
||||
* 平台达达门店
|
||||
* @var string
|
||||
*/
|
||||
public string $platCityShopId = 'plat_delivery_city_shop_001';
|
||||
|
||||
/**
|
||||
* @var StoreDeliveryOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreDeliveryOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 配送信息
|
||||
* @return string[]
|
||||
*/
|
||||
public function getStatusMsg()
|
||||
{
|
||||
return $this->statusData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, '*', $page, $limit, ['orderInfo', 'storeInfo']);
|
||||
$count = $this->dao->count();
|
||||
if ($list) {
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s') : '';
|
||||
$item['distance'] = $item['distance'] ? bcdiv($item['distance'], '1000', 3) : 0;
|
||||
}
|
||||
}
|
||||
return compact('count', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单号
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getOrderSn(string $key = '')
|
||||
{
|
||||
[$msec, $sec] = explode(' ', microtime());
|
||||
$msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
|
||||
$orderId = $key . $msectime . random_int(10000, max(intval($msec * 10000) + 10000, 98369));
|
||||
return $orderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 地址转经纬度
|
||||
* @param $region
|
||||
* @param $address
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function lbs_address($region, $address)
|
||||
{
|
||||
$key = sys_config('tengxun_map_key', '');
|
||||
if (!$key) {
|
||||
throw new ValidateException('请先配置地图KEY');
|
||||
}
|
||||
$locationOption = new \Joypack\Tencent\Map\Bundle\AddressOption($key);
|
||||
$locationOption->setAddress($region . $address);
|
||||
// $locationOption->setRegion($region);
|
||||
$location = new \Joypack\Tencent\Map\Bundle\Address($locationOption);
|
||||
$res = $location->request();
|
||||
if ($res->error) {
|
||||
throw new ValidateException($res->error);
|
||||
}
|
||||
if ($res->status) {
|
||||
throw new ValidateException($res->message);
|
||||
}
|
||||
if (!$res->result) {
|
||||
throw new ValidateException('获取失败');
|
||||
}
|
||||
return $res->result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理订单数据
|
||||
* @param array $station
|
||||
* @param array $order
|
||||
* @param int $type
|
||||
* @return array
|
||||
*/
|
||||
public function getPriceParams(array $station, array $order, int $type)
|
||||
{
|
||||
$data = [];
|
||||
$type = (int)$type;
|
||||
|
||||
switch ($type) {
|
||||
case 1:
|
||||
$city = DeliverySevices::init(DeliverySevices::DELIVERY_TYPE_DADA)->getCity([]);
|
||||
$res = [];
|
||||
foreach ($city as $item) {
|
||||
$res[$item['label']] = $item['key'];
|
||||
}
|
||||
//达达城市数据:西安
|
||||
$city_name = str_replace(['市', '自治州', '地区', '区划', '县'], '', $station['city_name'] ?? '');
|
||||
$data = [
|
||||
'shop_no' => $station['origin_shop_id'],
|
||||
'city_code' => $res[$city_name],
|
||||
'cargo_price' => $order['pay_price'],
|
||||
'is_prepay' => 0,
|
||||
'receiver_name' => $order['real_name'],
|
||||
'receiver_address' => $order['user_address'],
|
||||
'cargo_weight' => 0,
|
||||
'receiver_phone' => $order['user_phone'],
|
||||
'is_finish_code_needed' => 1,
|
||||
];
|
||||
break;
|
||||
case 2://uu城市数据:西安市
|
||||
$business = DeliverySevices::init(DeliverySevices::DELIVERY_TYPE_UU)->getBusiness();
|
||||
$business = array_combine(array_column($business, 'key'), $business);
|
||||
$data = [
|
||||
'from_address' => $station['station_address'],
|
||||
'to_address' => $order['user_address'],
|
||||
'city_name' => $station['city_name'] ?? '西安',
|
||||
'goods_type' => $business[$station['business'] ?? 1]['label'],
|
||||
'send_type' => '0',
|
||||
'to_lat' => $order['latitude'],
|
||||
'to_lng' => $order['longitude'],
|
||||
'from_lat' => $station['lat'],
|
||||
'from_lng' => $station['lng'],
|
||||
];
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建配送单
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $type
|
||||
* @param $order
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function create(int $id, array $data, int $type = 1, $order = [])
|
||||
{
|
||||
if (!$order) {
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$order = $orderServices->get($id);
|
||||
}
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单信息获取失败');
|
||||
}
|
||||
if (isset($order['user_address']) && !$order['user_address']) {
|
||||
throw new ValidateException('自提订单不支持同城配送');
|
||||
}
|
||||
$order = is_object($order) ? $order->toArray() : $order;
|
||||
//处理地址定位
|
||||
if (isset($order['user_location']) && $order['user_location']) {
|
||||
[$longitude, $latitude] = explode(' ', $order['user_location']);
|
||||
$order['longitude'] = $longitude;
|
||||
$order['latitude'] = $latitude;
|
||||
if (!$order['longitude'] || !$order['latitude']) {
|
||||
$addressArr = $this->addressHandle($order['user_address']);
|
||||
$city_name = $addressArr['city'] ?? '';
|
||||
try {
|
||||
$addres = $this->lbs_address($city_name, $order['user_address']);
|
||||
$order['latitude'] = $addres['location']['lat'] ?? '';
|
||||
$order['longitude'] = $addres['location']['lng'] ?? '';
|
||||
} catch (\Exception $e) {
|
||||
throw new ValidateException('获取经纬度失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($order['store_id']) {//门店
|
||||
$resType = 1;
|
||||
$relationId = (int)$order['store_id'];
|
||||
} elseif ($order['supplier_id']) {//供应商
|
||||
$resType = 2;
|
||||
$relationId = (int)$order['supplier_id'];
|
||||
} else {//平台信息
|
||||
$resType = 0;
|
||||
$relationId = 0;
|
||||
}
|
||||
//获取发货信息
|
||||
$station = $this->syncCityShop($relationId, $resType, $type);
|
||||
if (!$station || !isset($station['lat']) || !$station['lat'] || !isset($station['lng']) || !$station['lng']) {
|
||||
throw new ValidateException('获取发货信息失败');
|
||||
}
|
||||
$getPriceParams = $this->getPriceParams($station, $order, $type);
|
||||
$orderSn = $this->getOrderSn($type == 1 ? 'dd' : 'uu');
|
||||
$getPriceParams['origin_id'] = $orderSn;
|
||||
$getPriceParams['cargo_weight'] = $data['cargo_weight'] ?? '';
|
||||
|
||||
$service = DeliverySevices::init($type);
|
||||
try {
|
||||
//计算价格
|
||||
$priceData = $service->getOrderPrice($getPriceParams);
|
||||
if ($type == DeliverySevices::DELIVERY_TYPE_UU) { //uu
|
||||
$priceData['receiver'] = $order['real_name'];
|
||||
$priceData['receiver_phone'] = $order['user_phone'];
|
||||
$priceData['note'] = $data['delivery_remark'] ?? '';
|
||||
$priceData['push_type'] = 2;
|
||||
$priceData['special_type'] = $data['special_type'] ?? 0;
|
||||
}
|
||||
|
||||
$res = $service->addOrder($priceData);
|
||||
$ret = [
|
||||
'type' => $resType,
|
||||
'relation_id' => $relationId,
|
||||
'oid' => $id,
|
||||
'order_id' => $orderSn,
|
||||
'delivery_no' => $type == 2 ? $res['ordercode'] : $priceData['deliveryNo'] ?? '',
|
||||
'city_code' => $station['city_name'] ?? '西安',
|
||||
'receiver_phone' => $order['user_phone'],
|
||||
'user_name' => $order['real_name'],
|
||||
'from_address' => $station['station_address'] ?? '',
|
||||
'to_address' => $order['user_address'],
|
||||
'info' => $data['delivery_remark'] ?? '',
|
||||
'status' => 0,
|
||||
'station_type' => $type,
|
||||
'to_lat' => $order['latitude'],
|
||||
'to_lng' => $order['longitude'],
|
||||
'from_lat' => $station['lat'] ?? '',
|
||||
'from_lng' => $station['lng'] ?? '',
|
||||
'distance' => $priceData['distance'],
|
||||
'fee' => $priceData['fee'] ?? $priceData['need_paymoney'] ?? 0,
|
||||
'mark' => $data['delivery_remark'] ?? '',
|
||||
'uid' => $order['uid'],
|
||||
'add_time' => time()
|
||||
];
|
||||
//入库操作
|
||||
$this->dao->save($ret);
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
if (isset($res['status']) && $res['status'] == 'success') {
|
||||
$error['origin_id'] = $orderSn;
|
||||
$error['reason'] = $type == 1 ? 36 : '信息错误';
|
||||
$error['delivery_no'] = $type == 2 ? $res['ordercode'] : $priceData['deliveryNo'];
|
||||
$service->cancelOrder($error);
|
||||
}
|
||||
throw new ValidateException($e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 配送订单详情
|
||||
* @param int $id
|
||||
* @return array|\think\Model
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function detail(int $id)
|
||||
{
|
||||
$res = $this->dao->get($id, ['orderInfo']);
|
||||
if (!$res) {
|
||||
throw new ValidateException('配送订单不存在,或已取消');
|
||||
}
|
||||
$res = $res->toArray();
|
||||
$order = DeliverySevices::init((int)$res['station_type'])->getOrderDetail($res);
|
||||
if (!$res) throw new ValidateException('订单不存在');
|
||||
$res['data'] = [
|
||||
'order_id' => $order['order_code'],
|
||||
'to_address' => $order['to_address'],
|
||||
'from_address' => $order['from_address'],
|
||||
'state' => $order['state'],
|
||||
'note' => $order['note'],
|
||||
'order_price' => $order['order_price'],
|
||||
'distance' => round(($order['distance'] / 1000), 2) . ' km',
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单获取配送信息
|
||||
* @param int $oid
|
||||
* @return array|string[]
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/12/25 下午4:54
|
||||
*/
|
||||
public function orderDetail(int $oid)
|
||||
{
|
||||
// 获取订单数据
|
||||
$res = $this->dao->get(['oid' => $oid]);
|
||||
if (!$res) {
|
||||
return [
|
||||
'status_name' => '',
|
||||
'porter_name' => '',
|
||||
'porter_phone' => ''
|
||||
];
|
||||
}
|
||||
// 获取派送服务实例
|
||||
$order = DeliverySevices::init((int)$res['station_type'])->getOrderDetail($res);
|
||||
return [
|
||||
'status_name' => $order['status_name'] ?? '',
|
||||
'porter_name' => $order['porter_name'] ?? '',
|
||||
'porter_phone' => $order['porter_phone'] ?? ''
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(int $id)
|
||||
{
|
||||
$res = $this->dao->get($id);
|
||||
if (!$res) throw new ValidateException('订单不存在');
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function cancelForm($id)
|
||||
{
|
||||
$order = $this->dao->get($id);
|
||||
if (!$order) throw new ValidateException('订单不存在');
|
||||
if ($order['status'] == -1) throw new ValidateException('订单已取消,无法操作');
|
||||
$field = [];
|
||||
if ($order['station_type'] == 1) {
|
||||
$options = DeliverySevices::init(1)->reasons();
|
||||
$field[] = Form::select('reason', '取消原因')->setOptions(Form::setOptions($options))->filterable(1)->col(12);
|
||||
$field[] = Form::input('cancel_reason', '其他原因说明')->required('请输入原因');
|
||||
} else {
|
||||
$field[] = Form::input('reason', '取消原因')->required('请输入原因');
|
||||
}
|
||||
return create_form('取消同城配送订单', $field, Url::buildUrl('/order/delivery_order/cancel/' . $id), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* @param int $id
|
||||
* @param array $reason
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function cancel(int $id, array $reason)
|
||||
{
|
||||
$order = $this->dao->get($id);
|
||||
if (!$order) throw new ValidateException('配送订单不存在');
|
||||
if ($order['status'] == -1) throw new ValidateException('请勿重复操作');
|
||||
$data = [
|
||||
'origin_id' => $order['order_id'],
|
||||
'order_code' => $order['delivery_no'],
|
||||
'reason' => $reason['reason'],
|
||||
'cancel_reason' => $reason['cancel_reason'],
|
||||
];
|
||||
$this->transaction(function () use ($id, $order, $data) {
|
||||
$mark = $data['reason'];
|
||||
$delivery = DeliverySevices::init((int)$order['station_type']);
|
||||
if ($order['station_type'] == DeliverySevices::DELIVERY_TYPE_DADA) {
|
||||
$options = $delivery->reasons();
|
||||
if ($options) $options = array_combine(array_column($options, 'value'), $options);
|
||||
$mark = $options[$data['reason']]['label'] ?? '';
|
||||
}
|
||||
if ($data['cancel_reason']) $mark .= ',' . $data['cancel_reason'];
|
||||
$res = $delivery->cancelOrder($data);
|
||||
$deduct_fee = $res['deduct_fee'] ?? 0;
|
||||
$this->doCancel($id, $order, $deduct_fee, $mark);
|
||||
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行取消订单
|
||||
* @param int $id
|
||||
* @param $deliveryOrder
|
||||
* @param $deduct_fee
|
||||
* @param $mark
|
||||
* @return bool
|
||||
*/
|
||||
public function doCancel(int $id, $deliveryOrder, $deduct_fee, $mark)
|
||||
{
|
||||
//修改配送单
|
||||
$this->dao->update($id, ['status' => 1, 'mark' => $mark, 'deduct_fee' => $deduct_fee]);
|
||||
//修改愿订单
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$storeOrderServices->update($deliveryOrder['oid'], ['status' => 0, 'delivery_type' => '', 'delivery_name' => '', 'delivery_id' => '', 'delivery_uid' => '']);
|
||||
//记录订单状态
|
||||
OrderStatusJob::dispatch([$deliveryOrder['oid'], 'city_delivery_cancel', ['change_message' => '同城配送取消', 'change_manager_id' => request()->adminId(), 'change_manager_type' => 'admin']]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO 回调
|
||||
* @param $data
|
||||
* @author Qinii
|
||||
* @day 2/17/22
|
||||
*/
|
||||
public function notify($data)
|
||||
{
|
||||
//达达
|
||||
/**
|
||||
* 订单状态(待接单=1,待取货=2,配送中=3,已完成=4,已取消=5, 指派单=8,妥投异常之物品返回中=9, 妥投异常之物品返回完成=10, 骑士到店=100,创建达达运单失败=1000 可参考文末的状态说明)
|
||||
*/
|
||||
Log::info('同城回调参数:' . var_export(['=======', $data, '======='], 1));
|
||||
if (isset($data['data'])) {
|
||||
$data = json_decode($data['data'], 1);
|
||||
}
|
||||
|
||||
$reason = '';
|
||||
$deductFee = 0;
|
||||
$delivery = [];
|
||||
if (isset($data['order_status'])) {
|
||||
$order_id = $data['order_id'];
|
||||
if ($data['order_status'] == 1) {
|
||||
$orderData = $this->dao->getOne(['order_id' => $data['order_id']]);
|
||||
if (!$orderData['finish_code']) {
|
||||
$orderData->finish_code = $data['finish_code'];
|
||||
$orderData->save();
|
||||
}
|
||||
return;
|
||||
} else if (in_array($data['order_status'], [2, 3, 4, 5, 9, 10, 100])) {
|
||||
$status = $data['order_status'];
|
||||
if ($data['order_status'] == 5) {
|
||||
$msg = [
|
||||
'取消:',
|
||||
'达达配送员取消:',
|
||||
'商家主动取消:',
|
||||
'系统或客服取消:',
|
||||
];
|
||||
//1:达达配送员取消;2:商家主动取消;3:系统或客服取消;0:默认值
|
||||
$status = -1;
|
||||
$reason = $msg[$data['cancel_from']] . $data['cancel_reason'];
|
||||
}
|
||||
$deductFee = $data['deductFee'] ?? 0;
|
||||
if (isset($data['dm_name']) && $data['dm_name']) {
|
||||
$delivery = [
|
||||
'delivery_name' => $data['dm_name'],
|
||||
'delivery_id' => $data['dm_mobile'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
} else if (isset($data['state'])) { //uu
|
||||
if (!$data['origin_id']) $deliveryOrder = $this->dao->getOne(['delivery_no' => $data['order_code']]);
|
||||
$order_id = $data['origin_id'] ?: $deliveryOrder['order_id'];
|
||||
//当前状态 1下单成功 3跑男抢单 4已到达 5已取件 6到达目的地 10收件人已收货 -1订单取消
|
||||
switch ($data['state']) {
|
||||
case 3:
|
||||
$status = 2;
|
||||
break;
|
||||
case 4:
|
||||
$status = 100;
|
||||
break;
|
||||
case 5:
|
||||
$status = 3;
|
||||
break;
|
||||
case 10:
|
||||
$status = 4;
|
||||
break;
|
||||
case -1:
|
||||
$status = -1;
|
||||
$reason = $data['state_text'];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isset($data['driver_name']) && $data['driver_name']) {
|
||||
$delivery = [
|
||||
'delivery_name' => $data['driver_name'],
|
||||
'delivery_id' => $data['driver_mobile'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($order_id) && isset($status)) {
|
||||
$deliveryOrder = $this->dao->getOne(['order_id' => $order_id]);
|
||||
if ($deliveryOrder) {
|
||||
$this->notifyAfter($status, $reason, $deliveryOrder, $delivery, $deductFee);
|
||||
} else {
|
||||
Log::info('同城配送回调,未查询到订单:' . $order_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $status
|
||||
* @param $reason
|
||||
* @param $res
|
||||
* @param $data
|
||||
* @param $deductFee
|
||||
* @return bool
|
||||
*/
|
||||
public function notifyAfter($status, $reason, $deliveryOrder, $data, $deductFee)
|
||||
{
|
||||
if (!isset($this->statusData[$status])) return true;
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$orderData = $orderServices->get($deliveryOrder['oid']);
|
||||
/** @var StoreOrderStatusServices $statusServices */
|
||||
$statusServices = app()->make(StoreOrderStatusServices::class);
|
||||
$change_type = 'city_delivery_' . $status;
|
||||
$oid = (int)$deliveryOrder['oid'];
|
||||
if ($orderData['status'] != $status && !$statusServices->count(['oid' => $oid, 'change_type' => $change_type])) {
|
||||
|
||||
$order = $orderServices->get($oid);
|
||||
//修改配送单
|
||||
$this->dao->update($deliveryOrder['id'], ['status' => $status, 'reason' => $reason]);
|
||||
//增加
|
||||
$message = '订单已配送【' . $this->statusData[$status] . '】';
|
||||
//记录原订单状态
|
||||
OrderStatusJob::dispatch([$oid, $change_type, ['change_message' => $message, 'change_manager_type' => 'system']]);
|
||||
switch ($status) {
|
||||
case 2:
|
||||
if (!empty($data)) $orderServices->update($oid, $data);
|
||||
break;
|
||||
case 4:
|
||||
//订单收货
|
||||
if ($order['status'] != 2) {
|
||||
OrderTakeJob::dispatch([$order]);
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
$this->doCancel((int)$deliveryOrder['id'], $deliveryOrder, $deductFee, $reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步达达门店信息
|
||||
* @param int $id
|
||||
* @param bool $is_new
|
||||
* @param int $type
|
||||
* @param int $station_type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function syncCityShop(int $id, int $type = 1, int $station_type = 1)
|
||||
{
|
||||
$data = [];
|
||||
if ($station_type == 1) {
|
||||
$status = sys_config('dada_delivery_status');
|
||||
} else {
|
||||
$status = sys_config('uu_delivery_status');
|
||||
}
|
||||
if (!$status) {//未开启
|
||||
return $data;
|
||||
}
|
||||
if ($type == 1) {//门店
|
||||
/** @var SystemStoreServices $storeServices */
|
||||
$storeServices = app()->make(SystemStoreServices::class);
|
||||
$station = $storeServices->getStoreInfo($id);
|
||||
/** @var CityAreaServices $cityArea */
|
||||
$cityArea = app()->make(CityAreaServices::class);
|
||||
$station['city_name'] = $cityArea->value(['id' => $station['city']], 'name');
|
||||
$station['address'] = $station['detailed_address'];
|
||||
if (!$station['city_shop_id']) {
|
||||
$station['city_shop_id'] = 'deliver_store_' . $station['id'] . '_' . $this->getOrderSn();
|
||||
$storeServices->update($id, ['city_shop_id' => $station['city_shop_id']]);
|
||||
}
|
||||
} elseif ($type == 2) {//供应商
|
||||
/** @var SystemSupplierServices $services */
|
||||
$services = app()->make(SystemSupplierServices::class);
|
||||
$station = $services->getSupplierInfo($id);
|
||||
if ($station) {
|
||||
$station['name'] = $station['supplier_name'] ?? '';
|
||||
}
|
||||
} else {//平台
|
||||
$station = SystemConfigService::more(['refund_address', 'refund_name', 'refund_phone']);
|
||||
$address = $station['refund_address'];
|
||||
if ($address) {
|
||||
$station['address'] = $station['refund_address'];
|
||||
$station['name'] = $station['refund_name'];
|
||||
$station['phone'] = $station['refund_phone'];
|
||||
$station['city_shop_id'] = $this->platCityShopId;
|
||||
}
|
||||
}
|
||||
if (!isset($station['latitude'])) {//地址转经纬度
|
||||
if (!isset($station['address'])) {
|
||||
throw new ValidateException($type == 0 ? '请检查(设置->商城设置->交易设置->退货收货人地址)完整性' : '请检查该订单关联供应商地址信息是否正确');
|
||||
}
|
||||
$addressArr = $this->addressHandle($station['address']);
|
||||
if (!$addressArr['province'] || !$addressArr['city']) {
|
||||
throw new ValidateException($type == 0 ? '退货收货地址格错误,应包含完整的省市地址' : '请检查该订单关联供应商地址信息是否正确');
|
||||
}
|
||||
$station['city_name'] = $addressArr['city'] ?? '';
|
||||
try {
|
||||
$addres = $this->lbs_address($station['city_name'], $station['address']);
|
||||
$station['latitude'] = $addres['location']['lat'] ?? '';
|
||||
$station['longitude'] = $addres['location']['lng'] ?? '';
|
||||
} catch (\Exception $e) {
|
||||
throw new ValidateException('获取经纬度失败');
|
||||
}
|
||||
}
|
||||
$data = [
|
||||
'lng' => (float)($station['longitude'] ?? 0),
|
||||
'lat' => (float)($station['latitude'] ?? 0),
|
||||
'phone' => $station['phone'] ?? '',
|
||||
'business' => (int)($station['business'] ?? 5),
|
||||
'contact_name' => $station['name'] ?? '',
|
||||
'station_name' => $station['name'],
|
||||
'station_address' => $station['address'] ?? '',
|
||||
'status' => 1,
|
||||
'origin_shop_id' => $station['city_shop_id'],
|
||||
];
|
||||
if ($data) {
|
||||
$serve = DeliverySevices::init($station_type);
|
||||
try {
|
||||
$shop = $serve->getShopDetail($data['origin_shop_id']);
|
||||
} catch (\Throwable $e) {
|
||||
$shop = [];
|
||||
}
|
||||
try {
|
||||
if (!$shop) {
|
||||
$serve->addShop($data);
|
||||
} else {
|
||||
$serve->updateShop($data);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
throw new ValidateException('创建达达门店失败,原因:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$data['city_name'] = $station['city_name'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
403
app/services/order/StoreOrderCartInfoServices.php
Normal file
403
app/services/order/StoreOrderCartInfoServices.php
Normal file
@@ -0,0 +1,403 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
use app\dao\order\StoreOrderCartInfoDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use crmeb\traits\OptionTrait;
|
||||
use crmeb\utils\Arr;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class StoreOrderCartInfoServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderCartInfoDao
|
||||
*/
|
||||
class StoreOrderCartInfoServices extends BaseServices
|
||||
{
|
||||
use OptionTrait;
|
||||
|
||||
/**
|
||||
* @var StoreOrderCartInfoDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderCartInfoDao $dao;
|
||||
|
||||
/**
|
||||
* 检测订单商品是否核销完
|
||||
* @param int $oid
|
||||
* @return bool
|
||||
*/
|
||||
public function checkWriteOff(int $oid): bool
|
||||
{
|
||||
return !$this->dao->count(['oid' => $oid, 'is_writeoff' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空订单商品缓存
|
||||
* @param int $oid
|
||||
* @return bool
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function clearOrderCartInfo(int $oid)
|
||||
{
|
||||
return CacheService::delete(md5('store_order_cart_info_' . $oid));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定订单下的商品详情
|
||||
* @param int $oid
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getOrderCartInfo(int $oid)
|
||||
{
|
||||
$key = md5('store_order_cart_info_' . $oid);
|
||||
return $this->dao->cacheTag()->remember($key, function () use ($oid) {
|
||||
$cart_info = $this->dao->getCartColunm(['oid' => $oid], 'cart_info', 'cart_id');
|
||||
$info = [];
|
||||
foreach ($cart_info as $k => $v) {
|
||||
$_info = is_string($v) ? json_decode($v, true) : $v;
|
||||
if (!isset($_info['productInfo'])) $_info['productInfo'] = [];
|
||||
//缩略图处理
|
||||
if (isset($_info['productInfo']['attrInfo'])) {
|
||||
$_info['productInfo']['attrInfo'] = get_thumb_water($_info['productInfo']['attrInfo']);
|
||||
}
|
||||
$_info['product_type'] = $_info['productInfo']['product_type'] ?? 0;
|
||||
$_info['supplier_id'] = $_info['productInfo']['supplier_id'] ?? 0;
|
||||
$_info['is_support_refund'] = $_info['productInfo']['is_support_refund'] ?? 1;
|
||||
$_info['store_name'] = $_info['store_name'] ?? $_info['title'] ?? '';
|
||||
$_info['productInfo'] = get_thumb_water($_info['productInfo']);
|
||||
$_info['refund_num'] = $this->dao->sum(['cart_id' => $_info['id']], 'refund_num');
|
||||
$info[$k]['cart_info'] = $_info;
|
||||
unset($_info);
|
||||
}
|
||||
return $info;
|
||||
}, 7 * 24 * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定订单下的商品详情 供应商
|
||||
* @param int $oid
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderCartInfoSettlePrice(int $oid)
|
||||
{
|
||||
$cart_info = $this->dao->getCartColunm(['oid' => $oid], 'cart_num,refund_num,cart_info', 'id');
|
||||
$settlePrice = 0;
|
||||
$refundSettlePrice = 0;
|
||||
foreach ($cart_info as $k => &$v) {
|
||||
$_info = is_string($v['cart_info']) ? json_decode($v['cart_info'], true) : $v['cart_info'];
|
||||
$v['cart_info'] = $_info;
|
||||
if (!isset($_info['productInfo'])) $_info['productInfo'] = [];
|
||||
$settle_price = $_info['productInfo']['attrInfo']['settle_price'] ?? 0;
|
||||
$_info['settlePrice'] = bcmul((string)$settle_price, (string)$v['cart_num'], 2); //购买结算价格
|
||||
$settlePrice = bcadd($_info['settlePrice'], $settlePrice, 2);
|
||||
$_info['refundSettlePrice'] = bcmul((string)$settle_price, (string)$v['cart_num'], 2);//退款结算价格
|
||||
$refundSettlePrice = bcadd($_info['refundSettlePrice'], $refundSettlePrice, 2);
|
||||
}
|
||||
return ['settlePrice' => $settlePrice, 'refundSettlePrice' => $refundSettlePrice, 'info' => $cart_info];
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找购物车里的所有商品标题
|
||||
* @param int $oid
|
||||
* @param false $goodsNum
|
||||
* @return bool|mixed|string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getCarIdByProductTitle(int $oid, bool $goodsNum = false)
|
||||
{
|
||||
$key = md5('store_order_cart_product_title_' . ($goodsNum ? 1 : 0) . '_' . $oid);
|
||||
$title = CacheService::get($key);
|
||||
if (!$title) {
|
||||
$orderCart = $this->dao->getCartInfoList(['oid' => $oid], ['cart_info']);
|
||||
foreach ($orderCart as $item) {
|
||||
if (isset($item['cart_info']['productInfo']['store_name'])) {
|
||||
if ($goodsNum && isset($item['cart_info']['cart_num'])) {
|
||||
$title .= $item['cart_info']['productInfo']['store_name'] . ' * ' . $item['cart_info']['cart_num'] . ' | '.$item['cart_info']['productInfo']['attrInfo']['suk']. ' |';
|
||||
} else {
|
||||
$title .= $item['cart_info']['productInfo']['store_name'] . '|';
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($title) {
|
||||
$title = substr($title, 0, strlen($title) - 1);
|
||||
}
|
||||
CacheService::set($key, $title, 7 * 24 * 3600);
|
||||
}
|
||||
return $title ? $title : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取打印订单的商品信息
|
||||
* @param int $oid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getCartInfoPrintProduct(int $oid)
|
||||
{
|
||||
$cartInfo = $this->dao->getCartInfoList(['oid' => $oid], ['is_gift', 'cart_info']);
|
||||
$product = [];
|
||||
foreach ($cartInfo as $item) {
|
||||
$value = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
$value['productInfo']['store_name'] = $value['productInfo']['store_name'] ?? "";
|
||||
$value['productInfo']['store_name'] = substrUTf8($value['productInfo']['store_name'], 10, 'UTF-8', '');
|
||||
$value['is_gift'] = $item['is_gift'];
|
||||
$product[] = $value;
|
||||
}
|
||||
return $product;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存购物车info
|
||||
* @param $oid
|
||||
* @param array $cartInfo
|
||||
* @param $uid
|
||||
* @param array $promotions
|
||||
* @return int
|
||||
*/
|
||||
public function setCartInfo($oid, array $cartInfo, $uid, array $promotions = [])
|
||||
{
|
||||
$group = [];
|
||||
foreach ($cartInfo as $cart) {
|
||||
$group[] = [
|
||||
'oid' => $oid,
|
||||
'uid' => $uid,
|
||||
'cart_id' => $cart['id'],
|
||||
'type' => $cart['type'] == 5 ? ($cart['productInfo']['plat_type'] ?? 0) : ($cart['productInfo']['type'] ?? 0),
|
||||
'relation_id' => $cart['productInfo']['relation_id'] ?? 0,
|
||||
'product_id' => $cart['product_id'] ?? $cart['productInfo']['id'],//原商品ID
|
||||
'product_type' => $cart['productInfo']['product_type'] ?? 0,
|
||||
'sku_unique' => $cart['product_attr_unique'] ?? '',
|
||||
'promotions_id' => implode(',', $cart['promotions_id'] ?? []),
|
||||
'is_gift' => isset($cart['is_gift']) && $cart['is_gift'] ? 1 : 0,
|
||||
'is_support_refund' => isset($cart['is_gift']) && $cart['is_gift'] ? 0 : ($cart['productInfo']['is_support_refund'] ?? 1),
|
||||
'cart_info' => json_encode($cart),
|
||||
'cart_num' => $cart['cart_num'],
|
||||
'surplus_num' => $cart['cart_num'],
|
||||
'split_surplus_num' => $cart['cart_num'],
|
||||
'write_times' => bcmul((string)$cart['cart_num'], (string)(max($cart['productInfo']['attrInfo']['write_times'] ?? 1, 1)), 0),
|
||||
'write_surplus_times' => bcmul((string)$cart['cart_num'], (string)(max($cart['productInfo']['attrInfo']['write_times'] ?? 1, 1)), 0),
|
||||
'unique' => md5($cart['id'] . '' . $oid),
|
||||
'total_price' => $cart['total_price'] ?? 0,
|
||||
'pay_price' => $cart['pay_price'] ?? 0,
|
||||
'pay_postage' => $cart['postage_price'] ?? 0,
|
||||
'coupon_price' => $cart['coupon_price'] ?? 0,
|
||||
'promotions_price' => $cart['sum_promotions_price'] ?? 0,
|
||||
'first_order_price' => $cart['first_order_price'] ?? 0,
|
||||
];
|
||||
}
|
||||
if ($promotions) {
|
||||
/** @var StoreOrderPromotionsServices $services */
|
||||
$services = app()->make(StoreOrderPromotionsServices::class);
|
||||
$services->setPromotionsDetail((int)$uid, (int)$oid, $cartInfo, $promotions);
|
||||
}
|
||||
return $this->dao->saveAll($group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单创建成功之后计算订单(实际优惠、积分、佣金、上级、上上级)
|
||||
* @param $oid
|
||||
* @param array $cartInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function updateCartInfo($oid, array $cartInfo)
|
||||
{
|
||||
foreach ($cartInfo as $cart) {
|
||||
$group = [
|
||||
'cart_info' => json_encode($cart),
|
||||
'pay_price' => max($cart['pay_price'],0),
|
||||
'deduction_price' => $cart['integral_price'] ?? 0,
|
||||
'change_price' => $cart['change_price'] ?? 0
|
||||
];
|
||||
$this->dao->update(['oid' => $oid, 'cart_id' => $cart['id']], $group);
|
||||
}
|
||||
$this->dao->cacheTag()->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品编号
|
||||
* @param int $oid
|
||||
* @return array
|
||||
*/
|
||||
public function getCartIdsProduct(int $oid)
|
||||
{
|
||||
$where = [
|
||||
'oid' => $oid,
|
||||
];
|
||||
return $this->dao->getColumn($where, 'product_id', 'oid', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测这些商品是否还可以拆分
|
||||
* @param int $oid
|
||||
* @param array $cart_data
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function checkCartIdsIsSplit(int $oid, array $cart_data)
|
||||
{
|
||||
if (!$cart_data) return false;
|
||||
$ids = array_unique(array_column($cart_data, 'cart_id'));
|
||||
if ($this->dao->getCartInfoList(['oid' => $oid, 'cart_id' => $ids, 'split_status' => 2], ['cart_id'])) {
|
||||
throw new ValidateException('您选择的商品已经拆分完成,请刷新或稍后重新选择');
|
||||
}
|
||||
$cartInfo = $this->getSplitCartList($oid, 'surplus_num,split_surplus_num,cart_info,cart_num', 'cart_id');
|
||||
if (!$cartInfo) {
|
||||
throw new ValidateException('该订单已发货完成');
|
||||
}
|
||||
foreach ($cart_data as $cart) {
|
||||
$surplus_num = $cartInfo[$cart['cart_id']]['surplus_num'] ?? 0;
|
||||
if (!$surplus_num) {//兼容之前老数据
|
||||
$_info = $cartInfo[$cart['cart_id']]['cart_info'] ?? [];
|
||||
$surplus_num = $_info['cart_num'] ?? 0;
|
||||
}
|
||||
if ($cart['cart_num'] > $surplus_num) {
|
||||
throw new ValidateException('您选择商品拆分数量大于购买数量');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可退款商品
|
||||
* @param int $oid
|
||||
* @param string $field
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function getRefundCartList(int $oid, string $field = '*', string $key = '')
|
||||
{
|
||||
$cartInfo = $this->dao->getColumn([['oid', '=', $oid]], $field, $key);
|
||||
foreach ($cartInfo as $key => &$item) {
|
||||
if ($field == 'cart_info') {
|
||||
$item = is_string($item) ? json_decode($item, true) : $item;
|
||||
} else {
|
||||
if (isset($item['cart_info'])) $item['cart_info'] = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
if (isset($item['cart_num']) && !$item['cart_num']) {//兼容之前老数据
|
||||
$item['cart_num'] = $item['cart_info']['cart_num'] ?? 0;
|
||||
}
|
||||
}
|
||||
$surplus = (int)bcsub((string)$item['cart_num'], (string)$item['refund_num'], 0);
|
||||
if ($surplus > 0) {
|
||||
$item['surplus_num'] = $surplus;
|
||||
} else {
|
||||
unset($cartInfo[$key]);
|
||||
}
|
||||
}
|
||||
return array_merge($cartInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个订单还可以拆分商品 split_status 0:未拆分1:部分拆分2:拆分完成
|
||||
* @param int $oid
|
||||
* @param string $field
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function getSplitCartList(int $oid, string $field = '*', string $key = '')
|
||||
{
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$order = $orderServices->get($oid);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$store_id = $this->getItem('store_id', 0);
|
||||
$supplier_id = $this->getItem('supplier_id', 0);
|
||||
|
||||
//拆分完整主订单查询未发货子订单
|
||||
if ($order['pid'] == -1) {
|
||||
$oid = $orderServices->value(['pid' => $oid, 'status' => 0, 'supplier_id' => $supplier_id, 'store_id' => $store_id, 'refund_type' => [0, 3]], 'id');
|
||||
}
|
||||
$cartInfo = $this->dao->getColumn([['oid', '=', $oid], ['split_status', 'IN', [0, 1]]], $field, $key);
|
||||
foreach ($cartInfo as &$item) {
|
||||
if ($field == 'cart_info') {
|
||||
$item = is_string($item) ? json_decode($item, true) : $item;
|
||||
} else {
|
||||
if (isset($item['cart_info'])) $item['cart_info'] = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
if (isset($item['cart_num']) && !$item['cart_num']) {//兼容之前老数据
|
||||
$item['cart_num'] = $item['cart_info']['cart_num'] ?? 0;
|
||||
}
|
||||
$item['surplus_num'] = $item['split_surplus_num'];
|
||||
}
|
||||
}
|
||||
return $cartInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 次卡商品未核销短信提醒
|
||||
* @return bool
|
||||
*/
|
||||
public function reminderUnverifiedRemind()
|
||||
{
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
// 临期
|
||||
//系统预设取消订单时间段
|
||||
$keyValue = ['reminder_deadline_second_card_time'];
|
||||
//获取配置
|
||||
$systemValue = SystemConfigService::more($keyValue);
|
||||
//格式化数据
|
||||
$systemValue = Arr::setValeTime($keyValue, is_array($systemValue) ? $systemValue : []);
|
||||
$reminder_deadline_second_card_time = $systemValue['reminder_deadline_second_card_time'];
|
||||
$reminder_deadline_second_card_time = (int)bcmul((string)$reminder_deadline_second_card_time, '3600', 0);
|
||||
$writeTime = time() + $reminder_deadline_second_card_time;
|
||||
$adventList = $this->dao->getAdventCartInfoList(time(), $writeTime);
|
||||
if ($adventList) {
|
||||
foreach ($adventList as $key => $item) {
|
||||
$cart_info = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
$store_name = substrUTf8($cart_info['productInfo']['store_name'], 10, 'UTF-8', '');
|
||||
$data['store_name'] = $store_name;
|
||||
$order = $orderServices->get($item['oid'], ['id', 'uid', 'pay_time', 'user_phone']);
|
||||
if (!$order) {
|
||||
continue;
|
||||
}
|
||||
$data['uid'] = $order['uid'];
|
||||
$data['end_time'] = date('Y-m-d H:i', $item['write_end']);
|
||||
$data['pay_time'] = date('Y-m-d H:i', $order['pay_time']);
|
||||
$data['phone'] = $order['user_phone'];
|
||||
event('notice.notice', [$data, 'reminder_brink_death']);
|
||||
$this->dao->update($item['id'], ['is_advent_sms' => 1]);
|
||||
}
|
||||
}
|
||||
// 过期
|
||||
$expireList = $this->dao->getExpireCartInfoList(time());
|
||||
if ($expireList) {
|
||||
foreach ($expireList as $key => $item) {
|
||||
$cart_info = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
$store_name = substrUTf8($cart_info['productInfo']['store_name'], 10, 'UTF-8', '');
|
||||
$data['store_name'] = $store_name;
|
||||
$data['end_time'] = date('Y-m-d H:i', $item['write_end']);
|
||||
$order = $orderServices->get($item['oid'], ['id', 'uid', 'pay_time', 'user_phone']);
|
||||
if (!$order) {
|
||||
continue;
|
||||
}
|
||||
$data['uid'] = $order['uid'];
|
||||
$data['phone'] = $order['user_phone'];
|
||||
event('notice.notice', [$data, 'expiration_reminder']);
|
||||
$this->dao->update($item['id'], ['is_expire_sms' => 1]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
219
app/services/order/StoreOrderCommentServices.php
Normal file
219
app/services/order/StoreOrderCommentServices.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\jobs\order\AutoCommentOrderJob;
|
||||
use app\services\BaseServices;
|
||||
use app\services\product\product\StoreProductReplyServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 订单评价
|
||||
* Class StoreOrderCommentServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderCommentServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* 评论默认数据
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $commentArr = [
|
||||
'reply_score' => 3,
|
||||
'product_score' => 5,
|
||||
'service_score' => 5,
|
||||
'delivery_score' => 5,
|
||||
'comment' => '',
|
||||
'pics' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 订单评价
|
||||
* @param int $oid
|
||||
* @param int $uid
|
||||
* @param array $group
|
||||
* @param string $unique
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function comment(int $oid, int $uid = 0, array $group = [], string $unique = '')
|
||||
{
|
||||
if (!$oid) throw new ValidateException('参数错误!');
|
||||
$order = $this->dao->get($oid);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在!');
|
||||
}
|
||||
$where = ['oid' => $oid];
|
||||
if ($unique) {
|
||||
$where['unique'] = $unique;
|
||||
}
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfos = $cartInfoServices->getColumn($where, 'oid,product_id,cart_info,unique');
|
||||
if (!$cartInfos) {
|
||||
throw new ValidateException('评价商品不存在');
|
||||
}
|
||||
$is_sync = $group['is_sync'] ?? 0;
|
||||
unset($group['is_sync']);
|
||||
$group = array_merge($this->commentArr, array_intersect_key($group, $this->commentArr));
|
||||
$group['comment'] = htmlspecialchars(trim($group['comment']));
|
||||
if ($group['product_score'] < 1) throw new ValidateException('请为商品评分');
|
||||
if ($group['service_score'] < 1) throw new ValidateException('请为商家服务评分');
|
||||
if ($group['delivery_score'] < 1) throw new ValidateException('请为物流服务评分');
|
||||
if ($group['pics']){
|
||||
$pics = is_array($group['pics']) ? $group['pics'] : explode(',', $group['pics']);
|
||||
$group['pics'] = json_encode($pics);
|
||||
}
|
||||
$user_info = [];
|
||||
if ($uid) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user_info = $userServices->getUserInfo($uid);
|
||||
}
|
||||
if ($order['store_id']) {
|
||||
$group['type'] = 1;
|
||||
$group['relation_id'] = $order['store_id'];
|
||||
} elseif ($order['supplier_id']) {
|
||||
$group['type'] = 2;
|
||||
$group['relation_id'] = $order['supplier_id'];
|
||||
} else {
|
||||
$group['type'] = $group['relation_id'] = 0;
|
||||
}
|
||||
$group = array_merge($group, [
|
||||
'uid' => $uid,
|
||||
'nickname' => $user_info['nickname'] ?? substr(md5($oid . time()), 0, 12),
|
||||
'avatar' => $user_info['avatar'] ?? sys_config('h5_avatar'),
|
||||
'oid' => $oid,
|
||||
'add_time' => time(),
|
||||
'reply_type' => 'product'
|
||||
]);
|
||||
/** @var StoreProductReplyServices $replyServices */
|
||||
$replyServices = app()->make(StoreProductReplyServices::class);
|
||||
$data_all = [];
|
||||
$ids = [];
|
||||
$sync = [];
|
||||
foreach ($cartInfos as $cartInfo) {
|
||||
if ($replyServices->be(['oid' => $cartInfo['oid'], 'unique' => $cartInfo['unique']])) continue;
|
||||
$_info = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
|
||||
if (isset($_info['activity_id']) && $_info['activity_id']) $productId = $_info['product_id'];
|
||||
else $productId = $cartInfo['product_id'];
|
||||
$ids[] = $productId;
|
||||
$group['unique'] = $cartInfo['unique'];
|
||||
$group['product_id'] = $productId;
|
||||
$group['sku_unique'] = $_info['productInfo']['attrInfo']['unique'] ?? '';
|
||||
$group['sku'] = $_info['productInfo']['attrInfo']['suk'] ?? '';
|
||||
$data_all[] = $group;
|
||||
}
|
||||
if ($is_sync) {
|
||||
$sync = [
|
||||
'content_type' => 1,
|
||||
'content' => $group['comment'] ?? '',
|
||||
'slider_image' => $pics ?? [],
|
||||
'relation_id' => $uid,
|
||||
'product_id' => $ids
|
||||
];
|
||||
}
|
||||
if ($data_all) {
|
||||
$res = $replyServices->saveAll($data_all);
|
||||
if (!$res) {
|
||||
throw new ValidateException('评价失败!');
|
||||
}
|
||||
}
|
||||
try {
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$orderServices->checkOrderOver($replyServices, $cartInfoServices->getCartColunm(['oid' => $oid, 'is_gift' => 0], 'unique', ''), $oid);
|
||||
} catch (\Exception $e) {
|
||||
throw new ValidateException($e->getMessage());
|
||||
}
|
||||
//清除评价缓存
|
||||
$replyServices->cacheTag()->clear();
|
||||
//订单评价成功事件
|
||||
event('order.comment', [$order]);
|
||||
|
||||
if ($ids) {
|
||||
//商品评价
|
||||
event('product.reply', [$ids, $is_sync, $sync]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行自动默认好评
|
||||
* @param array $where
|
||||
* @param int $page
|
||||
* @param int $maxLimit
|
||||
* @return bool
|
||||
*/
|
||||
public function runAutoCommentOrder(array $where, int $page = 0, int $maxLimit = 0)
|
||||
{
|
||||
/** @var StoreOrderStoreOrderStatusServices $service */
|
||||
$service = app()->make(StoreOrderStoreOrderStatusServices::class);
|
||||
$orderList = $service->getOrderIds($where, $page, $maxLimit);
|
||||
foreach ($orderList as $order) {
|
||||
if ($order['status'] == 3) {
|
||||
continue;
|
||||
}
|
||||
$group = ['comment' => '此用户未作评价'];
|
||||
$this->comment((int)$order['id'], (int)$order['uid'], $group);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动默认好评
|
||||
* @return bool
|
||||
*/
|
||||
public function autoCommentOrder()
|
||||
{
|
||||
//7天前时间戳
|
||||
$systemCommentTime = (int)sys_config('system_comment_time', 0);
|
||||
//0为取消自动默认好评功能
|
||||
if ($systemCommentTime == 0) {
|
||||
return true;
|
||||
}
|
||||
$sevenDay = strtotime(date('Y-m-d H:i:s', strtotime('-' . $systemCommentTime . ' day')));
|
||||
/** @var StoreOrderStoreOrderStatusServices $service */
|
||||
$service = app()->make(StoreOrderStoreOrderStatusServices::class);
|
||||
$where = [
|
||||
'change_time' => $sevenDay,
|
||||
'is_del' => 0,
|
||||
'paid' => 1,
|
||||
'status' => 2,
|
||||
'change_type' => ['user_take_delivery', 'take_delivery', 'writeoff']
|
||||
];
|
||||
$maxLimit = 20;
|
||||
$count = $service->getOrderCount($where);
|
||||
if ($count > $maxLimit) {
|
||||
$pages = ceil($count / $maxLimit);
|
||||
for ($i = 1; $i <= $pages; $i++) {
|
||||
AutoCommentOrderJob::dispatch([$where, $i, $maxLimit]);
|
||||
}
|
||||
} else {
|
||||
$this->runAutoCommentOrder($where);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
743
app/services/order/StoreOrderComputedServices.php
Normal file
743
app/services/order/StoreOrderComputedServices.php
Normal file
@@ -0,0 +1,743 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
use app\services\activity\discounts\StoreDiscountsServices;
|
||||
use app\services\activity\holiday\HolidayGiftPushServices;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\other\CityAreaServices;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\product\brand\StoreBrandServices;
|
||||
use app\services\product\category\StoreProductCategoryServices;
|
||||
use app\services\user\member\MemberCardServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use app\services\user\UserAddressServices;
|
||||
use app\services\activity\coupon\StoreCouponUserServices;
|
||||
use app\services\product\shipping\ShippingTemplatesFreeServices;
|
||||
use app\services\product\shipping\ShippingTemplatesRegionServices;
|
||||
use app\services\product\shipping\ShippingTemplatesServices;
|
||||
use app\services\user\UserBillServices;
|
||||
use function Swoole\Coroutine\batch;
|
||||
|
||||
/**
|
||||
* 订单计算金额
|
||||
* Class StoreOrderComputedServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderComputedServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* 支付类型
|
||||
* @var string[]
|
||||
*/
|
||||
public array $payType = ['weixin' => '微信支付', 'yue' => '余额支付', 'offline' => '线下支付', 'pc' => 'pc'];
|
||||
|
||||
/**
|
||||
* 额外参数
|
||||
* @var array
|
||||
*/
|
||||
protected array $paramData = [];
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 设置额外参数
|
||||
* @param array $paramData
|
||||
* @return $this
|
||||
*/
|
||||
public function setParamData(array $paramData)
|
||||
{
|
||||
$this->paramData = $paramData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算订单金额
|
||||
* @param int $uid
|
||||
* @param array $userInfo
|
||||
* @param array $cartGroup
|
||||
* @param int $addressId
|
||||
* @param string $payType
|
||||
* @param bool $useIntegral
|
||||
* @param int $couponId
|
||||
* @param int $shippingType
|
||||
* @return array
|
||||
*/
|
||||
public function computedOrder(int $uid, array $userInfo, array $cartGroup, int $addressId, string $payType, bool $useIntegral = false, int $couponId = 0, int $shippingType = 1, int $isSendGift = 0)
|
||||
{
|
||||
$offlinePayStatus = (int)sys_config('offline_pay_status') ?? (int)2;
|
||||
$systemPayType = PayServices::PAY_TYPE;
|
||||
if ($offlinePayStatus == 2) unset($systemPayType['offline']);
|
||||
if ($payType && !array_key_exists($payType, $systemPayType)) {
|
||||
throw new ValidateException('选择支付方式有误');
|
||||
}
|
||||
if ($uid && !$userInfo) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('用户不存在!');
|
||||
}
|
||||
}
|
||||
$cartInfo = $cartGroup['cartInfo'];
|
||||
$priceGroup = $cartGroup['priceGroup'];
|
||||
$deduction = $cartGroup['deduction'];
|
||||
$other = $cartGroup['other'];
|
||||
$promotions = $other['promotions'] ?? [];
|
||||
$payPrice = (float)$priceGroup['totalPrice'];
|
||||
$payIntegral = (int)$priceGroup['totalIntegral'] ?? 0;
|
||||
$couponPrice = (float)$priceGroup['couponPrice'];
|
||||
$firstOrderPrice = (float)$priceGroup['firstOrderPrice'];
|
||||
$changePrice = (float)$priceGroup['changePrice'] ?? 0.00;
|
||||
$addr = $cartGroup['addr'] ?? [];
|
||||
$postage = $priceGroup;
|
||||
if (!$addr || $addr['id'] != $addressId) {
|
||||
/** @var UserAddressServices $addressServices */
|
||||
$addressServices = app()->make(UserAddressServices::class);
|
||||
$addr = $addressServices->getAdderssCache($addressId);
|
||||
//改变地址重新计算邮费
|
||||
$postage = [];
|
||||
}
|
||||
$type = (int)$deduction['type'] ?? 0;
|
||||
$results = batch([
|
||||
'promotions' => function () use ($cartInfo, $type) {
|
||||
$promotionsPrice = 0;
|
||||
if ($type == 8) return $promotionsPrice;
|
||||
foreach ($cartInfo as $key => $cart) {
|
||||
if (isset($cart['sum_promotions_price']) && isset($cart['price_type']) && $cart['price_type'] == 'promotions') {
|
||||
$promotionsPrice = bcadd((string)$promotionsPrice, (string)$cart['sum_promotions_price'], 2);
|
||||
}
|
||||
}
|
||||
return $promotionsPrice;
|
||||
},
|
||||
'postage' => function () use ($uid, $shippingType, $payType, $cartInfo, $addr, $payPrice, $postage, $other, $type, $isSendGift) {
|
||||
if ($type == 8) $shippingType = 2;
|
||||
return $this->computedPayPostage($uid, $shippingType, $payType, $cartInfo, $addr, $payPrice, $postage, $other, $isSendGift);
|
||||
},
|
||||
]);
|
||||
|
||||
$promotionsDetail = [];
|
||||
if ($promotions) {
|
||||
foreach ($promotions as $key => $value) {
|
||||
if (isset($value['details']['sum_promotions_price']) && $value['details']['sum_promotions_price']) {
|
||||
$promotionsDetail[] = ['id' => $value['id'], 'name' => $value['name'], 'title' => $value['title'], 'desc' => $value['desc'], 'promotions_price' => $value['details']['sum_promotions_price'], 'promotions_type' => $value['promotions_type']];
|
||||
}
|
||||
}
|
||||
if ($promotionsDetail) {
|
||||
$typeArr = array_column($promotionsDetail, 'promotions_type');
|
||||
array_multisort($typeArr, SORT_ASC, $promotionsDetail);
|
||||
}
|
||||
}
|
||||
|
||||
// [$p, $couponPrice] = $results['coupon'];
|
||||
[$p, $payPostage, $storePostageDiscount, $storeFreePostage, $isStoreFreePostage] = $results['postage'];
|
||||
if ($couponPrice < $payPrice) {//优惠券金额
|
||||
$payPrice = bcsub((string)$payPrice, (string)$couponPrice, 2);
|
||||
} else {
|
||||
$payPrice = 0;
|
||||
}
|
||||
if ($type == 8) {
|
||||
$firstOrderPrice = 0;
|
||||
$payPrice = 0;
|
||||
}
|
||||
if ($firstOrderPrice < $payPrice) {//首单优惠金额
|
||||
$payPrice = bcsub((string)$payPrice, (string)$firstOrderPrice, 2);
|
||||
} else {
|
||||
$payPrice = 0;
|
||||
}
|
||||
if ($uid && sys_config('integral_ratio_status') && in_array($type, [0, 6])) {
|
||||
//使用积分
|
||||
[$payPrice, $deductionPrice, $usedIntegral, $SurplusIntegral] = $this->useIntegral($useIntegral, $userInfo, $payPrice, $other);
|
||||
}
|
||||
|
||||
$payPrice = (float)bcadd((string)$payPrice, (string)$payPostage, 2);
|
||||
foreach ($cartInfo as &$item) {
|
||||
$item['invalid'] = false;
|
||||
if ($shippingType === 2 && in_array(2, $item['productInfo']['delivery_type'])) {
|
||||
$item['invalid'] = true;
|
||||
}
|
||||
if($shippingType == 2){
|
||||
$item['postage_price'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$payPrice = bcadd($payPrice, $priceGroup['sendGiftPrice'], 2);
|
||||
$result = [
|
||||
'total_price' => $priceGroup['totalPrice'],
|
||||
'sendGiftPrice' => $priceGroup['sendGiftPrice'],
|
||||
'pay_price' => max($payPrice, 0),
|
||||
'pay_integral' => max($payIntegral, 0),
|
||||
'total_postage' => bcadd((string)$payPostage, (string)($storePostageDiscount ?? 0), 2),
|
||||
'pay_postage' => $payPostage,
|
||||
'first_order_price' => $firstOrderPrice ?? 0,
|
||||
'coupon_price' => $couponPrice ?? 0,
|
||||
'promotions_price' => $results['promotions'] ?? 0,
|
||||
'promotions_detail' => $promotionsDetail,
|
||||
'deduction_price' => $deductionPrice ?? 0,
|
||||
'usedIntegral' => $usedIntegral ?? 0,
|
||||
'SurplusIntegral' => $SurplusIntegral ?? 0,
|
||||
'storePostageDiscount' => $storePostageDiscount ?? 0,
|
||||
'isStoreFreePostage' => $isStoreFreePostage ?? false,
|
||||
'storeFreePostage' => $storeFreePostage ?? 0,
|
||||
'change_price' => $changePrice,
|
||||
'cartInfo' => $cartInfo
|
||||
];
|
||||
$this->paramData = [];
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用优惠卷
|
||||
* @param int $couponId
|
||||
* @param int $uid
|
||||
* @param $cartInfo
|
||||
* @param $payPrice
|
||||
*/
|
||||
public function useCouponId(int $couponId, int $uid, $cartInfo, $payPrice, $promotions)
|
||||
{
|
||||
//使用优惠劵
|
||||
$couponPrice = 0;
|
||||
if ($couponId && $cartInfo) {
|
||||
/** @var StoreCouponUserServices $couponServices */
|
||||
$couponServices = app()->make(StoreCouponUserServices::class);
|
||||
$couponInfo = $couponServices->getOne([['id', '=', $couponId], ['uid', '=', $uid], ['is_fail', '=', 0], ['status', '=', 0], ['start_time', '<=', time()], ['end_time', '>=', time()]], '*', ['issue']);
|
||||
if (!$couponInfo) {
|
||||
throw new ValidateException('选择的优惠劵无效!');
|
||||
}
|
||||
$type = $couponInfo['applicable_type'] ?? 0;
|
||||
$flag = false;
|
||||
$price = 0;
|
||||
$count = 0;
|
||||
$promotionsList = [];
|
||||
if ($promotions) {
|
||||
$promotionsList = array_combine(array_column($promotions, 'id'), $promotions);
|
||||
}
|
||||
$isOverlay = function ($cart) use ($promotionsList) {
|
||||
$productInfo = $cart['productInfo'] ?? [];
|
||||
if (!$productInfo) {
|
||||
return false;
|
||||
}
|
||||
if (isset($cart['promotions_id']) && $cart['promotions_id']) {
|
||||
foreach ($cart['promotions_id'] as $key => $promotions_id) {
|
||||
$promotions = $promotionsList[$promotions_id] ?? [];
|
||||
if ($promotions && $promotions['promotions_type'] != 4) {
|
||||
$overlay = is_string($promotions['overlay']) ? explode(',', $promotions['overlay']) : $promotions['overlay'];
|
||||
if (!in_array(5, $overlay)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
switch ($type) {
|
||||
case 0:
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (!$isOverlay($cart)) continue;
|
||||
$price = bcadd($price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
|
||||
$count++;
|
||||
}
|
||||
break;
|
||||
case 1://品类券
|
||||
/** @var StoreProductCategoryServices $storeCategoryServices */
|
||||
$storeCategoryServices = app()->make(StoreProductCategoryServices::class);
|
||||
$cateGorys = $storeCategoryServices->getAllById((int)$couponInfo['category_id']);
|
||||
if ($cateGorys) {
|
||||
$cateIds = array_column($cateGorys, 'id');
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (!$isOverlay($cart)) continue;
|
||||
if (isset($cart['productInfo']['cate_id']) && array_intersect(explode(',', $cart['productInfo']['cate_id']), $cateIds)) {
|
||||
$price = bcadd($price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (!$isOverlay($cart)) continue;
|
||||
if (isset($cart['product_id']) && in_array($cart['product_id'], explode(',', $couponInfo['product_id']))) {
|
||||
$price = bcadd($price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
/** @var StoreBrandServices $storeBrandServices */
|
||||
$storeBrandServices = app()->make(StoreBrandServices::class);
|
||||
$brands = $storeBrandServices->getAllById((int)$couponInfo['brand_id']);
|
||||
if ($brands) {
|
||||
$brandIds = array_column($brands, 'id');
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (!$isOverlay($cart)) continue;
|
||||
if (isset($cart['productInfo']['brand_id']) && in_array($cart['productInfo']['brand_id'], $brandIds)) {
|
||||
$price = bcadd((string)$price, (string)bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($count && $couponInfo['use_min_price'] <= $price) {
|
||||
$flag = true;
|
||||
}
|
||||
if (!$flag) {
|
||||
return [$payPrice, 0];
|
||||
// throw new ValidateException('不满足优惠劵的使用条件!');
|
||||
}
|
||||
//满减券
|
||||
if ($couponInfo['coupon_type'] == 1) {
|
||||
$couponPrice = $couponInfo['coupon_price'];
|
||||
} else {
|
||||
if ($couponInfo['coupon_price'] <= 0) {//0折
|
||||
$couponPrice = $price;
|
||||
} else if ($couponInfo['coupon_price'] >= 100) {
|
||||
$couponPrice = 0;
|
||||
} else {
|
||||
$truePrice = (float)bcmul((string)$price, bcdiv((string)$couponInfo['coupon_price'], '100', 2), 2);
|
||||
$couponPrice = (float)bcsub((string)$price, (string)$truePrice, 2);
|
||||
}
|
||||
}
|
||||
if ($couponPrice < $payPrice) {
|
||||
$payPrice = (float)bcsub((string)$payPrice, (string)$couponPrice, 2);
|
||||
} else {
|
||||
$couponPrice = $payPrice;
|
||||
$payPrice = 0;
|
||||
}
|
||||
}
|
||||
return [$payPrice, $couponPrice];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用积分
|
||||
* @param $useIntegral
|
||||
* @param $userInfo
|
||||
* @param $payPrice
|
||||
* @param $other
|
||||
* @return array
|
||||
*/
|
||||
public function useIntegral(bool $useIntegral, $userInfo, string $payPrice, array $other)
|
||||
{
|
||||
$SurplusIntegral = 0;
|
||||
$deductionPrice = 0;
|
||||
$usedIntegral = 0;
|
||||
if ($userInfo && $userInfo['integral'] > 0) {
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
// 可用积分
|
||||
$usable = bcsub((string)$userInfo['integral'], (string)$userBillServices->getBillSum(['uid' => $userInfo['uid'], 'is_frozen' => 1]), 0);
|
||||
$SurplusIntegral = $usable;
|
||||
if ($useIntegral && $payPrice && $usable > 0) {
|
||||
$integralMaxType = sys_config('integral_max_type', 1);//积分抵用上限类型1:积分、2:订单金额比例
|
||||
if ($integralMaxType == 1) {//最多抵用积分
|
||||
$integralMaxNum = sys_config('integral_max_num', 200);
|
||||
if ($integralMaxNum > 0 && $usable > $integralMaxNum) {
|
||||
$integral = $integralMaxNum;
|
||||
} else {
|
||||
$integral = $usable;
|
||||
}
|
||||
$deductionPrice = (float)bcmul((string)$integral, (string)$other['integralRatio'], 2);
|
||||
if ($deductionPrice < $payPrice) {
|
||||
$payPrice = bcsub((string)$payPrice, (string)$deductionPrice, 2);
|
||||
$usedIntegral = $integral;
|
||||
} else {
|
||||
if ($other['integralRatio']) {
|
||||
$deductionPrice = $payPrice;
|
||||
$usedIntegral = (int)ceil(bcdiv((string)$payPrice, (string)$other['integralRatio'], 2));
|
||||
}
|
||||
$payPrice = 0;
|
||||
}
|
||||
} else {//最高抵用比率
|
||||
$integralMaxRate = sys_config('integral_max_rate', 0);
|
||||
$deductionPrice = (float)bcmul((string)$usable, (string)$other['integralRatio'], 2);
|
||||
if ($integralMaxRate > 0 && $integralMaxRate <= 100) {
|
||||
$integralMaxPrice = (float)bcmul((string)$payPrice, (string)bcdiv((string)$integralMaxRate, '100', 2), 2);
|
||||
} else {
|
||||
$integralMaxPrice = $payPrice;
|
||||
}
|
||||
$deductionPrice = min($deductionPrice, $integralMaxPrice);
|
||||
$payPrice = bcsub((string)$payPrice, (string)$deductionPrice, 2);
|
||||
$usedIntegral = ceil(bcdiv((string)$deductionPrice, (string)$other['integralRatio'], 2));
|
||||
}
|
||||
$SurplusIntegral = (int)bcsub((string)$SurplusIntegral, (string)$usedIntegral, 0);
|
||||
if ($payPrice <= 0) $payPrice = 0;
|
||||
}
|
||||
}
|
||||
return [$payPrice, $deductionPrice, $usedIntegral, $SurplusIntegral];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算邮费
|
||||
* @param int $uid
|
||||
* @param int $shipping_type
|
||||
* @param string $payType
|
||||
* @param array $cartInfo
|
||||
* @param array $addr
|
||||
* @param string $payPrice
|
||||
* @param array $postage
|
||||
* @param array $other
|
||||
* @return array
|
||||
* @throws \Throwable
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function computedPayPostage(int $uid, int $shipping_type, string $payType, array $cartInfo, array $addr, string $payPrice, array $postage = [], array $other = [], int $isSendGift = 0)
|
||||
{
|
||||
$storePostageDiscount = 0;
|
||||
$storeFreePostage = $postage['storeFreePostage'] ?? 0;
|
||||
$isStoreFreePostage = false;
|
||||
if ($isSendGift == 1) {
|
||||
$shipping_type = 0;
|
||||
$addr = [];
|
||||
}
|
||||
if (!$storeFreePostage) {
|
||||
$storeFreePostage = floatval(sys_config('store_free_postage')) ?: 0;//满额包邮金额
|
||||
}
|
||||
if (!$addr && !isset($addr['id']) || !$cartInfo) {
|
||||
$payPostage = 0;
|
||||
} else {
|
||||
//$shipping_type = 1 快递发货 $shipping_type = 2 门店自提
|
||||
if ($shipping_type == 2) {
|
||||
if (!sys_config('store_func_status', 1) || !sys_config('store_self_mention', 1)) $shipping_type = 1;
|
||||
}
|
||||
//门店自提 || (线下支付 && 线下支付包邮) 没有邮费支付 || 节日任务赠送
|
||||
$holidayGiftPushServices = app()->make(HolidayGiftPushServices::class);
|
||||
$holidayGift = $holidayGiftPushServices->receiveHolidayGift($uid, 1);
|
||||
|
||||
if ($shipping_type === 2 || ($payType == 'offline' && ((isset($other['offlinePostage']) && $other['offlinePostage']) || sys_config('offline_postage')) == 1) || $holidayGift) {
|
||||
$payPostage = 0;
|
||||
} else {
|
||||
if (!$postage || !isset($postage['storePostage']) || !isset($postage['storePostageDiscount'])) {
|
||||
$postage = $this->getOrderPriceGroup($uid, $cartInfo, $addr, $storeFreePostage);
|
||||
}
|
||||
$payPostage = $postage['storePostage'];
|
||||
$storePostageDiscount = $postage['storePostageDiscount'];
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
//享受svip 运费折扣
|
||||
if ($userService->checkUserIsSvip($uid)) {
|
||||
$payPostage = bcsub((string)$payPostage, (string)$storePostageDiscount, 2);
|
||||
} else {
|
||||
$storePostageDiscount = 0;
|
||||
}
|
||||
$isStoreFreePostage = $postage['isStoreFreePostage'] ?? false;
|
||||
|
||||
$payPrice = (float)bcadd((string)$payPrice, (string)$payPostage, 2);
|
||||
}
|
||||
}
|
||||
return [$payPrice, $payPostage, $storePostageDiscount, $storeFreePostage, $isStoreFreePostage];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 运费计算,总金额计算
|
||||
* @param int $uid
|
||||
* @param $cartInfo
|
||||
* @param $addr
|
||||
* @param $storeFreePostage
|
||||
* @return array
|
||||
* @throws \Throwable
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOrderPriceGroup(int $uid, $cartInfo, $addr, $storeFreePostage = null, $isSendGift = 0)
|
||||
{
|
||||
$storePostage = 0;
|
||||
$sendGiftPrice = 0;
|
||||
$storePostageDiscount = 0;
|
||||
$isStoreFreePostage = false;//是否满额包邮
|
||||
if (is_null($storeFreePostage)) {
|
||||
$storeFreePostage = floatval(sys_config('store_free_postage')) ?: 0;//满额包邮金额
|
||||
}
|
||||
$sumPrice = $this->getOrderSumPrice($cartInfo, 'sum_price');//获取订单原总金额
|
||||
$totalPrice = $this->getOrderSumPrice($cartInfo, 'pay_price', false);//获取订单svip、用户等级优惠之后总金额
|
||||
$costPrice = $this->getOrderSumPrice($cartInfo, 'costPrice');//获取订单成本价
|
||||
$totalIntegral = (int)$this->getOrderSumPrice($cartInfo, 'integral');//获取订单总积分
|
||||
$vipPrice = $this->getOrderSumPrice($cartInfo, 'vip_truePrice');//获取订单等级和付费会员总优惠金额
|
||||
$levelPrice = $this->getOrderSumPrice($cartInfo, 'level');//获取会员等级优惠
|
||||
$memberPrice = $this->getOrderSumPrice($cartInfo, 'member');//获取付费会员优惠
|
||||
$changePrice = (float)$this->getOrderSumPrice($cartInfo, 'change_price', false);//获取改价优惠金额
|
||||
$channelPrice = (float)$this->getOrderSumPrice($cartInfo, 'channel_price', false);//采购商优惠价
|
||||
// 如果送礼订单,不计算邮费,只计算送礼附加费
|
||||
if ($isSendGift) {
|
||||
foreach ($cartInfo as $item) {
|
||||
if ($item['productInfo']['is_send_gift']) {
|
||||
$giftPrice = bcmul($item['productInfo']['send_gift_price'], $item['cart_num'], 2);
|
||||
$sendGiftPrice = bcadd((string)$sendGiftPrice, (string)$giftPrice, 2);
|
||||
}
|
||||
}
|
||||
return compact('storePostage', 'storeFreePostage', 'isStoreFreePostage', 'sumPrice', 'totalPrice', 'totalIntegral', 'costPrice', 'vipPrice', 'levelPrice', 'memberPrice', 'storePostageDiscount', 'changePrice', 'cartInfo', 'channelPrice', 'sendGiftPrice');
|
||||
}
|
||||
//节日任务赠送包邮
|
||||
$holidayGiftPushServices = app()->make(HolidayGiftPushServices::class);
|
||||
if ($holidayGiftPushServices->receiveHolidayGift($uid, 1)) {
|
||||
return compact('storePostage', 'storeFreePostage', 'isStoreFreePostage', 'sumPrice', 'totalPrice', 'totalIntegral', 'costPrice', 'vipPrice', 'levelPrice', 'memberPrice', 'storePostageDiscount', 'changePrice', 'cartInfo', 'channelPrice', 'sendGiftPrice');
|
||||
}
|
||||
//如果满额包邮等于0
|
||||
$free_shipping = 0;
|
||||
$postageArr = [];
|
||||
if (isset($cartInfo[0]['productInfo']['product_type']) && in_array($cartInfo[0]['productInfo']['product_type'], [1, 2])) {
|
||||
$storePostage = 0;
|
||||
} elseif ($cartInfo && $addr) {
|
||||
//优惠套餐包邮判断
|
||||
if (isset($cartInfo[0]['type']) && $cartInfo[0]['type'] == 5 && isset($cartInfo[0]['activity_id']) && $cartInfo[0]['activity_id']) {
|
||||
/** @var StoreDiscountsServices $discountService */
|
||||
$discountService = app()->make(StoreDiscountsServices::class);
|
||||
$free_shipping = $discountService->value(['id' => $cartInfo[0]['activity_id']], 'free_shipping');
|
||||
}
|
||||
if ($free_shipping) {
|
||||
$storePostage = 0;
|
||||
} else if (sys_config('whole_free_shipping') == 1 && $totalPrice >= $storeFreePostage) {//如果总价大于等于满额包邮 邮费等于0
|
||||
$isStoreFreePostage = true;
|
||||
$storePostage = 0;
|
||||
} else {
|
||||
|
||||
// 判断商品包邮和固定运费
|
||||
foreach ($cartInfo as &$item) {
|
||||
if (!isset($item['productInfo']['freight'])) continue;
|
||||
if ($item['productInfo']['freight'] == 1) {
|
||||
$item['postage_price'] = 0;
|
||||
} elseif ($item['productInfo']['freight'] == 2) {
|
||||
$item['postage_price'] = bcmul((string)$item['productInfo']['postage'], (string)$item['cart_num'], 2);
|
||||
$storePostage = bcadd((string)$storePostage, (string)$item['postage_price'], 2);
|
||||
}
|
||||
}
|
||||
|
||||
//按照运费模板计算每个运费模板下商品的件数/重量/体积以及总金额 按照首重倒序排列
|
||||
$cityId = (int)($addr['city_id'] ?? 0);
|
||||
$ids = [];
|
||||
if ($cityId) {
|
||||
/** @var CityAreaServices $cityAreaServices */
|
||||
$cityAreaServices = app()->make(CityAreaServices::class);
|
||||
$ids = $cityAreaServices->getRelationCityIds($cityId);
|
||||
}
|
||||
$cityIds = array_merge([0], $ids);
|
||||
|
||||
$tempIds[] = 1;
|
||||
foreach ($cartInfo as $key_c => $item_c) {
|
||||
if (isset($item_c['productInfo']['freight']) && $item_c['productInfo']['freight'] == 3) {
|
||||
$tempIds[] = $item_c['productInfo']['temp_id'];
|
||||
}
|
||||
}
|
||||
$tempIds = array_unique($tempIds);
|
||||
/** @var ShippingTemplatesServices $shippServices */
|
||||
$shippServices = app()->make(ShippingTemplatesServices::class);
|
||||
$temp = $shippServices->getShippingColumnCache(['id' => $tempIds], 'appoint,group', 'id');
|
||||
/** @var ShippingTemplatesRegionServices $regionServices */
|
||||
$regionServices = app()->make(ShippingTemplatesRegionServices::class);
|
||||
$regions = $regionServices->getTempRegionListCache($tempIds, $cityIds);
|
||||
$temp_num = [];
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (isset($cart['productInfo']['freight']) && in_array($cart['productInfo']['freight'], [1, 2])) {
|
||||
continue;
|
||||
}
|
||||
$tempId = $cart['productInfo']['temp_id'] ?? 1;
|
||||
$group = isset($temp[$tempId]['group']) ? $temp[$tempId]['group'] : $temp[1]['group'];
|
||||
if ($group == 1) {
|
||||
$num = $cart['cart_num'];
|
||||
} elseif ($group == 2) {
|
||||
$num = $cart['cart_num'] * $cart['productInfo']['attrInfo']['weight'];
|
||||
} else {
|
||||
$num = $cart['cart_num'] * $cart['productInfo']['attrInfo']['volume'];
|
||||
}
|
||||
$region = $regions[$tempId] ?? ($regions[1] ?? []);
|
||||
if (!$region) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($temp_num[$tempId])) {
|
||||
$temp_num[$tempId] = [
|
||||
'number' => $num,
|
||||
'group' => $group,
|
||||
'price' => bcmul($cart['cart_num'], $cart['truePrice'], 2),
|
||||
'first' => $region['first'],
|
||||
'first_price' => $region['first_price'],
|
||||
'continue' => $region['continue'],
|
||||
'continue_price' => $region['continue_price'],
|
||||
'temp_id' => $tempId
|
||||
];
|
||||
} else {
|
||||
$temp_num[$tempId]['number'] += $num;
|
||||
$temp_num[$tempId]['price'] += $cart['pay_price'];
|
||||
}
|
||||
}
|
||||
if ($temp_num) {
|
||||
/** @var ShippingTemplatesFreeServices $freeServices */
|
||||
$freeServices = app()->make(ShippingTemplatesFreeServices::class);
|
||||
$freeList = $freeServices->isFreeListCache($tempIds, $cityIds);
|
||||
if ($freeList) {
|
||||
foreach ($temp_num as $k => $v) {
|
||||
if (isset($temp[$v['temp_id']]['appoint']) && $temp[$v['temp_id']]['appoint'] && isset($freeList[$v['temp_id']])) {
|
||||
$free = $freeList[$v['temp_id']];
|
||||
$condition = $free['number'] <= $v['number'];
|
||||
if ($free['price'] <= $v['price'] && $condition) {
|
||||
unset($temp_num[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//首件运费最大值
|
||||
$maxFirstPrice = $temp_num ? max(array_column($temp_num, 'first_price')) : 0;
|
||||
//初始运费为0
|
||||
$storePostage_arr = [];
|
||||
|
||||
$i = 0;
|
||||
//循环运费数组
|
||||
foreach ($temp_num as $fk => $fv) {
|
||||
//找到首件运费等于最大值
|
||||
if ($fv['first_price'] == $maxFirstPrice) {
|
||||
//每次循环设置初始值
|
||||
$tempArr = $temp_num;
|
||||
$Postage = 0;
|
||||
//计算首件运费
|
||||
if ($fv['number'] <= $fv['first']) {
|
||||
$Postage = bcadd($Postage, $fv['first_price'], 2);
|
||||
} else {
|
||||
if ($fv['continue'] <= 0) {
|
||||
$Postage = $Postage;
|
||||
} else {
|
||||
$Postage = bcadd(bcadd($Postage, $fv['first_price'], 2), bcmul(ceil(bcdiv(bcsub($fv['number'], $fv['first'], 2), $fv['continue'] ?? 0, 2)), $fv['continue_price'], 4), 2);
|
||||
}
|
||||
}
|
||||
$postageArr[$i]['data'][$fk] = $Postage;
|
||||
|
||||
//删除计算过的首件数据
|
||||
unset($tempArr[$fk]);
|
||||
//循环计算剩余运费
|
||||
foreach ($tempArr as $ck => $cv) {
|
||||
if ($cv['continue'] <= 0) {
|
||||
$Postage = $Postage;
|
||||
} else {
|
||||
$one_postage = bcmul(ceil(bcdiv($cv['number'], $cv['continue'] ?? 0, 2)), $cv['continue_price'], 2);
|
||||
$Postage = bcadd($Postage, $one_postage, 2);
|
||||
$postageArr[$i]['data'][$ck] = $one_postage;
|
||||
}
|
||||
}
|
||||
$postageArr[$i]['sum'] = $Postage;
|
||||
$storePostage_arr[] = $Postage;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$maxStorePostage = $storePostage_arr ? max($storePostage_arr) : 0;
|
||||
// //获取运费计算中的最大值
|
||||
$storePostage = bcadd((string)$storePostage, (string)$maxStorePostage, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//会员邮费享受折扣
|
||||
if ($storePostage) {
|
||||
//看是否开启会员折扣奖励
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$express_rule_number = $memberCardService->isOpenMemberCardCache('express');
|
||||
$express_rule_number = $express_rule_number <= 0 ? 0 : $express_rule_number;
|
||||
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userIsSvip = $userService->checkUserIsSvip($uid);
|
||||
|
||||
$truePostageArr = [];
|
||||
foreach ($postageArr as $postageitem) {
|
||||
if ($postageitem['sum'] == ($maxStorePostage ?? 0)) {
|
||||
$truePostageArr = $postageitem['data'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$cartAlready = [];
|
||||
foreach ($cartInfo as &$item) {
|
||||
if (isset($item['productInfo']['freight']) && in_array($item['productInfo']['freight'], [1, 2])) {
|
||||
if (isset($item['postage_price']) && $item['postage_price'] && $express_rule_number && $express_rule_number < 100 && $userIsSvip) {
|
||||
$item['postage_price'] = bcmul($item['postage_price'], bcdiv($express_rule_number, 100, 4), 2);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$tempId = $item['productInfo']['temp_id'] ?? 0;
|
||||
$tempPostage = $truePostageArr[$tempId] ?? 0;
|
||||
$tempNumber = $temp_num[$tempId]['number'] ?? 0;
|
||||
if (!$tempId || !$tempPostage) continue;
|
||||
$group = $temp_num[$tempId]['group'];
|
||||
|
||||
if ($group == 1) {
|
||||
$num = $item['cart_num'];
|
||||
} elseif ($group == 2) {
|
||||
$num = $item['cart_num'] * $item['productInfo']['attrInfo']['weight'];
|
||||
} else {
|
||||
$num = $item['cart_num'] * $item['productInfo']['attrInfo']['volume'];
|
||||
}
|
||||
|
||||
if ((($cartAlready[$tempId]['number'] ?? 0) + $num) >= $tempNumber) {
|
||||
$price = isset($cartAlready[$tempId]['price']) ? bcsub((string)$tempPostage, (string)$cartAlready[$tempId]['price'], 2) : $tempPostage;
|
||||
} else {
|
||||
$price = bcmul((string)$tempPostage, bcdiv((string)$num, (string)$tempNumber, 4), 2);
|
||||
}
|
||||
$cartAlready[$tempId]['number'] = bcadd((string)($cartAlready[$tempId]['number'] ?? 0), (string)$num, 2);
|
||||
$cartAlready[$tempId]['price'] = bcadd((string)($cartAlready[$tempId]['price'] ?? 0.00), (string)$price, 2);
|
||||
|
||||
if ($express_rule_number && $express_rule_number < 100 && $userIsSvip) {
|
||||
$price = bcmul($price, bcdiv($express_rule_number, 100, 4), 2);
|
||||
}
|
||||
$price = sprintf("%.2f", $price);
|
||||
$item['postage_price'] = $price;
|
||||
}
|
||||
if ($express_rule_number && $express_rule_number < 100) {
|
||||
$payPostage = bcmul($storePostage, bcdiv($express_rule_number, 100, 4), 2);
|
||||
$storePostageDiscount = bcsub($storePostage, $payPostage, 2);
|
||||
} else {
|
||||
$storePostageDiscount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
return compact('storePostage', 'storeFreePostage', 'isStoreFreePostage', 'sumPrice', 'totalPrice', 'totalIntegral', 'costPrice', 'vipPrice', 'levelPrice', 'memberPrice', 'storePostageDiscount', 'changePrice', 'cartInfo', 'channelPrice', 'sendGiftPrice');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个字段总金额
|
||||
* @param $cartInfo
|
||||
* @param string $key
|
||||
* @param bool $is_unit
|
||||
* @return int|string
|
||||
*/
|
||||
public function getOrderSumPrice($cartInfo, $key = 'truePrice', $is_unit = true)
|
||||
{
|
||||
$SumPrice = 0;
|
||||
foreach ($cartInfo as $cart) {
|
||||
if (isset($cart['cart_info'])) $cart = $cart['cart_info'];
|
||||
if (isset($cart['is_gift']) && $cart['is_gift']) {
|
||||
continue;
|
||||
}
|
||||
if ($is_unit) {
|
||||
if ($key == 'level' || $key == 'member') {
|
||||
if (isset($cart['price_type']) && $cart['price_type'] == $key) {
|
||||
$SumPrice = bcadd($SumPrice, bcmul($cart['cart_num'], $cart['vip_truePrice'], 2), 2);
|
||||
}
|
||||
} else {
|
||||
$SumPrice = bcadd($SumPrice, bcmul($cart['cart_num'] ?? 1, $cart[$key] ?? 0, 2), 2);
|
||||
}
|
||||
|
||||
} else {
|
||||
$SumPrice = bcadd($SumPrice, $cart[$key] ?? 0, 2);
|
||||
}
|
||||
}
|
||||
return $SumPrice;
|
||||
}
|
||||
}
|
||||
1080
app/services/order/StoreOrderCreateServices.php
Normal file
1080
app/services/order/StoreOrderCreateServices.php
Normal file
File diff suppressed because it is too large
Load Diff
681
app/services/order/StoreOrderDeliveryServices.php
Normal file
681
app/services/order/StoreOrderDeliveryServices.php
Normal file
@@ -0,0 +1,681 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\jobs\order\OrderStatusJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\user\UserServices;
|
||||
use app\services\serve\ServeServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\exception\ValidateException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use app\services\other\ExpressServices;
|
||||
use app\services\message\sms\SmsSendServices;
|
||||
use crmeb\traits\OptionTrait;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 订单发货
|
||||
* Class StoreOrderDeliveryServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderDeliveryServices extends BaseServices
|
||||
{
|
||||
use OptionTrait;
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 订单整体发货
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $staff_id
|
||||
* @return array
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function delivery(int $id, array $data, int $staff_id = 0)
|
||||
{
|
||||
$orderInfo = $this->dao->get($id, ['*'], ['pink']);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能发货!');
|
||||
}
|
||||
if ($orderInfo['paid'] != 1) {
|
||||
throw new ValidateException('订单未支付');
|
||||
}
|
||||
if ($orderInfo->is_del) {
|
||||
throw new ValidateException('订单已删除,不能发货!');
|
||||
}
|
||||
if ($orderInfo->status == 1) {
|
||||
throw new ValidateException('订单已发货请勿重复操作!');
|
||||
}
|
||||
if ($orderInfo->shipping_type == 2) {
|
||||
throw new ValidateException('核销订单不能发货!');
|
||||
}
|
||||
if (isset($orderInfo['pinkStatus']) && $orderInfo['pinkStatus'] != 2) {
|
||||
throw new ValidateException('拼团未完成暂不能发货!');
|
||||
}
|
||||
$store_id = $this->getItem('store_id', 0);
|
||||
$supplier_id = $this->getItem('supplier_id', 0);
|
||||
|
||||
//拆分完整主订单查询未发货子订单
|
||||
if ($orderInfo['pid'] == -1) {
|
||||
$orderInfo = $this->dao->get(['pid' => $id, 'status' => 0, 'supplier_id' => $supplier_id, 'refund_type' => [0, 3]], ['*'], ['pink']);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('请在详情->发货记录:查看具体发货情况');
|
||||
}
|
||||
$id = (int)$orderInfo['id'];
|
||||
}
|
||||
/** @var StoreOrderRefundServices $storeOrderRefundServices */
|
||||
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
if ($storeOrderRefundServices->count(['store_order_id' => $id, 'refund_type' => [1, 2, 4, 5, 6], 'is_cancel' => 0, 'is_del' => 0])) {
|
||||
throw new ValidateException('订单有售后申请请先处理');
|
||||
}
|
||||
//取消预售订单 验证预售活动是否结束
|
||||
// if ($orderInfo['type'] == 6) {
|
||||
// /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
// $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
// $cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($id);
|
||||
// $time = time();
|
||||
// foreach ($cartInfo as $cart) {
|
||||
// if (isset($cart['cart_info']['productInfo']['presale_end_time']) && $cart['cart_info']['productInfo']['presale_end_time'] > $time) {
|
||||
// throw new ValidateException('预售活动暂未结束,请稍后发货');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (isset($data['remark']) && $data['remark'] == '') {
|
||||
unset($data['remark']);
|
||||
}
|
||||
|
||||
$dump = $this->doDelivery($id, $orderInfo, $data);
|
||||
if ($staff_id) {
|
||||
$this->dao->update($id, ['staff_id' => $staff_id]);
|
||||
}
|
||||
return compact('orderInfo', 'dump');
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单拆单发货
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $staff_id
|
||||
* @return bool
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function splitDelivery(int $id, array $data, int $staff_id = 0)
|
||||
{
|
||||
$orderInfo = $this->dao->get($id, ['*'], ['pink']);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能发货!');
|
||||
}
|
||||
if ($orderInfo['paid'] != 1) {
|
||||
throw new ValidateException('订单未支付');
|
||||
}
|
||||
if ($orderInfo->is_del) {
|
||||
throw new ValidateException('订单已删除,不能发货!');
|
||||
}
|
||||
if ($orderInfo->shipping_type == 2) {
|
||||
throw new ValidateException('核销订单不能发货!');
|
||||
}
|
||||
if (isset($orderInfo['pinkStatus']) && $orderInfo['pinkStatus'] != 2) {
|
||||
throw new ValidateException('拼团未完成暂不能发货!');
|
||||
}
|
||||
$store_id = $this->getItem('store_id', 0);
|
||||
$supplier_id = $this->getItem('supplier_id', 0);
|
||||
|
||||
//拆分完整主订单查询未发货子订单
|
||||
if ($orderInfo['pid'] == -1) {
|
||||
$orderInfo = $this->dao->get(['pid' => $id, 'status' => 0, 'supplier_id' => $supplier_id, 'refund_type' => [0, 3]], ['*'], ['pink']);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能发货!');
|
||||
}
|
||||
$id = (int)$orderInfo['id'];
|
||||
}
|
||||
/** @var StoreOrderRefundServices $storeOrderRefundServices */
|
||||
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
if ($storeOrderRefundServices->count(['store_order_id' => $id, 'refund_type' => [1, 2, 4, 5, 6], 'is_cancel' => 0, 'is_del' => 0])) {
|
||||
throw new ValidateException('订单有售后申请请先处理');
|
||||
}
|
||||
//取消预售订单 验证预售活动是否结束
|
||||
// if ($orderInfo['type'] == 6) {
|
||||
// /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
// $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
// $cartInfo = $storeOrderCartInfoServices->getOrderCartInfo($id);
|
||||
// $time = time();
|
||||
// foreach ($cartInfo as $cart) {
|
||||
// if (isset($cart['cart_info']['productInfo']['presale_end_time']) && $cart['cart_info']['productInfo']['presale_end_time'] > $time) {
|
||||
// throw new ValidateException('预售活动暂未结束,请稍后发货');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
$cart_ids = $data['cart_ids'];
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
//检测选择商品是否还可拆分
|
||||
$storeOrderCartInfoServices->checkCartIdsIsSplit($id, $cart_ids);
|
||||
unset($data['cart_ids']);
|
||||
return $this->transaction(function () use ($id, $cart_ids, $orderInfo, $data, $storeOrderCartInfoServices, $staff_id) {
|
||||
/** @var StoreOrderSplitServices $storeOrderSplitServices */
|
||||
$storeOrderSplitServices = app()->make(StoreOrderSplitServices::class);
|
||||
//拆单
|
||||
$splitResult = $storeOrderSplitServices->equalSplit($id, $cart_ids, $orderInfo, 0, false, $data['erp_id'] ?? 0);
|
||||
if ($splitResult) {//拆分发货
|
||||
[$orderInfo, $otherOrder] = $splitResult;
|
||||
|
||||
//拆分订单执行发货
|
||||
$this->doDelivery((int)$orderInfo->id, $orderInfo, $data);
|
||||
//检测原订单商品是否 全部拆分发货完成 改原订单状态
|
||||
$status_data = ['oid' => $id, 'change_time' => time()];
|
||||
if (!$storeOrderCartInfoServices->getSplitCartList($id)) {//发货完成
|
||||
$change_type = 'delivery_split';
|
||||
$change_message = '已拆分发货';
|
||||
} else {
|
||||
$change_type = 'delivery_part_split';
|
||||
$change_message = '已拆分部分发货';
|
||||
}
|
||||
//记录原订单状态
|
||||
OrderStatusJob::dispatch([$id, $change_type, ['change_message' => $change_message, 'change_manager_type' => 'system']]);
|
||||
} else {//整体发货
|
||||
$this->delivery($id, $data, $staff_id);
|
||||
}
|
||||
return $splitResult;
|
||||
});
|
||||
// return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 具体执行发货
|
||||
* @param int $id
|
||||
* @param $orderInfo
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function doDelivery(int $id, $orderInfo, array $data)
|
||||
{
|
||||
$type = (int)$data['type'];
|
||||
unset($data['type']);
|
||||
//获取购物车内的商品标题
|
||||
/** @var StoreOrderCartInfoServices $orderInfoServices */
|
||||
$orderInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$storeName = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id']);
|
||||
if (isset($data['pickup_time']) && count($data['pickup_time']) == 2) {
|
||||
$data['pickup_start_time'] = $data['pickup_time'][0];
|
||||
$data['pickup_end_time'] = $data['pickup_time'][1];
|
||||
} else {
|
||||
$data['pickup_start_time'] = '';
|
||||
$data['pickup_end_time'] = '';
|
||||
}
|
||||
//修改返回数据
|
||||
$res = [];
|
||||
switch ($type) {
|
||||
case 1://快递发货
|
||||
|
||||
$res = $this->orderDeliverGoods($id, $data, $orderInfo, $storeName);
|
||||
break;
|
||||
case 2://配送
|
||||
$this->orderDelivery($id, $data, $orderInfo);
|
||||
break;
|
||||
case 3://虚拟发货
|
||||
$this->orderVirtualDelivery($id, $data);
|
||||
break;
|
||||
case 4://门店收银订单自动发货
|
||||
$this->dao->update($orderInfo['id'], ['delivery_type' => 'cashier']);
|
||||
OrderStatusJob::dispatch([$orderInfo['id'], 'delivery_cashier', ['change_message' => '门店收银台核销', 'change_manager_type' => 'system']]);
|
||||
break;
|
||||
default:
|
||||
throw new ValidateException('暂时不支持其他发货类型');
|
||||
}
|
||||
$orderInfo = $this->dao->get($id);
|
||||
event('order.delivery', [$orderInfo, $storeName, $data, $type]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单快递发货
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function orderDeliverGoods(int $id, array $data, $orderInfo, $storeTitle)
|
||||
{
|
||||
if (!$data['delivery_name']) {
|
||||
throw new ValidateException('请选择快递公司');
|
||||
}
|
||||
//修改
|
||||
$dump = [];
|
||||
$data['delivery_type'] = 'express';
|
||||
/** @var StoreOrderCartInfoServices $orderInfoServices */
|
||||
$orderInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
if ($data['express_record_type'] == 2) {//电子面单
|
||||
if (!sys_config('config_export_open', 0)) {
|
||||
throw new ValidateException('系统通知:电子面单已关闭,请选择其他发货方式!');
|
||||
}
|
||||
if (!$data['delivery_code']) {
|
||||
throw new ValidateException('快递公司编缺失');
|
||||
}
|
||||
if (!$data['express_temp_id']) {
|
||||
throw new ValidateException('请选择电子面单模板');
|
||||
}
|
||||
if (!$data['to_name']) {
|
||||
throw new ValidateException('请填写寄件人姓名');
|
||||
}
|
||||
if (!$data['to_tel']) {
|
||||
throw new ValidateException('请填写寄件人电话');
|
||||
}
|
||||
if (!$data['to_addr']) {
|
||||
throw new ValidateException('请填写寄件人地址');
|
||||
}
|
||||
$expData['com'] = $data['delivery_code'];
|
||||
$expData['to_name'] = $orderInfo['real_name'];
|
||||
$expData['to_tel'] = $orderInfo['user_phone'];
|
||||
$expData['to_addr'] = $orderInfo['user_address'];
|
||||
$expData['from_name'] = $data['to_name'];
|
||||
$expData['from_tel'] = $data['to_tel'];
|
||||
$expData['from_addr'] = $data['to_addr'];
|
||||
$expData['siid'] = sys_config('config_export_siid');
|
||||
$expData['temp_id'] = $data['express_temp_id'];
|
||||
$expData['count'] = $orderInfo['total_num'];
|
||||
$expData['weight'] = $this->getOrderSumWeight($id);
|
||||
$expData['cargo'] = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id'], true);
|
||||
$expData['order_id'] = $orderInfo['order_id'];
|
||||
$expData['customParam'] = json_encode([
|
||||
'product_name' => $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id'], true)
|
||||
]);
|
||||
/** @var ServeServices $expressService */
|
||||
$expressService = app()->make(ServeServices::class);
|
||||
$dump = $expressService->express()->dump($expData);
|
||||
$data['express_dump'] = json_encode([
|
||||
'com' => $expData['com'],
|
||||
'from_name' => $expData['from_name'],
|
||||
'from_tel' => $expData['from_tel'],
|
||||
'from_addr' => $expData['from_addr'],
|
||||
'temp_id' => $expData['temp_id'],
|
||||
'cargo' => $expData['cargo'],
|
||||
]);
|
||||
$data['delivery_id'] = $dump['kuaidinum'] ?? '';
|
||||
$orderInfo->delivery_id = $dump['kuaidinum'] ?? '';
|
||||
//修改快递面单图片写入数据库
|
||||
if (!empty($dump['label'])) {
|
||||
$data['kuaidi_label'] = $dump['label'];
|
||||
}
|
||||
} elseif ($data['express_record_type'] == 3) {
|
||||
//商家寄件
|
||||
if (!$data['delivery_code']) {
|
||||
throw new ValidateException('快递公司编缺失');
|
||||
}
|
||||
if (!$data['express_temp_id']) {
|
||||
throw new ValidateException('请选择电子面单模板');
|
||||
}
|
||||
if (!$data['to_name']) {
|
||||
throw new ValidateException('请填写寄件人姓名');
|
||||
}
|
||||
if (!$data['to_tel']) {
|
||||
throw new ValidateException('请填写寄件人电话');
|
||||
}
|
||||
if (!$data['to_addr']) {
|
||||
throw new ValidateException('请填写寄件人地址');
|
||||
}
|
||||
/** @var ServeServices $expressService */
|
||||
$expressService = app()->make(ServeServices::class);
|
||||
$expData['kuaidicom'] = $data['delivery_code'];
|
||||
$expData['man_name'] = $orderInfo->real_name;
|
||||
$expData['phone'] = $orderInfo->user_phone;
|
||||
$expData['address'] = $orderInfo->user_address;
|
||||
$expData['send_real_name'] = $data['to_name'];
|
||||
$expData['send_phone'] = $data['to_tel'];
|
||||
$expData['send_address'] = $data['to_addr'];
|
||||
$expData['temp_id'] = $data['express_temp_id'];
|
||||
$expData['weight'] = $this->getOrderSumWeight($id);
|
||||
$expData['cargo'] = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo->id, true);
|
||||
$expData['day_type'] = $data['day_type'];
|
||||
$expData['pickup_start_time'] = $data['pickup_start_time'];
|
||||
$expData['pickup_end_time'] = $data['pickup_end_time'];
|
||||
// if (!sys_config('config_shippment_open', 0)) {
|
||||
// throw new AdminException('商家寄件未开启无法寄件');
|
||||
// }
|
||||
$dump = $expressService->express()->shippmentCreateOrder($expData);
|
||||
Log::error('商家寄件返回数据:' . json_encode($dump));
|
||||
$orderInfo->delivery_id = $dump['kuaidinum'] ?? '';
|
||||
$data['express_dump'] = json_encode([
|
||||
'com' => $expData['kuaidicom'],
|
||||
'from_name' => $expData['send_real_name'],
|
||||
'from_tel' => $expData['send_phone'],
|
||||
'from_addr' => $expData['send_address'],
|
||||
'temp_id' => $expData['temp_id'],
|
||||
'cargo' => $expData['cargo'],
|
||||
]);
|
||||
$data['delivery_id'] = $dump['kuaidinum'] ?? '';
|
||||
$data['kuaidi_label'] = $dump['label'] ?? '';
|
||||
$data['kuaidi_task_id'] = $dump['task_id'] ?? '';
|
||||
$data['kuaidi_order_id'] = $dump['order_id'] ?? '';
|
||||
} else {
|
||||
if (!$data['delivery_id']) {
|
||||
throw new ValidateException('请输入快递单号');
|
||||
}
|
||||
$orderInfo->delivery_id = $data['delivery_id'];
|
||||
}
|
||||
|
||||
if ($data['express_record_type'] != 3) {
|
||||
|
||||
$data['status'] = 1;
|
||||
$this->transaction(function () use ($id, $data) {
|
||||
$res = $this->dao->update($id, $data);
|
||||
if (!$res) {
|
||||
throw new ValidateException('发货失败:数据保存不成功');
|
||||
}
|
||||
//记录主订单状态
|
||||
OrderStatusJob::dispatch([$id, 'delivery_goods', ['change_message' => '已发货 快递公司:' . $data['delivery_name'] . ' 快递单号:' . $data['delivery_id'], 'change_manager_id' => request()->adminId(), 'change_manager_type' => 'admin']]);
|
||||
});
|
||||
} else {
|
||||
|
||||
$update = [
|
||||
'is_stock_up' => 1,
|
||||
'delivery_type' => $data['delivery_type'],
|
||||
'delivery_name' => $data['delivery_name'],
|
||||
'delivery_code' => $data['delivery_code'],
|
||||
'delivery_id' => $data['delivery_id'],
|
||||
'kuaidi_label' => $data['kuaidi_label'],
|
||||
'kuaidi_task_id' => $data['kuaidi_task_id'],
|
||||
'kuaidi_order_id' => $data['kuaidi_order_id'],
|
||||
'express_dump' => $data['express_dump']
|
||||
];
|
||||
|
||||
/** @var StoreOrderStatusServices $services */
|
||||
$services = app()->make(StoreOrderStatusServices::class);
|
||||
$this->transaction(function () use ($id, $data, $services, $update) {
|
||||
$res = $this->dao->update($id, $update);
|
||||
$res = $res && $services->save([
|
||||
'oid' => $id,
|
||||
'change_time' => time(),
|
||||
'change_type' => 'stock_up_goods',
|
||||
'change_message' => '备货中 快递公司:' . $data['delivery_name'] . ' 快递单号:' . $data['delivery_id']
|
||||
]);
|
||||
if (!$res) {
|
||||
throw new AdminException('发货失败:数据保存不成功');
|
||||
}
|
||||
});
|
||||
}
|
||||
return $dump;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单配送
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function orderDelivery(int $id, array $data, $orderInfo = [])
|
||||
{
|
||||
$data['delivery_name'] = $data['sh_delivery_name'];
|
||||
$data['delivery_id'] = $data['sh_delivery_id'];
|
||||
$data['delivery_uid'] = $data['sh_delivery_uid'];
|
||||
$delivery_type = $data['delivery_type'] ?? 1;
|
||||
$delivery_type = $delivery_type ? $delivery_type : 1;
|
||||
$station_type = $data['station_type'] ?? 1;
|
||||
unset($data['delivery_type'], $data['station_type']);
|
||||
switch ($delivery_type) {
|
||||
case 1://自己配送
|
||||
if (!$data['delivery_name']) {
|
||||
throw new ValidateException('请输入送货人姓名');
|
||||
}
|
||||
if (!$data['delivery_id']) {
|
||||
throw new ValidateException('请输入送货人电话号码');
|
||||
}
|
||||
if (!$data['delivery_uid']) {
|
||||
throw new ValidateException('请输入送货人信息');
|
||||
}
|
||||
if (!check_phone($data['delivery_id'])) {
|
||||
throw new ValidateException('请输入正确的送货人电话号码');
|
||||
}
|
||||
//获取核销码
|
||||
/** @var StoreOrderCreateServices $storeOrderCreateService */
|
||||
$storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
|
||||
$data['verify_code'] = $storeOrderCreateService->getStoreCode();
|
||||
$data['delivery_type'] = 'send';
|
||||
break;
|
||||
case 2://第三方配送
|
||||
if (!isset($data['cargo_weight']) || !$data['cargo_weight']) {
|
||||
throw new ValidateException('请填写配送商品重量');
|
||||
}
|
||||
$data['delivery_type'] = 'city_delivery';
|
||||
/** @var StoreDeliveryOrderServices $storeDeliverOrderServices */
|
||||
$storeDeliverOrderServices = app()->make(StoreDeliveryOrderServices::class);
|
||||
$storeDeliverOrderServices->create($id, $data, $station_type, $orderInfo);
|
||||
break;
|
||||
}
|
||||
$data['status'] = 1;
|
||||
|
||||
unset($data['sh_delivery_name'], $data['sh_delivery_id'], $data['sh_delivery_uid'], $data['delivery_remark']);
|
||||
|
||||
|
||||
$this->transaction(function () use ($id, $data, $delivery_type, $station_type) {
|
||||
//修改订单发货信息
|
||||
$this->dao->update($id, $data);
|
||||
if ($delivery_type == 1) {
|
||||
$message = '已配送 发货人:' . $data['delivery_name'] . ' 发货人电话:' . $data['delivery_id'];
|
||||
} else {
|
||||
$message = '已' . ($station_type == 1 ? '达达' : 'UU跑腿') . '同城配送';
|
||||
}
|
||||
//记录主订单状态
|
||||
OrderStatusJob::dispatch([$id, $delivery_type == 1 ? 'delivery' : 'city_delivery', ['change_message' => $message, 'change_manager_type' => 'system']]);
|
||||
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 虚拟发货
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function orderVirtualDelivery(int $id, array $data)
|
||||
{
|
||||
$data['delivery_type'] = 'fictitious';
|
||||
$data['status'] = 1;
|
||||
unset($data['sh_delivery_name'], $data['sh_delivery_id'], $data['delivery_name'], $data['delivery_id'], $data['delivery_remark']);
|
||||
//保存信息
|
||||
|
||||
return $this->transaction(function () use ($id, $data) {
|
||||
$this->dao->update($id, $data);
|
||||
|
||||
//记录主订单状态
|
||||
OrderStatusJob::dispatch([$id, 'delivery_fictitious', ['change_message' => '已虚拟发货', 'change_manager_id' => request()->adminId(), 'change_manager_type' => 'admin']]);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发货发送短信
|
||||
* @param $orderInfo
|
||||
*/
|
||||
public function deliverySmsSendAfter($orderInfo, string $store_name)
|
||||
{
|
||||
$order_id = $orderInfo->order_id;
|
||||
$switch = (bool)sys_config('deliver_goods_switch');
|
||||
$service = app()->make(UserServices::class);
|
||||
$nickname = $service->value(['uid' => $orderInfo->uid], 'nickname');
|
||||
|
||||
/** @var SmsSendServices $smsServices */
|
||||
$smsServices = app()->make(SmsSendServices::class);
|
||||
$smsServices->send($switch, $orderInfo->user_phone, compact('order_id', 'store_name', 'nickname'), 'DELIVER_GOODS_CODE', '用户发货发送短信失败,订单号为:' . $order_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修改配送信息表单结构
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function distributionForm(int $id)
|
||||
{
|
||||
if (!$orderInfo = $this->dao->get($id))
|
||||
throw new ValidateException('订单不存在');
|
||||
|
||||
$f[] = Form::input('order_id', '订单号', $orderInfo->getData('order_id'))->disabled(1);
|
||||
|
||||
switch ($orderInfo['delivery_type']) {
|
||||
case 'send'://送货
|
||||
$f[] = Form::input('delivery_name', '送货人姓名', $orderInfo->getData('delivery_name'))->required('请输入送货人姓名');
|
||||
$f[] = Form::input('delivery_id', '送货人电话', $orderInfo->getData('delivery_id'))->required('请输入送货人电话');
|
||||
break;
|
||||
case 'express'://快递
|
||||
/** @var ExpressServices $expressServices */
|
||||
$expressServices = app()->make(ExpressServices::class);
|
||||
$f[] = Form::select('delivery_name', '快递公司', (string)$orderInfo->getData('delivery_name'))->setOptions(array_map(function ($item) {
|
||||
$item['value'] = $item['label'];
|
||||
return $item;
|
||||
}, $expressServices->expressSelectForm(['is_show' => 1])))->filterable(true)->required('请选择快递公司');
|
||||
$f[] = Form::input('delivery_id', '快递单号', $orderInfo->getData('delivery_id'))->required('请填写快递单号');
|
||||
break;
|
||||
case 'fictitious'://虚拟发货
|
||||
$f[] = Form::input('fictitious_content', '备注', $orderInfo->getData('fictitious_content'));
|
||||
break;
|
||||
}
|
||||
return create_form('配送信息', $f, $this->url('/order/distribution/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配送信息
|
||||
* @param int $id 订单id
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateDistribution(int $id, array $data)
|
||||
{
|
||||
$order = $this->dao->get($id);
|
||||
if (!$order) {
|
||||
throw new ValidateException('数据不存在!');
|
||||
}
|
||||
switch ($order['delivery_type']) {
|
||||
case 'send':
|
||||
if (!$data['delivery_name']) {
|
||||
throw new ValidateException('请输入送货人姓名');
|
||||
}
|
||||
if (!$data['delivery_id']) {
|
||||
throw new ValidateException('请输入送货人电话号码');
|
||||
}
|
||||
if (!check_phone($data['delivery_id'])) {
|
||||
throw new ValidateException('请输入正确的送货人电话号码');
|
||||
}
|
||||
break;
|
||||
case 'express':
|
||||
if (!$data['delivery_name']) {
|
||||
throw new ValidateException('请选择快递公司');
|
||||
}
|
||||
if (!$data['delivery_id']) {
|
||||
throw new ValidateException('请输入快递单号');
|
||||
}
|
||||
break;
|
||||
case 'fictitious':
|
||||
break;
|
||||
default:
|
||||
throw new ValidateException('未发货,请先发货再修改配送信息');
|
||||
break;
|
||||
}
|
||||
$this->dao->update($id, $data);
|
||||
OrderStatusJob::dispatch([$id, 'distribution', ['change_message' => '修改发货信息为' . $data['delivery_name'] . '号' . $data['delivery_id'], 'change_manager_id' => request()->adminId(), 'change_manager_type' => 'admin']]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单发货后打印电子面单
|
||||
* @param $orderId
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function orderDump($orderId)
|
||||
{
|
||||
if (!$orderId) throw new ValidateException('订单号缺失');
|
||||
/** @var StoreOrderServices $orderService */
|
||||
$orderService = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $orderService->getOne(['id' => $orderId]);
|
||||
if (!$orderInfo) throw new ValidateException('订单不存在');
|
||||
if (in_array($orderInfo->shipping_type, [2, 4])) throw new ValidateException('订单无法打印');
|
||||
if (!$orderInfo->express_dump) throw new ValidateException('请先发货');
|
||||
if (!sys_config('config_export_open', 0)) {
|
||||
throw new ValidateException('请先在系统设置中打开单子面单打印开关');
|
||||
}
|
||||
$dumpInfo = json_decode($orderInfo->express_dump, true);
|
||||
/** @var ServeServices $expressService */
|
||||
$expressService = app()->make(ServeServices::class);
|
||||
$expData['com'] = $dumpInfo['com'];
|
||||
$expData['to_name'] = $orderInfo->real_name;
|
||||
$expData['to_tel'] = $orderInfo->user_phone;
|
||||
$expData['to_addr'] = $orderInfo->user_address;
|
||||
$expData['from_name'] = $dumpInfo['from_name'];
|
||||
$expData['from_tel'] = $dumpInfo['from_tel'];
|
||||
$expData['from_addr'] = $dumpInfo['from_addr'];
|
||||
$expData['siid'] = sys_config('config_export_siid');
|
||||
$expData['temp_id'] = $dumpInfo['temp_id'];
|
||||
$expData['cargo'] = $dumpInfo['cargo'];
|
||||
$expData['count'] = $orderInfo->total_num;
|
||||
$expData['weight'] = $this->getOrderSumWeight((int)$orderId);
|
||||
$expData['order_id'] = $orderInfo->order_id;
|
||||
try {
|
||||
$dump = $expressService->express()->dump($expData);
|
||||
$data['express_dump'] = json_encode([
|
||||
'com' => $expData['com'],
|
||||
'from_name' => $expData['from_name'],
|
||||
'from_tel' => $expData['from_tel'],
|
||||
'from_addr' => $expData['from_addr'],
|
||||
'temp_id' => $expData['temp_id'],
|
||||
'cargo' => $expData['cargo'],
|
||||
]);
|
||||
$data['delivery_id'] = $dump['kuaidinum'] ?? '';
|
||||
//修改快递面单图片写入数据库
|
||||
if (!empty($dump['label'])) {
|
||||
$data['kuaidi_label'] = $dump['label'];
|
||||
}
|
||||
$orderService->update($orderId, $data);
|
||||
} catch (\Throwable $e) {
|
||||
$dump = [];
|
||||
}
|
||||
return $dump;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回订单商品总重量
|
||||
* @param int $id
|
||||
* @return int|string
|
||||
*/
|
||||
public function getOrderSumWeight(int $id, $default = false)
|
||||
{
|
||||
/** @var StoreOrderCartInfoServices $services */
|
||||
$services = app()->make(StoreOrderCartInfoServices::class);
|
||||
$orderGoodInfo = $services->getOrderCartInfo((int)$id);
|
||||
$weight = 0;
|
||||
foreach ($orderGoodInfo as $cartInfo) {
|
||||
$cart = $cartInfo['cart_info'] ?? [];
|
||||
if ($cart) {
|
||||
$weight = bcadd((string)$weight, (string)bcmul((string)$cart['cart_num'] ?? '0', (string)$cart['productInfo']['attrInfo']['weight'] ?? '0', 4), 2);
|
||||
}
|
||||
}
|
||||
return $weight ? $weight : ($default === false ? 0 : $default);
|
||||
}
|
||||
}
|
||||
82
app/services/order/StoreOrderEconomizeServices.php
Normal file
82
app/services/order/StoreOrderEconomizeServices.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderEconomizeDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 计算节省金额
|
||||
* Class StoreOrderEconomizeServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderEconomizeDao
|
||||
*/
|
||||
class StoreOrderEconomizeServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var StoreOrderEconomizeDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderEconomizeDao $dao;
|
||||
|
||||
/**
|
||||
* 添加节省金额数据
|
||||
* @param array $add
|
||||
* @return \crmeb\basic\BaseModel|\think\Model
|
||||
*/
|
||||
public function addEconomize(array $add)
|
||||
{
|
||||
if (!$add) throw new ValidateException('数据不存在');
|
||||
return $this->dao->save($add);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $where
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOne(array $where)
|
||||
{
|
||||
if (!$where) throw new ValidateException('条件缺失');
|
||||
return $this->dao->getOne($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总付费会员节省金额
|
||||
* @param $uid
|
||||
* @return float
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function sumEconomizeMoney($uid)
|
||||
{
|
||||
$economizeMoney = 0.00;
|
||||
if (!$uid) return $economizeMoney;
|
||||
$list = $this->dao->getList(['uid' => $uid]);
|
||||
if ($list) {
|
||||
foreach ($list as $k => $v) {
|
||||
$economizeMoney += $v['postage_price'];
|
||||
$economizeMoney += $v['member_price'];
|
||||
$economizeMoney += $v['offline_price'];
|
||||
$economizeMoney += $v['coupon_price'];
|
||||
}
|
||||
}
|
||||
return (float)sprintf("%.2f", $economizeMoney);
|
||||
}
|
||||
}
|
||||
244
app/services/order/StoreOrderInvoiceServices.php
Normal file
244
app/services/order/StoreOrderInvoiceServices.php
Normal file
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use app\dao\order\StoreOrderInvoiceDao;
|
||||
use app\services\user\UserInvoiceServices;
|
||||
|
||||
|
||||
/**
|
||||
* Class StoreOrderInvoiceServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderInvoiceDao
|
||||
*/
|
||||
class StoreOrderInvoiceServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderInvoiceDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderInvoiceDao $dao;
|
||||
|
||||
/**
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2023/9/18
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function chart(array $where)
|
||||
{
|
||||
//全部
|
||||
$data['all'] = (string)$this->dao->count(['is_pay' => 1, 'is_del' => 0, 'time' => $where['time']]);
|
||||
//待开
|
||||
$data['noOpened'] = (string)$this->dao->count(['is_pay' => 1, 'is_del' => 0, 'time' => $where['time'], 'type' => 1]);
|
||||
//已开
|
||||
$data['opened'] = (string)$this->dao->count(['is_pay' => 1, 'is_del' => 0, 'time' => $where['time'], 'type' => 2]);
|
||||
//退款
|
||||
$data['refund'] = (string)$this->dao->count(['is_pay' => 1, 'is_del' => 0, 'time' => $where['time'], 'type' => 3]);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台获取开票列表
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $list] = $this->getPageValue();
|
||||
$field = 'id as invoice_id,order_id,header_type,type,name,invoice_amount,duty_number,drawer_phone,email,tell,address,bank,card_number,is_invoice,invoice_number,remark as invoice_reamrk,invoice_time,add_time as invoice_add_time';
|
||||
$where['is_pay'] = 1;
|
||||
$where['is_del'] = 0;
|
||||
$list = $this->dao->getList($where, $field, ['order' => function ($query) {
|
||||
$query->field('id,order_id,pay_price,add_time,real_name,user_phone,status,refund_status');
|
||||
}], 'add_time desc', $page, $list);
|
||||
foreach ($list as &$item) {
|
||||
$item['id'] = $item['order']['id'] ?? 0;
|
||||
$item['order_id'] = $item['order']['order_id'] ?? '';
|
||||
$item['pay_price'] = $item['order']['pay_price'] ?? 0.00;
|
||||
$item['real_name'] = $item['order']['real_name'] ?? '';
|
||||
$item['user_phone'] = $item['order']['user_phone'] ?? '';
|
||||
$item['status'] = $item['order']['status'] ?? '';
|
||||
$item['refund_status'] = $item['order']['refund_status'] ?? 0;
|
||||
$item['add_time'] = date('Y-m-d H:i:s', $item['order']['add_time'] ?? $item['invoice_add_time'] ?? time());
|
||||
$item['invoice_add_time'] = date('Y-m-d H:i:s', $item['invoice_add_time']);
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端获取开票列表(带商品信息)
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderInvoiceList(array $where)
|
||||
{
|
||||
[$page, $list] = $this->getPageValue();
|
||||
$where['is_pay'] = 1;
|
||||
$where['is_del'] = 0;
|
||||
$where['is_refund'] = 0;
|
||||
$list = $this->dao->getList($where, '*', ['order'], 'add_time desc', $page, $list);
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
foreach ($list as &$item) {
|
||||
if (isset($item['order']) && $item['order']) {
|
||||
$item['order'] = $storeOrderServices->tidyOrder($item['order'], true);
|
||||
if (isset($item['order']['_status']['_type']) && $item['order']['_status']['_type'] == 3) {
|
||||
foreach ($item['order']['cartInfo'] ?: [] as $key => $product) {
|
||||
$item['order']['cartInfo'][$key]['add_time'] = isset($product['add_time']) ? date('Y-m-d H:i', (int)$product['add_time']) : '时间错误';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单申请开票
|
||||
* @param int $uid
|
||||
* @param $order_id
|
||||
* @param int $invoice_id
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function makeUp(int $uid, $order_id, int $invoice_id)
|
||||
{
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
/** @var UserInvoiceServices $userInvoiceServices */
|
||||
$userInvoiceServices = app()->make(UserInvoiceServices::class);
|
||||
$order = $storeOrderServices->getOne(['order_id|id' => $order_id, 'is_del' => 0]);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
if ($order['pay_price'] <= 0) {
|
||||
throw new ValidateException('订单实际支付金额为0,不能开发票');
|
||||
}
|
||||
//检测再带查询
|
||||
$invoice = $userInvoiceServices->checkInvoice($invoice_id, $uid);
|
||||
$info= $this->dao->getOne(['order_id' => $order['id'], 'uid' => $uid]);
|
||||
if ($info && $info['is_invoice'] != -1) {
|
||||
throw new ValidateException('发票已申请,正在审核打印中');
|
||||
}
|
||||
if ($order['refund_status'] == 2) {
|
||||
throw new ValidateException('订单已退款');
|
||||
}
|
||||
if ($order['refund_status'] == 1) {
|
||||
throw new ValidateException('正在申请退款中');
|
||||
}
|
||||
unset($invoice['id'], $invoice['add_time']);
|
||||
$data = [];
|
||||
$data['category'] = 'order';
|
||||
$data['order_id'] = $order['id'];
|
||||
$data['invoice_id'] = $invoice_id;
|
||||
$data['add_time'] = time();
|
||||
$data['is_pay'] = $order['paid'] == 1 ? 1 : 0;
|
||||
$data = array_merge($data, $invoice);
|
||||
if (!$re = $this->dao->save($data)) {
|
||||
throw new ValidateException('申请失败,请稍后重试');
|
||||
}
|
||||
return ['id' => $re->id];
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置处理发票
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function setInvoice(int $id, array $data)
|
||||
{
|
||||
$orderInvoice = $this->dao->get($id);
|
||||
if (!$orderInvoice) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$data['invoice_time'] = time();
|
||||
if (!$this->dao->update($id, $data, 'id')) {
|
||||
throw new ValidateException('设置失败,请重试');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单id获取发票信息
|
||||
* @param int $oid
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOneInvoice(int $oid)
|
||||
{
|
||||
$info = $this->dao->get(['order_id' => $oid]);
|
||||
$info = $info ? $info->toArray() : [];
|
||||
if (!$info) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分订单同步拆分申请开票记录
|
||||
* @param int $oid
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function splitOrderInvoice(int $oid)
|
||||
{
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $storeOrderServices->getOne(['id' => $oid, 'is_del' => 0]);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$pid = $orderInfo['pid'] > 0 ? $orderInfo['pid'] : $orderInfo['id'];
|
||||
//查询开票记录
|
||||
$orderInvoice = $this->dao->get(['order_id' => $oid]);
|
||||
//查询子订单
|
||||
$spliteOrder = $storeOrderServices->getColumn(['pid' => $pid, 'is_system_del' => 0], 'id,order_id');
|
||||
if ($spliteOrder && $orderInvoice) {
|
||||
$data = $orderInvoice->toArray();
|
||||
unset($data['id']);
|
||||
$data['add_time'] = strtotime($data['add_time']);
|
||||
$data_all = [];
|
||||
foreach ($spliteOrder as $order) {
|
||||
if (!$this->dao->count(['order_id' => $order['id']])) {
|
||||
$data['order_id'] = $order['id'];
|
||||
$data_all[] = $data;
|
||||
}
|
||||
}
|
||||
if ($data_all) {
|
||||
$this->transaction(function () use ($data_all, $orderInvoice, $orderInfo) {
|
||||
$this->dao->saveAll($data_all);
|
||||
if ($orderInfo['pid'] <= 0) {
|
||||
$this->dao->delete(['id' => $orderInvoice['id']]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
194
app/services/order/StoreOrderPromotionsServices.php
Normal file
194
app/services/order/StoreOrderPromotionsServices.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
use app\dao\order\StoreOrderPromotionsDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class StoreOrderPromotionsServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderPromotionsDao
|
||||
*/
|
||||
class StoreOrderPromotionsServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderPromotionsDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderPromotionsDao $dao;
|
||||
|
||||
/**
|
||||
* 保存订单优惠详情
|
||||
* @param int $uid
|
||||
* @param int $oid
|
||||
* @param array $cartList
|
||||
* @param array $promotionsList
|
||||
* @return int
|
||||
*/
|
||||
public function setPromotionsDetail(int $uid, int $oid, array $cartList, array $promotionsList)
|
||||
{
|
||||
$group = [];
|
||||
if ($promotionsList) {
|
||||
$time = time();
|
||||
foreach ($cartList as $key => $cart) {
|
||||
foreach ($promotionsList as $promotions) {
|
||||
$details = $promotions['details'] ?? [];
|
||||
$unique = $cart['product_attr_unique'] ?? '';
|
||||
if ($details && isset($details[$unique]['sum_promotions_price'])) {
|
||||
$group[] = [
|
||||
'oid' => $oid,
|
||||
'uid' => $uid,
|
||||
'product_id' => $cart['productInfo']['id'],
|
||||
'promotions_id' => $promotions['id'],
|
||||
'promotions_price' => (float)$details[$unique]['sum_promotions_price'] ?? 0,
|
||||
'add_time' => $time
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($group) {
|
||||
return $this->dao->saveAll($group);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单商品实际参与优惠活动 以及优惠金额
|
||||
* @param int $oid
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderPromotionsDetail(int $oid)
|
||||
{
|
||||
$result = $this->dao->getPromotionsDetailList(['oid' => $oid], '*,sum(`promotions_price`) as promotions_price', ['promotions'], 'promotions_id');
|
||||
if ($result) {
|
||||
$typeArr = array_column($result, 'promotions_type');
|
||||
array_multisort($typeArr, SORT_ASC, $result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分订单同步拆分优惠活动记录
|
||||
* @param int $oid
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function splitOrderPromotions(int $oid)
|
||||
{
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $storeOrderServices->getOne(['id' => $oid, 'is_del' => 0]);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$promotions_give = [];
|
||||
$promotions = [];
|
||||
if (isset($orderInfo['promotions_give']) && $orderInfo['promotions_give']) {
|
||||
$promotions_give = is_string($orderInfo['promotions_give']) ? json_decode($promotions_give, true) : $orderInfo['promotions_give'];
|
||||
}
|
||||
$promotions = $promotions_give['promotions'] ?? [];
|
||||
$pid = $orderInfo['pid'] > 0 ? $orderInfo['pid'] : $orderInfo['id'];
|
||||
//查询优惠记录
|
||||
$orderPromotions = $this->dao->getPromotionsDetailList(['order_id' => $oid]);
|
||||
//查询子订单
|
||||
$spliteOrder = $storeOrderServices->getColumn(['pid' => $pid, 'is_system_del' => 0], 'id,order_id');
|
||||
if ($spliteOrder && $orderPromotions && $promotions) {
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$data_all = $data = [];
|
||||
$data['uid'] = $orderInfo['uid'];
|
||||
$data['add_time'] = time();
|
||||
foreach ($spliteOrder as $order) {
|
||||
$cartInfo = $storeOrderCartInfoServices->getColumn(['oid' => $order['id']], 'id,product_id,cart_num,cart_info');
|
||||
if (!$cartInfo) {
|
||||
continue;
|
||||
}
|
||||
$data['oid'] = $order['id'];
|
||||
foreach ($cartInfo as $key => $cart) {
|
||||
$data['product_id'] = $cart['product_id'];
|
||||
$_info = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
|
||||
$unique = $_info['product_attr_unique'] ?? '';
|
||||
foreach ($promotions as $key => $info) {
|
||||
if (isset($info['details'][$unique])) {
|
||||
$data['promotions_id'] = $info['id'];
|
||||
$data['promotions_price'] = floatval($info['details'][$unique]['sum_promotions_price'] ?? 0);
|
||||
$data_all[] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($data_all) {
|
||||
$this->transaction(function () use ($data_all, $spliteOrder) {
|
||||
$this->dao->delete(['oid' => array_column($spliteOrder, 'id')]);
|
||||
$this->dao->saveAll($data_all);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 申请退款订单优惠详情处理
|
||||
* @param int $oid
|
||||
* @param array $cartInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function applyRefundOrderPromotions(int $oid, array $cartInfo = [])
|
||||
{
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $storeOrderServices->getOne(['id' => $oid, 'is_del' => 0]);
|
||||
if (!$orderInfo) {
|
||||
return [];
|
||||
}
|
||||
$promotions_give = [];
|
||||
$promotions = [];
|
||||
if (isset($orderInfo['promotions_give']) && $orderInfo['promotions_give']) {
|
||||
$promotions_give = is_string($orderInfo['promotions_give']) ? json_decode($promotions_give, true) : $orderInfo['promotions_give'];
|
||||
}
|
||||
$promotions = $promotions_give['promotions'] ?? [];
|
||||
if (!$cartInfo || !$promotions) {
|
||||
return [];
|
||||
}
|
||||
$data_all = [];
|
||||
foreach ($promotions as $key => $info) {
|
||||
$data = [];
|
||||
foreach ($cartInfo as $key => $cart) {
|
||||
if (isset($info['details'][$cart['product_id']])) {
|
||||
$data['promotions_id'] = $info['id'];
|
||||
$data['promotions_type'] = $info['promotions_type'];
|
||||
$data['name'] = $info['name'];
|
||||
$data['title'] = $info['title'];
|
||||
$data['desc'] = $info['desc'];
|
||||
$data['promotions_price'] = bcadd((string)($data['promotions_price'] ?? 0), (string)($info['details'][$cart['product_id']]['sum_promotions_price'] ?? 0), 2);
|
||||
}
|
||||
}
|
||||
if ($data) {
|
||||
$data_all[] = $data;
|
||||
}
|
||||
}
|
||||
if ($data_all) {
|
||||
$typeArr = array_column($data_all, 'promotions_type');
|
||||
array_multisort($typeArr, SORT_ASC, $data_all);
|
||||
}
|
||||
return $data_all;
|
||||
}
|
||||
|
||||
}
|
||||
1418
app/services/order/StoreOrderRefundServices.php
Normal file
1418
app/services/order/StoreOrderRefundServices.php
Normal file
File diff suppressed because it is too large
Load Diff
2772
app/services/order/StoreOrderServices.php
Normal file
2772
app/services/order/StoreOrderServices.php
Normal file
File diff suppressed because it is too large
Load Diff
556
app/services/order/StoreOrderSplitServices.php
Normal file
556
app/services/order/StoreOrderSplitServices.php
Normal file
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\services\order;
|
||||
|
||||
use app\jobs\order\OrderStatusJob;
|
||||
use app\jobs\order\SpliteOrderAfterJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\store\SystemStoreServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 订单拆分
|
||||
* Class StoreOrderSplitServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderSplitServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 需要清空恢复默认数据字段
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $order_data = ['id', 'refund_status', 'refund_type', 'refund_express', 'refund_reason_wap_img', 'refund_reason_wap_explain', 'refund_reason_time', 'refund_reason_wap', 'refund_reason', 'refund_price'];
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 检测要拆分数组
|
||||
* @param int $id
|
||||
* @param array $cart_ids
|
||||
* @param array $orderInfo
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function checkCartNum(int $id, array $cart_ids, $orderInfo = [])
|
||||
{
|
||||
if (!$cart_ids) {
|
||||
return false;
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
$orderInfo = $this->dao->get($id, ['*']);
|
||||
}
|
||||
$total_num = array_sum(array_column($cart_ids, 'cart_num'));
|
||||
//商品和原订单一致,不拆分
|
||||
if ($total_num >= $orderInfo['total_num']) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平行拆分订单
|
||||
* @param int $id
|
||||
* @param array $cart_ids
|
||||
* @param array $orderInfo
|
||||
* @param int $store_id
|
||||
* @param bool $is_refund
|
||||
* @param int $erp_id
|
||||
* @return false
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function equalSplit(int $id, array $cart_ids, $orderInfo = [], int $store_id = 0, bool $is_refund = false, int $erp_id = 0)
|
||||
{
|
||||
if (!$cart_ids) {
|
||||
return false;
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
$orderInfo = $this->dao->get($id, ['*']);
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能拆分订单!');
|
||||
}
|
||||
if ($orderInfo['pid'] == -1) {
|
||||
throw new ValidateException('已拆分完毕,请返回列表重新操作');
|
||||
}
|
||||
if (!$this->checkCartNum($id, $cart_ids, $orderInfo)) {
|
||||
return false;
|
||||
}
|
||||
$orderInfo = is_object($orderInfo) ? $orderInfo->toArray() : $orderInfo;
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
//订单下原商品信息
|
||||
$cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'split_status' => [0, 1]], 'is_gift,cart_num,split_surplus_num', 'cart_id');
|
||||
$new_cart_ids = array_combine(array_column($cart_ids, 'cart_id'), $cart_ids);
|
||||
$other_cart_ids = $other = [];
|
||||
|
||||
foreach ($cartInfo as $cart_id => $cart) {
|
||||
if (!isset($new_cart_ids[$cart_id]) && $cart['split_surplus_num']) {//无拆分
|
||||
$other = ['cart_id' => $cart_id, 'cart_num' => $cart['split_surplus_num']];
|
||||
} else if ($new_cart_ids[$cart_id]['cart_num'] < $cart['split_surplus_num']) {
|
||||
$other = ['cart_id' => $cart_id, 'cart_num' => bcsub((string)$cart['split_surplus_num'], (string)$new_cart_ids[$cart_id]['cart_num'], 0)];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$other_cart_ids[] = $other;
|
||||
}
|
||||
$data = [$cart_ids, $other_cart_ids];
|
||||
$split_cart_ids = $cart_ids;
|
||||
if ($other_cart_ids && $orderInfo['status'] == 0 && $is_refund) {
|
||||
//拆分剩余 都是赠品
|
||||
$is_gift = true;
|
||||
foreach ($other_cart_ids as $cart) {
|
||||
if (!isset($cartInfo[$cart['cart_id']]) || !$cartInfo[$cart['cart_id']]['is_gift']) {
|
||||
$is_gift = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($is_gift) {//未发货 申请退款 整单退
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $storeOrderServices->tidyOrder($orderInfo, true, true);
|
||||
//核算优惠金额
|
||||
$vipTruePrice = 0;
|
||||
$refund_num = 0;
|
||||
$all_true_price = 0;
|
||||
foreach ($orderInfo['cartInfo'] ?? [] as $key => &$cart) {
|
||||
$vipTruePrice = bcadd((string)$vipTruePrice, (string)$cart['vip_sum_truePrice'], 2);
|
||||
$refund_num = bcadd((string)$refund_num, (string)$cart['refund_num'], 0);
|
||||
$all_true_price = bcadd((string)$all_true_price, bcmul((string)($cart['truePrice'] ?? 0), (string)$cart['cart_num'], 4), 2);
|
||||
}
|
||||
$orderInfo['vip_true_price'] = $vipTruePrice;
|
||||
$orderInfo['total_price'] = floatval(bcsub((string)$orderInfo['total_price'], (string)$vipTruePrice, 2));
|
||||
|
||||
//订单实际支付金额
|
||||
$order_pay_price = bcadd((string)$all_true_price, (string)$orderInfo['pay_postage'], 2);
|
||||
//有改价
|
||||
$change_price = $order_pay_price != $orderInfo['pay_price'];
|
||||
|
||||
$order = $this->transaction(function () use ($id, $data, $orderInfo, $store_id, $storeOrderCartInfoServices, $split_cart_ids, $is_refund, $change_price, $order_pay_price, $erp_id) {
|
||||
$order = [];
|
||||
$i = 0;
|
||||
$yue_price = $orderInfo['yue_price'];
|
||||
$online_price = $orderInfo['online_price'];
|
||||
foreach ($data as $key => $cart_ids) {
|
||||
if ($key == 0 && $erp_id > 0) {
|
||||
$orderInfo['erpId'] = $erp_id;
|
||||
}
|
||||
//生成新订单、处理cart_info
|
||||
[$new_id, $cart_data] = $this->splitV2($id, $cart_ids, $orderInfo, $i, $store_id, $is_refund, $split_cart_ids);
|
||||
//处理订单
|
||||
[$online_price, $yue_price] = $this->splitComputeOrder((int)$new_id, $cart_data, $orderInfo, (float)($change_price ? $order_pay_price : 0), (float)$orderInfo['pay_price'], (float)($order[0]['pay_price'] ?? 0), $online_price, $yue_price);
|
||||
$order[] = $this->dao->get($new_id);
|
||||
$i++;
|
||||
}
|
||||
//标记主订单拆分完成
|
||||
if (!$orderInfo['pid']) $this->dao->update($id, ['pid' => -1]);
|
||||
|
||||
//处理申请开票记录
|
||||
/** @var StoreOrderInvoiceServices $storeOrderInvoiceServics */
|
||||
$storeOrderInvoiceServics = app()->make(StoreOrderInvoiceServices::class);
|
||||
$storeOrderInvoiceServics->splitOrderInvoice((int)$id);
|
||||
//处理订单优惠活动记录
|
||||
/** @var StoreOrderPromotionsServices $storeOrderPromotionsServics */
|
||||
$storeOrderPromotionsServics = app()->make(StoreOrderPromotionsServices::class);
|
||||
$storeOrderPromotionsServics->splitOrderPromotions((int)$id);
|
||||
return $order;
|
||||
});
|
||||
//拆分完成后置队列 处理订单状态记录
|
||||
SpliteOrderAfterJob::dispatch([$id, $order]);
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单拆分
|
||||
* @param int $id
|
||||
* @param array $cart_ids
|
||||
* @param array $orderInfo
|
||||
* @param int $i
|
||||
* @param int $store_id
|
||||
* @param bool $is_refund
|
||||
* @param array $append
|
||||
* @return array|false
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function splitV2(int $id, array $cart_ids, $orderInfo = [], int $i = 0, int $store_id = 0, bool $is_refund = false, array $append = [])
|
||||
{
|
||||
$ids = array_unique(array_column($cart_ids, 'cart_id'));
|
||||
if (!$cart_ids || !$ids) {
|
||||
return false;
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
$orderInfo = $this->dao->get($id, ['*']);
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能拆分订单!');
|
||||
}
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
//订单下原商品信息
|
||||
$cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'cart_id' => $ids], '*', 'cart_id');
|
||||
if (!$cartInfo || count($cartInfo) != count($ids)) {
|
||||
return false;
|
||||
}
|
||||
if ($append) $append = array_combine(array_column($append, 'cart_id'), $append);
|
||||
|
||||
$is_not_split = $i && $orderInfo['pid'];
|
||||
|
||||
if ($is_not_split) {//保留原订单 不重新生成(只修改订单信息、订单商品信息)
|
||||
$new_id = $id;
|
||||
//删除原订单下商品信息
|
||||
$storeOrderCartInfoServices->delete(['oid' => $id]);
|
||||
//删除缓存
|
||||
$storeOrderCartInfoServices->clearOrderCartInfo($id);
|
||||
} else {
|
||||
/** @var StoreOrderCreateServices $storeOrderCreateServices */
|
||||
$storeOrderCreateServices = app()->make(StoreOrderCreateServices::class);
|
||||
$orderInfo = is_object($orderInfo) ? $orderInfo->toArray() : $orderInfo;
|
||||
|
||||
$pid = $orderInfo['pid'] ?: $orderInfo['id'];
|
||||
foreach ($this->order_data as $field) {
|
||||
unset($orderInfo[$field]);
|
||||
}
|
||||
//核销码重新生成
|
||||
if ($orderInfo['verify_code']) {
|
||||
$orderInfo['verify_code'] = $storeOrderCreateServices->getStoreCode();
|
||||
}
|
||||
$order_data = $orderInfo;
|
||||
$order_data['promotions_give'] = is_array($order_data['promotions_give']) ? json_encode($order_data['promotions_give']) : $order_data['promotions_give'];
|
||||
$order_data['give_coupon'] = is_array($order_data['give_coupon']) ? implode(',', $order_data['give_coupon']) : $order_data['give_coupon'];
|
||||
//$pid 平行拆分 0:子订单拆分
|
||||
$order_data['pid'] = $pid ?: $id;
|
||||
$parentOrder = $this->dao->get($order_data['pid']);
|
||||
$oldOrderId = $parentOrder['order_id'];
|
||||
$childCont = $this->dao->count(['pid' => $parentOrder['id']]);
|
||||
if ($store_id) {//门店分配拆分
|
||||
/** @var SystemStoreServices $storeServices */
|
||||
$storeServices = app()->make(SystemStoreServices::class);
|
||||
if (!$storeInfo = $storeServices->getStoreInfo($store_id)) {
|
||||
throw new ValidateException('门店不存在');
|
||||
}
|
||||
$order_data['store_id'] = $store_id;
|
||||
$order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
|
||||
if ($order_data['shipping_type'] == 1) {
|
||||
$order_data['shipping_type'] = 3;
|
||||
} else {//自提订单
|
||||
$order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
|
||||
// $order_data['verify_code'] = $storeOrderCreateServices->getStoreCode();
|
||||
}
|
||||
$change_type = 'store_split_create_order';
|
||||
$change_message = '门店分配拆分生成订单';
|
||||
} else {//发货拆分
|
||||
// $order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
|
||||
$order_data['order_id'] = $oldOrderId . '_' . ($childCont + 1);
|
||||
$change_type = 'split_create_order';
|
||||
$change_message = $is_refund ? '售后退款拆分生成订单' : '发货拆分生成订单';
|
||||
}
|
||||
$order_data['cart_id'] = [];
|
||||
$order_data['unique'] = $storeOrderCreateServices->getNewOrderId('');
|
||||
|
||||
$new_order = $this->dao->save($order_data);
|
||||
if (!$new_order) {
|
||||
throw new ValidateException('生成新订单失败');
|
||||
}
|
||||
$new_id = (int)$new_order->id;
|
||||
|
||||
OrderStatusJob::dispatch([$new_id, $change_type, ['change_message' => $change_message, 'change_manager_type' => 'system']]);
|
||||
|
||||
}
|
||||
//生成订单商品信息 保存
|
||||
$cart_data = $cart_data_all = $update_data = [];
|
||||
foreach ($cart_ids as $cart) {
|
||||
$split_surplus_num = $cartInfo[$cart['cart_id']]['split_surplus_num'] ?? 0;
|
||||
if (!isset($cartInfo[$cart['cart_id']]) || (!$is_not_split && !$split_surplus_num)) continue;
|
||||
$_info = is_string($cartInfo[$cart['cart_id']]['cart_info']) ? json_decode($cartInfo[$cart['cart_id']]['cart_info'], true) : $cartInfo[$cart['cart_id']]['cart_info'];
|
||||
$cart_data = $cartInfo[$cart['cart_id']];
|
||||
$cart_data['oid'] = $new_id;
|
||||
unset($cart_data['id']);
|
||||
$cart_data['split_surplus_num'] = $cart['cart_num'];
|
||||
$unit_write_times = max($_info['productInfo']['attrInfo']['write_times'] ?? 1, 1);
|
||||
$split_refund_num = $append[$cart['cart_id']]['cart_num'] ?? 0;
|
||||
if (!$is_not_split) {//新增cart_info
|
||||
$cart_data['cart_id'] = $storeOrderCreateServices->getNewOrderId('');
|
||||
$cart_data['product_id'] = $_info['product_id'];
|
||||
$cart_data['old_cart_id'] = $cart['cart_id'];
|
||||
$cart_data['unique'] = md5($cart_data['cart_id'] . '_' . $cart_data['oid']);
|
||||
// $cart_data['surplus_num'] = $cart['cart_num'];
|
||||
} else {//保留
|
||||
|
||||
}
|
||||
$refund_num = 0;
|
||||
$cart_num_times = bcmul((string)$cart['cart_num'], (string)$unit_write_times, 0);
|
||||
//拆出订单
|
||||
if (!$i) {
|
||||
//无核销 || 核销数量大于拆分数量
|
||||
$surplus_num = min($cart_data['write_surplus_times'], $cart_num_times);
|
||||
if ($is_refund) $refund_num = $cart['cart_num'];
|
||||
} else {//修改原订单
|
||||
//无核销 || 核销数量大于拆分数量
|
||||
if (!$cart_data['writeoff_time']) {
|
||||
$surplus_num = $cart_num_times;
|
||||
} else {
|
||||
$writoff_numm = bcsub((string)$cart_data['write_times'], (string)$cart_data['write_surplus_times'], 0);
|
||||
$surplus_num = $writoff_numm >= $cart_num_times ? 0 : bcsub((string)$cart_num_times, (string)$writoff_numm, 0);
|
||||
}
|
||||
if ($is_refund) $refund_num = $split_refund_num >= $cart_data['refund_num'] ? 0 : bcsub((string)$cart_data['refund_num'], (string)$split_refund_num, 0);
|
||||
}
|
||||
$cart_data['cart_num'] = $cart['cart_num'];
|
||||
$cart_data['write_times'] = bcmul((string)$cart['cart_num'], (string)$unit_write_times, 0);
|
||||
$cart_data['refund_num'] = max($refund_num, 0);
|
||||
$cart_data['write_surplus_times'] = max($surplus_num, 0);
|
||||
if (!$cart_data['write_surplus_times']) {//核销完毕
|
||||
$cart_data['is_writeoff'] = 1;
|
||||
} elseif ($cart_data['write_surplus_times'] == $cart_data['write_times']) {//未核销
|
||||
$cart_data['is_writeoff'] = 0;
|
||||
$cart_data['writeoff_time'] = 0;
|
||||
}
|
||||
if ($cart['cart_num'] >= $split_surplus_num) {//拆分完成
|
||||
$cart_data['cart_num'] = $split_surplus_num;
|
||||
$update_data['split_status'] = 2;
|
||||
$update_data['split_surplus_num'] = 0;
|
||||
} else {//拆分部分数量
|
||||
$update_data['split_surplus_num'] = bcsub((string)$split_surplus_num, $cart['cart_num'], 0);
|
||||
$update_data['split_status'] = $update_data['split_surplus_num'] > 0 ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
$_info = $this->slpitComputeOrderCart($cart_data['cart_num'], $_info, $i, !!($cart_data['is_gift'] ?? 0));
|
||||
$_info['id'] = $cart_data['cart_id'];
|
||||
$cart_data['cart_info'] = json_encode($_info);
|
||||
|
||||
//修改原来订单商品信息
|
||||
if (!$is_not_split && false === $storeOrderCartInfoServices->update(['oid' => $id, 'cart_id' => $cart['cart_id']], $update_data)) {
|
||||
throw new ValidateException('修改原来订单商品拆分状态失败,请稍候重试');
|
||||
}
|
||||
$cart_data_all[] = $cart_data;
|
||||
unset($cartInfo[$cart['cart_id']]);
|
||||
}
|
||||
|
||||
if (!$storeOrderCartInfoServices->saveAll($cart_data_all)) {
|
||||
throw new ValidateException('新增拆分订单商品信息失败');
|
||||
}
|
||||
return [$new_id, $cart_data_all];
|
||||
// $split_order_info = $this->dao->get($new_id);
|
||||
// $this->splitComputeOrder($new_id, $cart_data_all, $split_order_info);
|
||||
// return $split_order_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取整理后的订单商品信息
|
||||
* @param int $id
|
||||
* @param array $cart_ids
|
||||
* @param array $orderInfo
|
||||
* @return array|false
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSplitOrderCartInfo(int $id, array $cart_ids, $orderInfo = [])
|
||||
{
|
||||
$ids = array_unique(array_column($cart_ids, 'cart_id'));
|
||||
if (!$cart_ids || !$ids) {
|
||||
return false;
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
$orderInfo = $this->dao->get($id, ['*']);
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单未能查到,不能拆分订单!');
|
||||
}
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
|
||||
$storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'cart_id' => $ids], '*', 'cart_id');
|
||||
$cart_data_all = [];
|
||||
foreach ($cart_ids as $cart) {
|
||||
$split_surplus_num = $cartInfo[$cart['cart_id']]['split_surplus_num'] ?? 0;
|
||||
if (!isset($cartInfo[$cart['cart_id']]) || !$split_surplus_num) continue;
|
||||
$_info = is_string($cartInfo[$cart['cart_id']]['cart_info']) ? json_decode($cartInfo[$cart['cart_id']]['cart_info'], true) : $cartInfo[$cart['cart_id']]['cart_info'];
|
||||
$cart_data = $cartInfo[$cart['cart_id']];
|
||||
$cart_data['oid'] = $id;
|
||||
$cart_data['product_id'] = $_info['product_id'];
|
||||
$cart_data['old_cart_id'] = $cart['cart_id'];
|
||||
$cart_data['cart_num'] = $cart['cart_num'];
|
||||
$cart_data['surplus_num'] = $cart['cart_num'];
|
||||
$cart_data['split_surplus_num'] = $cart['cart_num'];
|
||||
|
||||
$_info = $this->slpitComputeOrderCart($cart_data['cart_num'], $_info);
|
||||
$_info['id'] = $cart_data['cart_id'];
|
||||
$cart_data['cart_info'] = $_info;
|
||||
$cart_data_all[] = $cart_data;
|
||||
unset($cartInfo[$cart['cart_id']]);
|
||||
}
|
||||
return $cart_data_all;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新计算新订单中价格等信息
|
||||
* @param int $id 订单号
|
||||
* @param array $cart_info_data 重新计算过订单商品信息
|
||||
* @param array $orderInfo 订单信息
|
||||
* @param float $order_pay_price 订单原来支付金额 0:没改价继续计算 >0 存在改价 需要计算新订单实际支付金额
|
||||
* @param float $pay_price 订单实际支付金额
|
||||
* @param float $pre_pay_price 上一个订单实际支付金额
|
||||
* @return bool|float[]
|
||||
*/
|
||||
public function splitComputeOrder(int $id, array $cart_info_data, $orderInfo = [], float $order_pay_price = 0.00, float $pay_price = 0.00, float $pre_pay_price = 0.00, float $online_price = 0.00, float $yue_price = 0.00)
|
||||
{
|
||||
$order_update['cart_id'] = array_column($cart_info_data, 'cart_id');
|
||||
$order_update['total_num'] = array_sum(array_column($cart_info_data, 'cart_num'));
|
||||
$cost_price = $total_price = $true_total_price = $true_total_integral = $coupon_price = $deduction_price = $use_integral = $pay_postage = $gainIntegral = $one_brokerage = $two_brokerage = $promotions_price = $first_order_price = 0;
|
||||
$unwriteoff = $wrrteoffed = 0;
|
||||
foreach ($cart_info_data as $cart) {
|
||||
$_info = json_decode($cart['cart_info'], true);
|
||||
if (isset($cart['is_writeoff']) && $cart['is_writeoff']) {
|
||||
$wrrteoffed++;
|
||||
}
|
||||
//赠品跳过
|
||||
if (isset($cart['is_gift']) && $cart['is_gift']) {
|
||||
continue;
|
||||
}
|
||||
$true_total_price = bcadd((string)$true_total_price, (string)($_info['sum_true_price'] ?? '0'), 2);
|
||||
$true_total_integral = bcadd((string)$true_total_integral, (string)bcmul((string)($cart['cart_num'] ?? '1'), (string)($_info['integral'] ?? '0'), 0), 0);
|
||||
$total_price = bcadd((string)$total_price, (string)bcmul((string)($cart['cart_num'] ?? '1'), (string)($_info['sum_price'] ?? '0'), 2), 2);
|
||||
$cost_price = bcadd((string)$cost_price, (string)bcmul((string)($cart['cart_num'] ?? '1'), (string)($_info['costPrice'] ?? '0'), 2), 2);
|
||||
$deduction_price = bcadd((string)$deduction_price, (string)($_info['integral_price'] ?? '0'), 2);
|
||||
$first_order_price = bcadd((string)$first_order_price, (string)($_info['first_order_price'] ?? '0'), 2);
|
||||
$coupon_price = bcadd((string)$coupon_price, (string)($_info['coupon_price'] ?? '0'), 2);
|
||||
$use_integral = bcadd((string)$use_integral, (string)($_info['use_integral'] ?? '0'), 0);
|
||||
if (!in_array($orderInfo['shipping_type'], [2, 4])) {
|
||||
$pay_postage = bcadd((string)$pay_postage, (string)($_info['postage_price'] ?? '0'), 2);
|
||||
}
|
||||
$cartInfoGainIntegral = bcmul((string)$cart['cart_num'], (string)($_info['productInfo']['give_integral'] ?? '0'), 0);
|
||||
$gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0);
|
||||
$one_brokerage = bcadd((string)$one_brokerage, (string)($_info['one_brokerage'] ?? '0'), 2);
|
||||
$two_brokerage = bcadd((string)$two_brokerage, (string)($_info['two_brokerage'] ?? '0'), 2);
|
||||
$promotions_price = bcadd((string)$promotions_price, (string)($_info['sum_promotions_price'] ?? '0'), 2);
|
||||
}
|
||||
|
||||
$order_update['coupon_id'] = array_unique(array_column($cart_info_data, 'coupon_id'));
|
||||
$order_update['pay_price'] = bcadd((string)$true_total_price, (string)$pay_postage, 2);
|
||||
//有订单原来支付金额 改价订单
|
||||
if ($order_pay_price) {
|
||||
if ($pre_pay_price) {//上一个已经计算 这里减法
|
||||
$order_update['pay_price'] = bcsub((string)$pay_price, (string)$pre_pay_price, 2);
|
||||
} else {//按比例计算实际支付金额
|
||||
$order_update['pay_price'] = bcmul((string)bcdiv((string)$pay_price, (string)$order_pay_price, 4), (string)$order_update['pay_price'], 2);
|
||||
}
|
||||
}
|
||||
if (!$pre_pay_price) {//最后一个订单保留赠送 积分 优惠券信息
|
||||
$order_update['give_integral'] = 0;
|
||||
$order_update['give_coupon'] = '';
|
||||
$order_update['gain_integral'] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$order_update['pay_price'] = max($order_update['pay_price'], 0);
|
||||
|
||||
|
||||
if($online_price >= $order_update['pay_price']){
|
||||
// online_price足够支付全部金额
|
||||
$order_update['online_price'] = $order_update['pay_price'];
|
||||
$order_update['yue_price'] = 0;
|
||||
$online_price = bcsub((string)$online_price, (string)$order_update['pay_price'], 2); // 剩余online_price
|
||||
// yue_price不变,全部剩余
|
||||
}else{
|
||||
// online_price不够,全部用完,剩余部分用yue_price
|
||||
$order_update['online_price'] = $online_price;
|
||||
$remaining_pay = bcsub((string)$order_update['pay_price'], (string)$online_price, 2); // 剩余需要支付的金额
|
||||
|
||||
if($yue_price >= $remaining_pay){
|
||||
// yue_price足够支付剩余金额
|
||||
$order_update['yue_price'] = $remaining_pay;
|
||||
$yue_price = bcsub((string)$yue_price, (string)$remaining_pay, 2); // 剩余yue_price
|
||||
}else{
|
||||
// yue_price也不够,全部用完
|
||||
$order_update['yue_price'] = $yue_price;
|
||||
$yue_price = 0; // yue_price用完
|
||||
}
|
||||
|
||||
$online_price = 0; // online_price已用完
|
||||
}
|
||||
|
||||
|
||||
$order_update['pay_integral'] = $true_total_integral;
|
||||
$order_update['total_price'] = $total_price;
|
||||
$order_update['cost'] = $cost_price;
|
||||
$order_update['deduction_price'] = $deduction_price;
|
||||
$order_update['first_order_price'] = $first_order_price;
|
||||
$order_update['coupon_price'] = $coupon_price;
|
||||
$order_update['use_integral'] = $use_integral;
|
||||
$order_update['pay_postage'] = $pay_postage;
|
||||
$order_update['one_brokerage'] = $one_brokerage;
|
||||
$order_update['two_brokerage'] = $two_brokerage;
|
||||
$order_update['promotions_price'] = $promotions_price;
|
||||
|
||||
if ($orderInfo['status'] == 5) {//部分核销拆单
|
||||
if (count($cart_info_data) == $wrrteoffed) {//全部核销
|
||||
$order_update['status'] = 2;
|
||||
}
|
||||
}
|
||||
if (false === $this->dao->update($id, $order_update, 'id')) {
|
||||
throw new ValidateException('保存新订单商品信息失败');
|
||||
}
|
||||
return [$online_price, $yue_price];
|
||||
}
|
||||
|
||||
/**
|
||||
* 部分发货重新计算订单商品:实际金额、优惠、积分等金额
|
||||
* @param int $cart_num
|
||||
* @param array $cart_info
|
||||
* @param int $i
|
||||
* @param bool $is_gift
|
||||
* @return array
|
||||
*/
|
||||
public function slpitComputeOrderCart(int $cart_num, array $cart_info, int $i = 0, bool $is_gift = false)
|
||||
{
|
||||
if (!$cart_num || !$cart_info) return [];
|
||||
$new_cart_info = $cart_info;
|
||||
if ($cart_num < $cart_info['cart_num']) {
|
||||
$compute_arr = ['coupon_price', 'integral_price', 'postage_price', 'use_integral', 'one_brokerage', 'two_brokerage', 'sum_true_price', 'first_order_price', 'division_staff_brokerage', 'division_agent_brokerage', 'division_brokerage'];
|
||||
foreach ($compute_arr as $field) {
|
||||
if (!isset($cart_info[$field]) || !$cart_info[$field] || $is_gift) {
|
||||
$new_cart_info[$field] = 0;
|
||||
continue;
|
||||
}
|
||||
$scale = 2;
|
||||
if ($field == 'use_integral') $scale = 0;
|
||||
|
||||
if (!$i) {//拆出
|
||||
$new_cart_info[$field] = bcmul((string)$cart_num, bcdiv((string)$cart_info[$field], (string)$cart_info['cart_num'], 4), $scale);
|
||||
} else {
|
||||
$field_number = bcmul((string)bcsub((string)$cart_info['cart_num'], (string)$cart_num, 0), bcdiv((string)$cart_info[$field], (string)$cart_info['cart_num'], 4), $scale);
|
||||
$new_cart_info[$field] = bcsub((string)$cart_info[$field], (string)$field_number, $scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
$new_cart_info['cart_num'] = $cart_num;
|
||||
return $new_cart_info;
|
||||
}
|
||||
}
|
||||
177
app/services/order/StoreOrderStatusServices.php
Normal file
177
app/services/order/StoreOrderStatusServices.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderStatusDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\message\service\StoreServiceServices;
|
||||
use app\services\store\SystemStoreStaffServices;
|
||||
use app\services\system\admin\SystemAdminServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 订单状态
|
||||
* Class StoreOrderStatusServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderStatusDao
|
||||
*/
|
||||
class StoreOrderStatusServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderStatusDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderStatusDao $dao;
|
||||
|
||||
/**
|
||||
* 订单状态分页
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getStatusList(array $where)
|
||||
{
|
||||
$list = $this->dao->getStatusList($where);
|
||||
foreach ($list as &$item) {
|
||||
if (is_int($item['change_time'])) $item['change_time'] = date('Y-m-d H:i:s', $item['change_time']);
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存订单状态变更记录
|
||||
* @param int $orderId 订单ID
|
||||
* @param string $changeType 变更类型
|
||||
* @param array $data 变更数据
|
||||
* @param int $changeManagerId 操作人ID
|
||||
* @param string $changeManagerType 操作人类型(user/admin/store/supplier/system)
|
||||
* @return bool
|
||||
*/
|
||||
public function saveStatus(int $orderId, string $changeType = 'create', array $data = [], int $changeManagerId = 0, string $changeManagerType = 'user')
|
||||
{
|
||||
if (!$orderId || !$data) {
|
||||
return true;
|
||||
}
|
||||
/** @var StoreOrderServices $orderService */
|
||||
$orderService = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $orderService->get($orderId);
|
||||
if (!$orderInfo) {
|
||||
return true;
|
||||
}
|
||||
$changeManagerId = !$changeManagerId && $changeManagerType == 'user' ? $orderInfo['uid'] : $changeManagerId;
|
||||
$statusData = [
|
||||
'oid' => $orderId,
|
||||
'change_time' => time(),
|
||||
'change_type' => $changeType,
|
||||
'change_message' => $data['change_message'] ?? '',
|
||||
'change_manager_type' => $changeManagerType,
|
||||
'change_manager_id' => $changeManagerId
|
||||
];
|
||||
if ($changeManagerId) {
|
||||
switch ($changeManagerType) {
|
||||
case 'user':
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($changeManagerId);
|
||||
if ($userInfo) {
|
||||
$statusData['change_manager'] = $userInfo['nickname'] ?? '';
|
||||
}
|
||||
break;
|
||||
case 'admin':
|
||||
/** @var SystemAdminServices $adminServices */
|
||||
$adminServices = app()->make(SystemAdminServices::class);
|
||||
$adminInfo = $adminServices->get($changeManagerId);
|
||||
if ($adminInfo) {
|
||||
$statusData['change_manager'] = $adminInfo['real_name'] ?? 'system';
|
||||
} else {
|
||||
$statusData['change_manager'] = 'system';
|
||||
}
|
||||
break;
|
||||
case 'store':
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($changeManagerId);
|
||||
$statusData['change_manager'] = $userInfo['nickname'] ?? '';
|
||||
break;
|
||||
case 'supplier':
|
||||
/** @var SystemAdminServices $systemAdminServices */
|
||||
$systemAdminServices = app()->make(SystemAdminServices::class);
|
||||
$supplierInfo = $systemAdminServices->get($changeManagerId);
|
||||
if ($supplierInfo) {
|
||||
$statusData['change_manager'] = $supplierInfo['real_name'] ?? '';
|
||||
}
|
||||
break;
|
||||
case 'system':
|
||||
$statusData['change_manager'] = '系统执行';
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->dao->save($statusData);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存订单记录
|
||||
* @param $type
|
||||
* @param $orderId
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
public function saveStatusOld($type, $orderId, $data)
|
||||
{
|
||||
if (!$type || !$orderId) {
|
||||
return true;
|
||||
}
|
||||
$statusData = ['oid' => $orderId, 'change_time' => time(), 'change_type' => ''];
|
||||
switch ($type) {
|
||||
case 'create'://创建
|
||||
$statusData['change_type'] = 'cache_key_create_order';
|
||||
$statusData['change_message'] = '订单生成';
|
||||
if (isset($data['changePrice']) && $data['changePrice'] > 0) {//有改价
|
||||
$this->saveStatus('edit', $orderId, $data);
|
||||
}
|
||||
break;
|
||||
case 'edit'://改价
|
||||
$statusData['change_type'] = 'order_edit';
|
||||
$statusData['change_message'] = '商品总价为:' . ($data['totalPrice'] ?? 0) . ' 修改实际支付金额为:' . ($data['payPrice'] ?? 0);
|
||||
break;
|
||||
case 'pay'://支付
|
||||
$statusData['change_type'] = 'pay_success';
|
||||
$statusData['change_message'] = '用户付款成功';
|
||||
break;
|
||||
case 'delivery'://发货
|
||||
break;
|
||||
case 'take'://收货
|
||||
break;
|
||||
case 'reply'://评价
|
||||
break;
|
||||
default:
|
||||
throw new ValidateException('未知订单类型记录');
|
||||
break;
|
||||
}
|
||||
/** @var StoreOrderStatusServices $statusService */
|
||||
$statusService = app()->make(StoreOrderStatusServices::class);
|
||||
$statusService->save($statusData);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
32
app/services/order/StoreOrderStoreOrderCartInfoServices.php
Normal file
32
app/services/order/StoreOrderStoreOrderCartInfoServices.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderStoreOrderCartInfoDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class StoreOrderStoreOrderCartInfoServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderStoreOrderCartInfoDao
|
||||
*/
|
||||
class StoreOrderStoreOrderCartInfoServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderStoreOrderCartInfoDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderStoreOrderCartInfoDao $dao;
|
||||
|
||||
}
|
||||
31
app/services/order/StoreOrderStoreOrderStatusServices.php
Normal file
31
app/services/order/StoreOrderStoreOrderStatusServices.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderStoreOrderStatusDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class StoreOrderStoreOrderStatusServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderStoreOrderStatusDao
|
||||
*/
|
||||
class StoreOrderStoreOrderStatusServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderStoreOrderStatusDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderStoreOrderStatusDao $dao;
|
||||
}
|
||||
99
app/services/order/StoreOrderSuccessServices.php
Normal file
99
app/services/order/StoreOrderSuccessServices.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\activity\lottery\LuckLotteryServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\pay\IntegralPayServices;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class StoreOrderSuccessServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderSuccessServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 0元支付
|
||||
* @param array $orderInfo
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
* @throws \think\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function zeroYuanPayment(array $orderInfo, int $uid, string $payType = PayServices::YUE_PAY)
|
||||
{
|
||||
$id = $orderInfo['id'] ?? 0;
|
||||
if (!$orderInfo || !$id) {
|
||||
throw new ValidateException('订单不存在!');
|
||||
}
|
||||
//更新订单信息
|
||||
$orderInfo = $this->dao->get($id);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$orderInfo = $orderInfo->toArray();
|
||||
if ($orderInfo['paid']) {
|
||||
throw new ValidateException('该订单已支付!');
|
||||
}
|
||||
return $this->paySuccess($orderInfo, $payType);//余额支付成功
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功
|
||||
* @param array $orderInfo
|
||||
* @param string $paytype
|
||||
* @return bool
|
||||
*/
|
||||
public function paySuccess(array $orderInfo, string $paytype = PayServices::WEIXIN_PAY, array $other = [])
|
||||
{
|
||||
$updata = ['paid' => 1, 'pay_type' => $paytype, 'pay_time' => time()];
|
||||
if ($other && isset($other['trade_no'])) {
|
||||
$updata['trade_no'] = $other['trade_no'];
|
||||
}
|
||||
$res1 = $this->dao->update($orderInfo['id'], $updata);
|
||||
$orderInfo['trade_no'] = $other['trade_no'] ?? '';
|
||||
$orderInfo['pay_time'] = time();
|
||||
$orderInfo['pay_type'] = $paytype;
|
||||
//缓存抽奖次数 除过线下支付和抽奖订单
|
||||
if (isset($orderInfo['pay_type']) && $orderInfo['pay_type'] != 'offline' && isset($orderInfo['type']) && $orderInfo['type'] != 8 && $orderInfo['type'] != 9) {
|
||||
/** @var LuckLotteryServices $luckLotteryServices */
|
||||
$luckLotteryServices = app()->make(LuckLotteryServices::class);
|
||||
$luckLotteryServices->setCacheLotteryNum((int)$orderInfo['uid'], 'order');
|
||||
}
|
||||
$userInfo = app()->make(UserServices::class)->get($orderInfo['uid']);
|
||||
if ($orderInfo['pay_integral']) {//需要支付积分
|
||||
/** @var IntegralPayServices $integralPayServices */
|
||||
$integralPayServices = app()->make(IntegralPayServices::class);
|
||||
$integralPayServices->integralOrderPay((int)$userInfo['uid'], $orderInfo, $userInfo->toArray());
|
||||
}
|
||||
//订单支付成功事件
|
||||
event('order.pay', [$orderInfo, $userInfo]);
|
||||
$res = $res1;
|
||||
return false !== $res;
|
||||
}
|
||||
|
||||
}
|
||||
619
app/services/order/StoreOrderTakeServices.php
Normal file
619
app/services/order/StoreOrderTakeServices.php
Normal file
@@ -0,0 +1,619 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\jobs\order\AutoTakeOrderJob;
|
||||
use app\jobs\notice\SmsAdminJob;
|
||||
use app\jobs\order\OrderStatusJob;
|
||||
use app\jobs\user\UserLevelJob;
|
||||
use app\services\activity\holiday\HolidayGiftPushServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\message\service\StoreServiceServices;
|
||||
use app\services\message\sms\SmsSendServices;
|
||||
use app\services\user\member\MemberCardServices;
|
||||
use app\services\user\UserBillServices;
|
||||
use app\services\user\UserBrokerageServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 订单收货
|
||||
* Class StoreOrderTakeServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderTakeServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 小程序订单服务收货
|
||||
* @param $order_id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*
|
||||
* @date 2023/05/18
|
||||
* @author yyw
|
||||
*/
|
||||
public function miniOrderTakeOrder($order_id)
|
||||
{
|
||||
$orderArr = explode('_', $order_id);
|
||||
if (count($orderArr) == 2) {
|
||||
$order_id = $orderArr[1] ?? $order_id;
|
||||
}
|
||||
//查找订单信息
|
||||
$order = $this->dao->getOne(['order_id' => $order_id]);
|
||||
if (!$order) {
|
||||
return true;
|
||||
}
|
||||
if ($order['pid'] == -1) { // 有子订单
|
||||
// 查找待收货的子订单
|
||||
$son_order_list = $this->dao->getSubOrderNotSendList((int)$order['id']);
|
||||
foreach ($son_order_list as $son_order) {
|
||||
$this->takeOrder($son_order['order_id'], $son_order['uid']);
|
||||
}
|
||||
} else {
|
||||
$this->takeOrder($order_id, $order['uid']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户订单收货
|
||||
* @param $uni
|
||||
* @param $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function takeOrder(string $uni, int $uid)
|
||||
{
|
||||
$order = $this->dao->getUserOrderDetail($uni, $uid);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在!');
|
||||
}
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$order = $orderServices->tidyOrder($order);
|
||||
if ($order['_status']['_type'] != 2) {
|
||||
throw new ValidateException('订单状态错误!');
|
||||
}
|
||||
//存在拆分发货 需要分开收货
|
||||
if ($this->dao->count(['pid' => $order['id']])) {
|
||||
throw new ValidateException('拆分发货,请去订单详情中包裹确认收货');
|
||||
}
|
||||
$order->status = 2;
|
||||
$res = $order->save();
|
||||
OrderStatusJob::dispatch([$order['id'], 'user_take_delivery', ['change_message' => '用户已收货', 'change_manager_type' => 'user']]);
|
||||
$res = $res && $this->storeProductOrderUserTakeDelivery($order);
|
||||
if (!$res) {
|
||||
throw new ValidateException('收货失败');
|
||||
}
|
||||
//核销订单 修改订单商品核销状态
|
||||
if ($order['shipping_type'] == 2 || (in_array($order['shipping_type'], [1, 3]) && $order['delivery_type'] == 'send')) {
|
||||
//修改原来订单商品信息
|
||||
$cartData['is_writeoff'] = 1;
|
||||
$cartData['write_surplus_times'] = 0;
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfoServices->update(['oid' => $order['id']], $cartData);
|
||||
}
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单确认收货
|
||||
* @param $order
|
||||
* @return bool
|
||||
*/
|
||||
public function storeProductOrderUserTakeDelivery($order, bool $isTran = true, bool $isRecord = true)
|
||||
{
|
||||
$res = true;
|
||||
//获取购物车内的商品标题
|
||||
/** @var StoreOrderCartInfoServices $orderInfoServices */
|
||||
$orderInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$storeName = $orderInfoServices->getCarIdByProductTitle((int)$order['id']);
|
||||
$storeTitle = substrUTf8($storeName, 20, 'UTF-8', '');
|
||||
if ($order['uid']) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo((int)$order['uid']);
|
||||
$res = $this->transaction(function () use ($order, $userInfo, $storeTitle) {
|
||||
//赠送积分
|
||||
$res1 = $this->gainUserIntegral($order, $userInfo, $storeTitle);
|
||||
//返佣
|
||||
$res2 = $this->backOrderBrokerage($order, $userInfo);
|
||||
//经验
|
||||
$res3 = $this->gainUserExp($order, $userInfo);
|
||||
//事业部
|
||||
$res4 = $this->divisionBrokerage($order, $userInfo);
|
||||
if (!($res1 && $res2 && $res3)) {
|
||||
throw new ValidateException('收货失败!');
|
||||
}
|
||||
return true;
|
||||
}, $isTran);
|
||||
}
|
||||
if ($res) {
|
||||
//订单收货事件
|
||||
event('order.take', [$order, $storeTitle, $isRecord]);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
* @param $order
|
||||
* @param $userInfo
|
||||
* @param $storeTitle
|
||||
* @return bool
|
||||
*/
|
||||
public function gainUserIntegral($order, $userInfo, $storeTitle)
|
||||
{
|
||||
$res2 = true;
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
// 营销产品送积分
|
||||
if (!isset($order['type']) || $order['type'] != 0) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
$balance = $userInfo['integral'];
|
||||
if ($order['gain_integral'] > 0) {
|
||||
$balance = bcadd((string)$balance, (string)$order['gain_integral']);
|
||||
$res2 = false != $userBillServices->income('pay_give_integral', $order['uid'], (int)$order['gain_integral'], (int)$balance, $order['id']);
|
||||
}
|
||||
$order_integral = 0;
|
||||
$res3 = true;
|
||||
$order_give_integral = sys_config('order_give_integral');
|
||||
if ($order['pay_price'] && $order_give_integral) {
|
||||
//积分倍数
|
||||
$multiple = 0;
|
||||
//会员消费返积分翻倍
|
||||
if ($userInfo['is_money_level'] > 0) {
|
||||
//看是否开启消费返积分翻倍奖励
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$integral_rule_number = $memberCardService->isOpenMemberCardCache('integral');
|
||||
$multiple = bcadd((string)$multiple, (string)$integral_rule_number, 0);
|
||||
}
|
||||
//节日任务赠送积分倍数
|
||||
$integral_multiple = app()->make(HolidayGiftPushServices::class)->receiveHolidayGift($userInfo['uid'], 2);
|
||||
if($integral_multiple){
|
||||
$multiple = bcadd((string)$multiple, (string)$integral_multiple, 0);
|
||||
}
|
||||
if($multiple){
|
||||
$order_integral = bcmul((string)$order['pay_price'], (string)$multiple, 2);
|
||||
}
|
||||
$order_integral = bcmul((string)$order_give_integral, (string)($order_integral ? $order_integral : $order['pay_price']), 0);
|
||||
|
||||
$balance = bcadd((string)$balance, (string)$order_integral);
|
||||
$res3 = false != $userBillServices->income('order_give_integral', $order['uid'], (int)$order_integral, (int)$balance, $order['id']);
|
||||
}
|
||||
$give_integral = $order_integral + $order['gain_integral'];
|
||||
if ($give_integral > 0) {
|
||||
$integral = $userInfo['integral'] + $give_integral;
|
||||
$userInfo->integral = $integral;
|
||||
$res1 = false != $userInfo->save();
|
||||
$res = $res1 && $res2 && $res3;
|
||||
//发送消息
|
||||
event('notice.notice', [['order' => $order, 'storeTitle' => $storeTitle, 'give_integral' => $give_integral, 'integral' => $integral], 'integral_accout']);
|
||||
return $res;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 一级返佣
|
||||
* @param $orderInfo
|
||||
* @param $userInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function backOrderBrokerage($orderInfo, $userInfo)
|
||||
{
|
||||
// 当前订单|用户不存在 直接返回
|
||||
if (!$orderInfo || !$userInfo) {
|
||||
return true;
|
||||
}
|
||||
//商城分销功能是否开启 0关闭1开启
|
||||
if (!sys_config('brokerage_func_status')) return true;
|
||||
|
||||
// 营销产品不返佣金
|
||||
if (!isset($orderInfo['type']) || in_array($orderInfo['type'], [4, 5, 7, 8])) {
|
||||
return true;
|
||||
}
|
||||
//绑定失效
|
||||
if (isset($orderInfo['spread_uid']) && $orderInfo['spread_uid'] == -1) {
|
||||
return true;
|
||||
}
|
||||
//是否开启自购返佣
|
||||
$isSelfBrokerage = sys_config('is_self_brokerage', 0);
|
||||
if (!isset($orderInfo['spread_uid']) || !$orderInfo['spread_uid']) {//兼容之前订单表没有spread_uid情况
|
||||
//没开启自购返佣 没有上级 或者 当用用户上级时自己 直接返回
|
||||
if (!$isSelfBrokerage && (!$userInfo['spread_uid'] || $userInfo['spread_uid'] == $orderInfo['uid'])) {
|
||||
return true;
|
||||
}
|
||||
$one_spread_uid = $isSelfBrokerage ? $userInfo['uid'] : $userInfo['spread_uid'];
|
||||
} else {
|
||||
$one_spread_uid = $orderInfo['spread_uid'];
|
||||
}
|
||||
$one_spread_uid = (int)$one_spread_uid;
|
||||
//冻结时间
|
||||
$broken_time = intval(sys_config('extract_time'));
|
||||
$frozen_time = time() + $broken_time * 86400;
|
||||
|
||||
//检测是否是分销员
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if (!$userServices->checkUserPromoter($one_spread_uid)) {//一级不是分销员 直接二级返佣
|
||||
return $this->backOrderBrokerageTwo($orderInfo, $userInfo, $isSelfBrokerage, $frozen_time);
|
||||
}
|
||||
//订单中取出
|
||||
$brokeragePrice = $orderInfo['one_brokerage'] ?? 0;
|
||||
// 返佣金额小于等于0 直接返回不返佣金
|
||||
if ($brokeragePrice <= 0) {
|
||||
return true;
|
||||
}
|
||||
// 获取上级推广员信息
|
||||
$spreadPrice = $userServices->value(['uid' => $one_spread_uid], 'brokerage_price');
|
||||
// 上级推广员返佣之后的金额
|
||||
$balance = bcadd($spreadPrice, $brokeragePrice, 2);
|
||||
// 添加佣金记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
//自购返佣 || 上级
|
||||
$type = $one_spread_uid == $orderInfo['uid'] ? 'get_self_brokerage' : 'get_brokerage';
|
||||
$res1 = $userBrokerageServices->income($type, $one_spread_uid, [
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'pay_price' => floatval($orderInfo['pay_price']),
|
||||
'number' => floatval($brokeragePrice),
|
||||
'frozen_time' => $frozen_time
|
||||
], $balance, $orderInfo['id']);
|
||||
// 添加用户佣金
|
||||
$res2 = $userServices->bcInc($one_spread_uid, 'brokerage_price', $brokeragePrice, 'uid');
|
||||
//给上级发送获得佣金的模板消息
|
||||
$this->sendBackOrderBrokerage($orderInfo, $one_spread_uid, $brokeragePrice);
|
||||
// 一级返佣成功 跳转二级返佣
|
||||
$res = $res1 && $res2 && $this->backOrderBrokerageTwo($orderInfo, $userInfo, $isSelfBrokerage, $frozen_time);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 二级推广返佣
|
||||
* @param $orderInfo
|
||||
* @param $userInfo
|
||||
* @param int $isSelfbrokerage
|
||||
* @param int $frozenTime
|
||||
* @return bool
|
||||
*/
|
||||
public function backOrderBrokerageTwo($orderInfo, $userInfo, $isSelfbrokerage = 0, $frozenTime = 0)
|
||||
{
|
||||
//绑定失效
|
||||
if (isset($orderInfo['spread_two_uid']) && $orderInfo['spread_two_uid'] == -1) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if (isset($orderInfo['spread_two_uid']) && $orderInfo['spread_two_uid']) {
|
||||
$spread_two_uid = $orderInfo['spread_two_uid'];
|
||||
} else {
|
||||
// 获取上推广人
|
||||
$userInfoTwo = $userServices->get((int)$userInfo['spread_uid']);
|
||||
// 订单|上级推广人不存在 直接返回
|
||||
if (!$orderInfo || !$userInfoTwo) {
|
||||
return true;
|
||||
}
|
||||
//没开启自购返佣 或者 上推广人没有上级 或者 当用用户上上级时自己 直接返回
|
||||
if (!$isSelfbrokerage && (!$userInfoTwo['spread_uid'] || $userInfoTwo['spread_uid'] == $orderInfo['uid'])) {
|
||||
return true;
|
||||
}
|
||||
$spread_two_uid = $isSelfbrokerage ? $userInfoTwo['uid'] : $userInfoTwo['spread_uid'];
|
||||
}
|
||||
$spread_two_uid = (int)$spread_two_uid;
|
||||
// 获取后台分销类型 1 指定分销 2 人人分销
|
||||
if (!$userServices->checkUserPromoter($spread_two_uid)) {
|
||||
return true;
|
||||
}
|
||||
//订单中取出
|
||||
$brokeragePrice = $orderInfo['two_brokerage'] ?? 0;
|
||||
// 返佣金额小于等于0 直接返回不返佣金
|
||||
if ($brokeragePrice <= 0) {
|
||||
return true;
|
||||
}
|
||||
// 获取上上级推广员信息
|
||||
$spreadPrice = $userServices->value(['uid' => $spread_two_uid], 'brokerage_price');
|
||||
// 获取上上级推广员返佣之后余额
|
||||
$balance = bcadd($spreadPrice, $brokeragePrice, 2);
|
||||
// 添加佣金记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$res1 = $userBrokerageServices->income('get_two_brokerage', $spread_two_uid, [
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'pay_price' => floatval($orderInfo['pay_price']),
|
||||
'number' => floatval($brokeragePrice),
|
||||
'frozen_time' => $frozenTime
|
||||
], $balance, $orderInfo['id']);
|
||||
// 添加用户佣金
|
||||
$res2 = $userServices->bcInc($spread_two_uid, 'brokerage_price', $brokeragePrice, 'uid');
|
||||
//给上级发送获得佣金的模板消息
|
||||
$this->sendBackOrderBrokerage($orderInfo, $spread_two_uid, $brokeragePrice);
|
||||
return $res1 && $res2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 佣金到账发送模板消息
|
||||
* @param $orderInfo
|
||||
* @param $spread_uid
|
||||
* @param $brokeragePrice
|
||||
*/
|
||||
public function sendBackOrderBrokerage($orderInfo, $spread_uid, $brokeragePrice, string $type = 'order')
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($spread_uid, 'phone,user_type');
|
||||
$goodsName = '';
|
||||
$goodsPrice = 0;
|
||||
if ($type == 'order') {
|
||||
/** @var StoreOrderCartInfoServices $storeOrderCartInfoService */
|
||||
$storeOrderCartInfoService = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfo = $storeOrderCartInfoService->getOrderCartInfo($orderInfo['id']);
|
||||
if ($cartInfo) {
|
||||
$cartInfo = array_column($cartInfo, 'cart_info');
|
||||
foreach ($cartInfo as $k => $v) {
|
||||
$goodsName .= $v['productInfo']['store_name'];
|
||||
$price = $v['productInfo']['attrInfo']['price'] ?? $v['productInfo']['price'] ?? 0;
|
||||
$goodsPrice = bcadd((string)$goodsPrice, (string)bcmul((string)$price, (string)$v['cart_num'], 2), 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$goodsName = '推广用户获取佣金';
|
||||
$goodsPrice = $brokeragePrice;
|
||||
}
|
||||
//提醒推送
|
||||
event('notice.notice', [['spread_uid' => $spread_uid, 'phone' => $user['phone'], 'userType' => $user['user_type'], 'brokeragePrice' => $brokeragePrice, 'goodsName' => $goodsName, 'goodsPrice' => $goodsPrice, 'add_time' => $orderInfo['add_time'] ?? time()], 'order_brokerage']);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
* @param $order
|
||||
* @param $storeTitle
|
||||
*/
|
||||
public function smsSend($order, $storeTitle)
|
||||
{
|
||||
/** @var SmsSendServices $smsServices */
|
||||
$smsServices = app()->make(SmsSendServices::class);
|
||||
$switch = (bool)sys_config('confirm_take_over_switch');
|
||||
//模板变量
|
||||
$store_name = $storeTitle;
|
||||
$order_id = $order['order_id'];
|
||||
$smsServices->send($switch, $order['user_phone'], compact('store_name', 'order_id'), 'TAKE_DELIVERY_CODE');
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送确认收货管理员短信
|
||||
* @param $order
|
||||
*/
|
||||
public function smsSendTake($order)
|
||||
{
|
||||
$switch = (bool)sys_config('admin_confirm_take_over_switch');
|
||||
/** @var StoreServiceServices $services */
|
||||
$services = app()->make(StoreServiceServices::class);
|
||||
$adminList = $services->getStoreServiceOrderNotice();
|
||||
SmsAdminJob::dispatchDo('sendAdminConfirmTakeOver', [$switch, $adminList, $order]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 赠送经验
|
||||
* @param $order
|
||||
* @param $userInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function gainUserExp($order, $userInfo)
|
||||
{
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
//用户等级是否开启
|
||||
if (!sys_config('member_func_status', 1)) {
|
||||
return true;
|
||||
}
|
||||
//用户等级未激活
|
||||
if (isset($userInfo['level_status']) && !$userInfo['level_status']) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
$order_exp = 0;
|
||||
$res3 = true;
|
||||
$order_give_exp = sys_config('order_give_exp');
|
||||
$balance = $userInfo['exp'];
|
||||
if ($order['pay_price'] && $order_give_exp) {
|
||||
$order_exp = bcmul($order_give_exp, (string)$order['pay_price'], 2);
|
||||
$balance = bcadd((string)$balance, (string)$order_exp, 2);
|
||||
$res3 = false != $userBillServices->income('order_give_exp', $order['uid'], $order_exp, $balance, $order['id']);
|
||||
}
|
||||
$res = true;
|
||||
if ($order_exp > 0) {
|
||||
$userInfo->exp = $balance;
|
||||
$res1 = false != $userInfo->save();
|
||||
$res = $res1 && $res3;
|
||||
}
|
||||
//检测用户等级升级
|
||||
UserLevelJob::dispatch([(int)$order['uid']]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行自动收货
|
||||
* @param array $where
|
||||
* @param int $page
|
||||
* @param int $maxLimit
|
||||
* @return bool
|
||||
*/
|
||||
public function runAutoTakeOrder(array $where, int $page = 0, int $maxLimit = 0)
|
||||
{
|
||||
/** @var StoreOrderStoreOrderStatusServices $service */
|
||||
$service = app()->make(StoreOrderStoreOrderStatusServices::class);
|
||||
$orderList = $service->getOrderIds($where, $page, $maxLimit);
|
||||
/** @var StoreOrderRefundServices $storeOrderRefundServices */
|
||||
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
foreach ($orderList as $order) {
|
||||
if ($order['status'] == 2) {
|
||||
continue;
|
||||
}
|
||||
if ($order['paid'] == 1 && $order['status'] == 1) {
|
||||
$data['status'] = 2;
|
||||
} else if ($order['pay_type'] == 'offline') {
|
||||
$data['status'] = 2;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if ($storeOrderRefundServices->count(['store_order_id' => $order['id'], 'refund_type' => [0, 1, 2, 4, 5], 'is_cancel' => 0, 'is_del' => 0])) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$res = $this->dao->update($order['id'], $data);
|
||||
$res = $res && $this->storeProductOrderUserTakeDelivery($order);
|
||||
OrderStatusJob::dispatch([$order['id'], 'take_delivery', ['change_message' => '已收货[自动收货]', 'change_manager_type' => 'system']]);
|
||||
if (!$res) {
|
||||
throw new ValidateException('订单号' . $order['order_id'] . '自动收货失败');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('自动收货失败,失败原因:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动收货
|
||||
* @return bool
|
||||
*/
|
||||
public function autoTakeOrder()
|
||||
{
|
||||
//7天前时间戳
|
||||
$systemDeliveryTime = (int)sys_config('system_delivery_time', 0);
|
||||
//0为取消自动收货功能
|
||||
if ($systemDeliveryTime == 0) {
|
||||
return true;
|
||||
}
|
||||
$sevenDay = strtotime(date('Y-m-d H:i:s', strtotime('-' . $systemDeliveryTime . ' day')));
|
||||
/** @var StoreOrderStoreOrderStatusServices $service */
|
||||
$service = app()->make(StoreOrderStoreOrderStatusServices::class);
|
||||
$where = [
|
||||
'change_time' => $sevenDay,
|
||||
'is_del' => 0,
|
||||
'paid' => 1,
|
||||
'status' => 1,
|
||||
'change_type' => ['delivery_goods', 'delivery_fictitious', 'delivery', 'city_delivery']
|
||||
];
|
||||
$maxLimit = 20;
|
||||
$count = $service->getOrderCount($where);
|
||||
if ($count > $maxLimit) {
|
||||
$page = ceil($count / $maxLimit);
|
||||
for ($i = 1; $i <= $page; $i++) {
|
||||
AutoTakeOrderJob::dispatch([$where, $i, $maxLimit]);
|
||||
}
|
||||
} else {
|
||||
$this->runAutoTakeOrder($where);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 事业部返佣
|
||||
* @param $orderInfo
|
||||
* @param $userInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function divisionBrokerage($orderInfo, $userInfo)
|
||||
{
|
||||
// 当前订单|用户不存在 直接返回
|
||||
if (!$orderInfo || !$userInfo) {
|
||||
return true;
|
||||
}
|
||||
// 营销产品不返佣金
|
||||
if (!isset($orderInfo['type']) || in_array($orderInfo['type'], [4, 5, 7, 8])) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if ($orderInfo['division_staff_id'] && $orderInfo['division_staff_brokerage'] > 0) {
|
||||
$spreadPrice = $userServices->value(['uid' => $orderInfo['division_staff_id']], 'brokerage_price');
|
||||
$balance = bcadd($spreadPrice, $orderInfo['division_staff_brokerage'], 2);
|
||||
$userServices->bcInc($orderInfo['division_staff_id'], 'brokerage_price', $orderInfo['division_staff_brokerage'], 'uid');
|
||||
//冻结时间
|
||||
$broken_time = intval(sys_config('extract_time'));
|
||||
$frozen_time = time() + $broken_time * 86400;
|
||||
// 添加佣金记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$userBrokerageServices->income('get_staff_brokerage', $orderInfo['division_staff_id'], [
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'pay_price' => floatval($orderInfo['pay_price']),
|
||||
'number' => floatval($orderInfo['division_staff_brokerage']),
|
||||
'frozen_time' => $frozen_time
|
||||
], $balance, $orderInfo['id']);
|
||||
}
|
||||
if ($orderInfo['division_agent_id'] && $orderInfo['division_agent_brokerage'] > 0) {
|
||||
$spreadPrice = $userServices->value(['uid' => $orderInfo['division_agent_id']], 'brokerage_price');
|
||||
$balance = bcadd($spreadPrice, $orderInfo['division_agent_brokerage'], 2);
|
||||
$userServices->bcInc($orderInfo['division_agent_id'], 'brokerage_price', $orderInfo['division_agent_brokerage'], 'uid');
|
||||
//冻结时间
|
||||
$broken_time = intval(sys_config('extract_time'));
|
||||
$frozen_time = time() + $broken_time * 86400;
|
||||
// 添加佣金记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$userBrokerageServices->income('get_agent_brokerage', $orderInfo['division_agent_id'], [
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'pay_price' => floatval($orderInfo['pay_price']),
|
||||
'number' => floatval($orderInfo['division_agent_brokerage']),
|
||||
'frozen_time' => $frozen_time
|
||||
], $balance, $orderInfo['id']);
|
||||
}
|
||||
if ($orderInfo['division_id'] && $orderInfo['division_brokerage'] > 0) {
|
||||
$spreadPrice = $userServices->value(['uid' => $orderInfo['division_id']], 'brokerage_price');
|
||||
$balance = bcadd($spreadPrice, $orderInfo['division_brokerage'], 2);
|
||||
$userServices->bcInc($orderInfo['division_id'], 'brokerage_price', $orderInfo['division_brokerage'], 'uid');
|
||||
//冻结时间
|
||||
$broken_time = intval(sys_config('extract_time'));
|
||||
$frozen_time = time() + $broken_time * 86400;
|
||||
// 添加佣金记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$userBrokerageServices->income('get_division_brokerage', $orderInfo['division_id'], [
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'pay_price' => floatval($orderInfo['pay_price']),
|
||||
'number' => floatval($orderInfo['division_brokerage']),
|
||||
'frozen_time' => $frozen_time
|
||||
], $balance, $orderInfo['id']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
151
app/services/order/StoreOrderWapServices.php
Normal file
151
app/services/order/StoreOrderWapServices.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\product\product\StoreProductLogServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class StoreOrderWapServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderWapServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 获取 今日 昨日 本月 订单金额
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrderTimeData(int $store_id = 0)
|
||||
{
|
||||
$where = ['pid' => 0, 'timeKey' => 'add_time', 'paid' => 1, 'is_del' => 0, 'is_system_del' => 0, 'refund_status' => [0, 3]];
|
||||
//今日成交额
|
||||
$data['todayPrice'] = $this->dao->together($where + ['time' => 'today'], 'pay_price');
|
||||
//今日订单数
|
||||
$data['todayCount'] = $this->dao->count($where + ['time' => 'today']);
|
||||
//昨日成交额
|
||||
$data['proPrice'] = $this->dao->together($where + ['time' => 'yesterday'], 'pay_price');
|
||||
//昨日订单数
|
||||
$data['proCount'] = $this->dao->count($where + ['time' => 'yesterday']);
|
||||
//本月成交额
|
||||
$data['monthPrice'] = $this->dao->together($where + ['time' => 'month'], 'pay_price');
|
||||
//本月订单数
|
||||
$data['monthCount'] = $this->dao->count($where + ['time' => 'month']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单每月统计数据
|
||||
* @param array $where
|
||||
* @param int $store_id
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderDataPriceCount(array $where = [], int $store_id = 0)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$data = $this->dao->getOrderDataPriceCount($where + ['pid' => 0, 'is_del' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'is_system_del' => 0], ['sum(pay_price) as price', 'count(id) as count', 'add_time'], $page, $limit);
|
||||
if (count($data) > 0) {
|
||||
/** @var StoreProductLogServices $productLogServices */
|
||||
$productLogServices = app()->make(StoreProductLogServices::class);
|
||||
foreach ($data as $key => &$time) {
|
||||
$time['time'] = date('m-d', $time['add_time']);
|
||||
$time['visit'] = $productLogServices->count(['time' => [$time['add_time'], $time['add_time'] + 86400], 'type' => 'visit']);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端订单列表
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @param array $with
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOrderApiList(array $where, array $field = ['*'], array $with = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
if (isset($where['status']) && $where['status'] === '') {
|
||||
$data = $this->dao->getOrderList($where, $field, $page, $limit, $with, 'id DESC');
|
||||
} else {
|
||||
$data = $this->dao->getOrderList($where, $field, $page, $limit, $with);
|
||||
}
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
foreach ($data as &$item) {
|
||||
$item['type_name'] = '';
|
||||
if ($item['type'] > 0) {
|
||||
[$type_name, $color] = $orderServices->tidyOrderType($item, true);
|
||||
$item['type_name'] = $type_name;
|
||||
}
|
||||
$item = $orderServices->tidyOrder($item, true);
|
||||
$cart_num = 0;
|
||||
foreach ($item['cartInfo'] ?: [] as $key => $product) {
|
||||
if (isset($item['_status']['_type']) && $item['_status']['_type'] == 3) {
|
||||
$item['cartInfo'][$key]['add_time'] = isset($product['add_time']) ? date('Y-m-d H:i', (int)$product['add_time']) : '时间错误';
|
||||
}
|
||||
$item['cartInfo'][$key]['productInfo']['price'] = $product['truePrice'] ?? 0;
|
||||
|
||||
if (isset($product['is_gift']) && $product['is_gift']) continue;
|
||||
$cart_num += $product['cart_num'];
|
||||
}
|
||||
if (count($item['refund'])) {
|
||||
$refund_num = array_sum(array_column($item['refund'], 'refund_num'));
|
||||
$item['is_all_refund'] = $refund_num == $cart_num;
|
||||
} else {
|
||||
$item['is_all_refund'] = false;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机端订单管理
|
||||
* @param array $where
|
||||
* @param array $with
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getWapAdminOrderList(array $where, array $with = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getOrderList($where, ['*'], $page, $limit, $with);
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$list = $orderServices->tidyOrderList($list);
|
||||
foreach ($list as &$item) {
|
||||
$refund_num = array_sum(array_column($item['refund'], 'refund_num'));
|
||||
$cart_num = 0;
|
||||
foreach ($item['_info'] as $items) {
|
||||
if (isset($items['cart_info']['is_gift']) && $items['cart_info']['is_gift']) continue;
|
||||
$cart_num += $items['cart_info']['cart_num'];
|
||||
}
|
||||
$item['is_all_refund'] = $refund_num == $cart_num;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
||||
378
app/services/order/StoreOrderWriteOffServices.php
Normal file
378
app/services/order/StoreOrderWriteOffServices.php
Normal file
@@ -0,0 +1,378 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\dao\order\StoreOrderWriteoffDao;
|
||||
use app\services\message\service\StoreServiceServices;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\store\DeliveryServiceServices;
|
||||
use app\services\activity\integral\StoreIntegralOrderServices;
|
||||
use app\services\activity\integral\StoreIntegralOrderStatusServices;
|
||||
use app\services\activity\combination\StorePinkServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\store\SystemStoreStaffServices;
|
||||
use app\services\supplier\SystemSupplierServices;
|
||||
use app\services\system\admin\SystemAdminServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 核销订单
|
||||
* Class StoreOrderWriteOffServices
|
||||
* @package app\sservices\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class StoreOrderWriteOffServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* @var StoreOrderWriteoffDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderWriteoffDao $writeoffdao;
|
||||
|
||||
/**
|
||||
* 订单核销
|
||||
* @param string $code
|
||||
* @param int $confirm
|
||||
* @param int $uid
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function writeOffOrder(string $code, int $confirm, int $uid = 0)
|
||||
{
|
||||
//订单
|
||||
$orderInfo = $this->dao->getOne(['verify_code' => $code, 'paid' => 1, 'refund_status' => 0, 'is_del' => 0], '*', ['pink']);
|
||||
$order_type = 'order';
|
||||
if (!$orderInfo) {
|
||||
//积分兑换订单
|
||||
/** @var StoreIntegralOrderServices $storeIntegralOrderServices */
|
||||
$storeIntegralOrderServices = app()->make(StoreIntegralOrderServices::class);
|
||||
$orderInfo = $storeIntegralOrderServices->getOne(['verify_code' => $code]);
|
||||
$order_type = 'integral';
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('Write off order does not exist');
|
||||
}
|
||||
if (!$orderInfo['verify_code'] || ($orderInfo->shipping_type != 2 && $orderInfo->delivery_type != 'send')) {
|
||||
throw new ValidateException('此订单不能被核销');
|
||||
}
|
||||
if ($uid) {
|
||||
$isAuth = true;
|
||||
switch ($orderInfo['shipping_type']) {
|
||||
case 1://配送订单
|
||||
/** @var DeliveryServiceServices $deliverServiceServices */
|
||||
$deliverServiceServices = app()->make(DeliveryServiceServices::class);
|
||||
$isAuth = $deliverServiceServices->getCount(['uid' => $uid, 'status' => 1]) > 0;
|
||||
break;
|
||||
case 2://自提订单
|
||||
/** @var SystemStoreStaffServices $storeStaffServices */
|
||||
$storeStaffServices = app()->make(SystemStoreStaffServices::class);
|
||||
$isAuth = $storeStaffServices->getCount(['uid' => $uid, 'verify_status' => 1, 'status' => 1]) > 0;
|
||||
break;
|
||||
}
|
||||
if (!$isAuth) {
|
||||
throw new ValidateException('您无权限核销此订单,请联系管理员');
|
||||
}
|
||||
}
|
||||
$orderInfo['order_type'] = $order_type;
|
||||
if ($order_type == 'order') {
|
||||
if ($orderInfo->status == 2) {
|
||||
throw new ValidateException('订单已核销');
|
||||
}
|
||||
if (isset($orderInfo['pinkStatus']) && $orderInfo['pinkStatus'] != 2) {
|
||||
throw new ValidateException('拼团未完成暂不能发货!');
|
||||
}
|
||||
/** @var StoreOrderCartInfoServices $orderCartInfo */
|
||||
$orderCartInfo = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfo = $orderCartInfo->getOne([
|
||||
['cart_id', '=', $orderInfo['cart_id'][0]]
|
||||
], 'cart_info');
|
||||
if ($cartInfo) $orderInfo['image'] = $cartInfo['cart_info']['productInfo']['image'];
|
||||
if ($orderInfo->shipping_type == 2) {
|
||||
if ($orderInfo->status > 0) {
|
||||
throw new ValidateException('Order written off');
|
||||
}
|
||||
}
|
||||
if ($orderInfo['type'] == 3 && $orderInfo['activity_id'] && $orderInfo['pink_id']) {
|
||||
/** @var StorePinkServices $services */
|
||||
$services = app()->make(StorePinkServices::class);
|
||||
$res = $services->getCount([['id', '=', $orderInfo->pink_id], ['status', '<>', 2]]);
|
||||
if ($res) throw new ValidateException('Failed to write off the group order');
|
||||
}
|
||||
if ($confirm == 0) {
|
||||
/** @var UserServices $services */
|
||||
$services = app()->make(UserServices::class);
|
||||
$orderInfo['nickname'] = $services->value(['uid' => $orderInfo['uid']], 'nickname');
|
||||
return $orderInfo->toArray();
|
||||
}
|
||||
$orderInfo->status = 2;
|
||||
if ($uid) {
|
||||
if ($orderInfo->shipping_type == 2) {
|
||||
$orderInfo->clerk_id = $uid;
|
||||
}
|
||||
}
|
||||
if ($orderInfo->save()) {
|
||||
/** @var StoreOrderTakeServices $storeOrdeTask */
|
||||
$storeOrdeTask = app()->make(StoreOrderTakeServices::class);
|
||||
$re = $storeOrdeTask->storeProductOrderUserTakeDelivery($orderInfo);
|
||||
if (!$re) {
|
||||
throw new ValidateException('Write off failure');
|
||||
}
|
||||
//修改订单商品信息
|
||||
$cartData = ['writeoff_time' => time()];
|
||||
$cartData['is_writeoff'] = 1;
|
||||
$cartData['surplus_num'] = 0;
|
||||
$orderCartInfo->update(['oid' => $orderInfo['id']], $cartData);
|
||||
return $orderInfo->toArray();
|
||||
} else {
|
||||
throw new ValidateException('Write off failure');
|
||||
}
|
||||
} else {
|
||||
if ($orderInfo['status'] == 3) {
|
||||
throw new ValidateException('订单已核销');
|
||||
}
|
||||
if ($confirm == 0) {
|
||||
/** @var UserServices $services */
|
||||
$services = app()->make(UserServices::class);
|
||||
$orderInfo['nickname'] = $services->value(['uid' => $orderInfo['uid']], 'nickname');
|
||||
return $orderInfo->toArray();
|
||||
}
|
||||
if (!$storeIntegralOrderServices->update($orderInfo['id'], ['status' => 3])) {
|
||||
throw new ValidateException('Write off failure');
|
||||
} else {
|
||||
//增加收货订单状态
|
||||
/** @var StoreIntegralOrderStatusServices $statusService */
|
||||
$statusService = app()->make(StoreIntegralOrderStatusServices::class);
|
||||
$statusService->save([
|
||||
'oid' => $orderInfo['id'],
|
||||
'change_type' => 'take_delivery',
|
||||
'change_message' => '已收货',
|
||||
'change_time' => time()
|
||||
]);
|
||||
}
|
||||
return $orderInfo->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取核销列表
|
||||
* @param $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function writeOffList($where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
|
||||
$list = $this->writeoffdao->getList($where, '*', $page, $limit, [
|
||||
'userInfo',
|
||||
'staffInfo',
|
||||
'orderInfo' => function ($query) {
|
||||
$query->field('id,order_id,pay_type');
|
||||
},
|
||||
'cartInfo' => function ($query) {
|
||||
$query->field('id,cart_info');
|
||||
},
|
||||
]);
|
||||
$count = $this->writeoffdao->count($where);
|
||||
if ($list) {
|
||||
$supplierIds = [];
|
||||
foreach ($list as $value) {
|
||||
switch ($value['type']) {
|
||||
case 0:
|
||||
break;
|
||||
case 2://供应商
|
||||
$supplierIds[] = $value['relation_id'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$supplierIds = array_unique($supplierIds);
|
||||
$supplierList = [];
|
||||
if ($supplierIds) {
|
||||
/** @var SystemSupplierServices $supplierServices */
|
||||
$supplierServices = app()->make(SystemSupplierServices::class);
|
||||
$supplierList = $supplierServices->getColumn([['id', 'in', $supplierIds], ['is_del', '=', 0]], 'id,supplier_name', 'id');
|
||||
}
|
||||
foreach ($list as &$item) {
|
||||
$cartInfo = $item['cartInfo'] ?? [];
|
||||
$cartInfo = is_string($cartInfo['cart_info']) ? json_decode($cartInfo['cart_info'], true) : $cartInfo['cart_info'];
|
||||
$item['productInfo'] = $cartInfo['productInfo'] ?? [];
|
||||
$orderInfo = $item['orderInfo'] ?? [];
|
||||
$item['order_id'] = $orderInfo['order_id'] ?? '';
|
||||
$item['pay_type'] = PayServices::PAY_TYPE[$item['pay_type']] ?? '其他方式';
|
||||
$item['plate_name'] = '平台';
|
||||
switch ($item['type']) {
|
||||
case 0:
|
||||
$item['plate_name'] = '平台';
|
||||
break;
|
||||
case 2://供应商
|
||||
$item['plate_name'] = '供应商:' . ($supplierList[$item['relation_id']]['supplier_name'] ?? '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存核销记录
|
||||
* @param int $oid
|
||||
* @param array $cartIds
|
||||
* @param array $data
|
||||
* @param array $orderInfo
|
||||
* @param array $cartInfo
|
||||
* @return bool
|
||||
*/
|
||||
public function saveWriteOff(int $oid, array $cartIds = [], array $data = [], array $orderInfo = [], array $cartInfo = [], int $admin_id = 0)
|
||||
{
|
||||
if (!$oid) {
|
||||
throw new ValidateException('缺少核销订单信息');
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
$orderInfo = $storeOrderServices->get($oid);
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('核销订单不存在');
|
||||
}
|
||||
$orderInfo = is_object($orderInfo) ? $orderInfo->toArray() : $orderInfo;
|
||||
if (!$cartInfo) {
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
if ($cartIds) {//商城存在部分核销
|
||||
$ids = array_unique(array_column($cartIds, 'cart_id'));
|
||||
$cartIds = array_combine($ids, $cartIds);
|
||||
//订单下原商品信息
|
||||
$cartInfo = $cartInfoServices->getCartColunm(['oid' => $orderInfo['id'], 'cart_id' => $ids], '*', 'cart_id');
|
||||
} else {//整单核销
|
||||
$cartInfo = $cartInfoServices->getCartColunm(['oid' => $orderInfo['id']], '*', 'cart_id');
|
||||
}
|
||||
}
|
||||
|
||||
$writeOffDataAll = [];
|
||||
$writeOffData = ['uid' => $orderInfo['uid'], 'oid' => $oid, 'writeoff_code' => $orderInfo['verify_code'], 'add_time' => time()];
|
||||
foreach ($cartInfo as $cart) {
|
||||
$write = $cartIds[$cart['cart_id']] ?? [];
|
||||
$info = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
|
||||
if (!$cartIds || $write) {
|
||||
$writeOffData['order_cart_id'] = $cart['id'];
|
||||
$writeOffData['writeoff_num'] = $write['cart_num'] ?? $cart['cart_num'];
|
||||
$writeOffData['type'] = $cart['type'];
|
||||
$writeOffData['relation_id'] = $cart['relation_id'];
|
||||
$writeOffData['product_id'] = $cart['product_id'];
|
||||
$writeOffData['product_type'] = $cart['product_type'];
|
||||
$writeOffData['writeoff_price'] = (float)bcmul((string)$info['truePrice'], (string)$writeOffData['writeoff_num'], 2);
|
||||
$writeOffData['staff_id'] = $data['staff_id'] ?? 0;
|
||||
if ($admin_id) {
|
||||
$writeOffData['is_admin'] = 1;
|
||||
$writeOffData['admin_id'] = $admin_id;
|
||||
}
|
||||
$writeOffDataAll[] = $writeOffData;
|
||||
}
|
||||
}
|
||||
if ($writeOffDataAll) {
|
||||
$this->writeoffdao->saveAll($writeOffDataAll);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销记录
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function userOrderWriteOffRecords(array $where = [], int $product_type = 0)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$count = 0;
|
||||
$times = [];
|
||||
if ($product_type == 4) {
|
||||
$list = $this->writeoffdao->getList($where + ['product_type' => 4], '*', $page, $limit);
|
||||
if ($list) {
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i', (int)$item['add_time']) : '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$list = $this->writeoffdao->getList($where, '*', $page, $limit, ['cartInfo']);
|
||||
$count = $this->writeoffdao->count($where);
|
||||
if ($list) {
|
||||
foreach ($list as &$item) {
|
||||
$item['time_key'] = $item['time'] = $item['add_time'] ? date('Y-m-d H:i', (int)$item['add_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i', (int)$item['add_time']) : '';
|
||||
$value = is_string($item['cartInfo']['cart_info']) ? json_decode($item['cartInfo']['cart_info'], true) : $item['cartInfo']['cart_info'];
|
||||
$value['productInfo']['store_name'] = $value['productInfo']['store_name'] ?? "";
|
||||
$value['productInfo']['store_name'] = substrUTf8($value['productInfo']['store_name'], 10, 'UTF-8', '');
|
||||
$item['cartInfo'] = $value;
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
}
|
||||
return ['count' => $count, 'list' => $list, 'time' => $times];
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销记录
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/9/4 16:51
|
||||
*/
|
||||
public function getOrderWriteOffRecords(array $where = [])
|
||||
{
|
||||
$list = $this->writeoffdao->getList($where, '*', 0, 0, ['cartInfo']);
|
||||
if ($list) {
|
||||
$adminIds = array_unique(array_filter(array_column($list, 'admin_id')));
|
||||
$staffIds = array_unique(array_filter(array_column($list, 'staff_id')));
|
||||
$adminList = $staffList = [];
|
||||
if ($adminIds) {
|
||||
/** @var SystemAdminServices $adminServices */
|
||||
$adminServices = app()->make(SystemAdminServices::class);
|
||||
$adminList = $adminServices->getColumn(['id' => $adminIds], 'real_name', 'id',true);
|
||||
}
|
||||
if($staffIds){
|
||||
/** @var StoreServiceServices $storeServiceServices */
|
||||
$storeServiceServices = app()->make(StoreServiceServices::class);
|
||||
$staffList = $storeServiceServices->getColumn(['id' => $staffIds], 'nickname', 'uid',true);
|
||||
}
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i', (int)$item['add_time']) : '';
|
||||
$value = is_string($item['cartInfo']['cart_info']) ? json_decode($item['cartInfo']['cart_info'], true) : $item['cartInfo']['cart_info'];
|
||||
$item['store_name'] = $value['productInfo']['store_name'] ?? "";
|
||||
$item['image'] = $value['productInfo']['image'] ?? "";
|
||||
$item['writeoff_name'] = $item['is_admin'] == 1 ? ($adminList[$item['admin_id']] ?? '') : ($staffList[$item['staff_id']] ?? '');
|
||||
unset($item['cartInfo']);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
606
app/services/order/cashier/CashierOrderServices.php
Normal file
606
app/services/order/cashier/CashierOrderServices.php
Normal file
@@ -0,0 +1,606 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order\cashier;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\jobs\activity\StorePromotionsJob;
|
||||
use app\jobs\user\MicroPayOrderJob;
|
||||
use app\services\BaseServices;
|
||||
use app\services\activity\coupon\StoreCouponUserServices;
|
||||
use app\services\activity\coupon\StoreCouponIssueServices;
|
||||
use app\services\order\StoreCartServices;
|
||||
use app\services\order\StoreOrderCartInfoServices;
|
||||
use app\services\order\StoreOrderComputedServices;
|
||||
use app\services\order\StoreOrderCreateServices;
|
||||
use app\services\order\StoreOrderSuccessServices;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\pay\YuePayServices;
|
||||
use app\services\user\level\SystemUserLevelServices;
|
||||
use app\services\user\level\UserLevelServices;
|
||||
use app\services\user\UserAddressServices;
|
||||
use app\services\user\UserInvoiceServices;
|
||||
use app\services\user\UserServices;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\traits\OptionTrait;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 收银台订单
|
||||
* Class CashierOrderServices
|
||||
* @package app\services\order\cashier
|
||||
*/
|
||||
class CashierOrderServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
use OptionTrait;
|
||||
|
||||
//余额支付
|
||||
const YUE_PAY = 1;
|
||||
//线上支付
|
||||
const ONE_LINE_PAY = 2;
|
||||
//现金支付
|
||||
const CASH_PAY = 3;
|
||||
|
||||
/**
|
||||
* 缓存订单信息
|
||||
* @param int $uid
|
||||
* @param array $cartInfo
|
||||
* @param array $priceGroup
|
||||
* @param array $other
|
||||
* @param array $addr
|
||||
* @param array $invalidCartInfo
|
||||
* @param array $deduction
|
||||
* @param int $cacheTime
|
||||
* @return string
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function cacheOrderInfo(int $uid, array $cartInfo, array $priceGroup, array $other = [], array $addr = [], array $invalidCartInfo = [], array $deduction = [], int $cacheTime = 600)
|
||||
{
|
||||
/** @var StoreOrderCreateServices $storeOrderCreateService */
|
||||
$storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
|
||||
$key = md5($storeOrderCreateService->getNewOrderId((string)$uid) . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8));
|
||||
CacheService::redisHandler()->set('admin_user_order_' . $uid . $key, compact('cartInfo', 'priceGroup', 'other', 'addr', 'invalidCartInfo', 'deduction'), $cacheTime);
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单缓存信息
|
||||
* @param int $uid
|
||||
* @param string $key
|
||||
* @return |null
|
||||
*/
|
||||
public function getCacheOrderInfo(int $uid, string $key)
|
||||
{
|
||||
$cacheName = 'admin_user_order_' . $uid . $key;
|
||||
if (!CacheService::redisHandler()->has($cacheName)) return null;
|
||||
return CacheService::redisHandler()->get($cacheName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单确认数据
|
||||
* @param array $user
|
||||
* @param $cartId
|
||||
* @param bool $new
|
||||
* @param int $addressId
|
||||
* @param int $shipping_type
|
||||
* @param int $store_id
|
||||
* @param int $coupon_id
|
||||
* @return array
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOrderConfirmData(int $uid, $cartId, bool $new, int $addressId, int $shipping_type = 1, int $coupon_id = 0)
|
||||
{
|
||||
$addr = $data = $user = [];
|
||||
if ($uid) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserCacheInfo($uid);
|
||||
}
|
||||
/** @var UserAddressServices $addressServices */
|
||||
$addressServices = app()->make(UserAddressServices::class);
|
||||
if ($addressId) {
|
||||
$addr = $addressServices->getAdderssCache($addressId);
|
||||
}
|
||||
//没传地址id或地址已删除未找到 ||获取默认地址
|
||||
if (!$addr && $uid) {
|
||||
$addr = $addressServices->getUserDefaultAddressCache($uid);
|
||||
}
|
||||
/** @var StoreCartServices $cartServices */
|
||||
$cartServices = app()->make(StoreCartServices::class);
|
||||
//获取购物车信息
|
||||
$cartGroup = $cartServices->getUserProductCartListV1($uid, $cartId, $new, $addr, $shipping_type, $coupon_id);
|
||||
$storeFreePostage = floatval(sys_config('store_free_postage')) ?: 0;//满额包邮金额
|
||||
$data['storeFreePostage'] = $storeFreePostage;
|
||||
$validCartInfo = $cartGroup['valid'];
|
||||
$giveCartList = $cartGroup['giveCartList'] ?? [];
|
||||
/** @var StoreOrderComputedServices $computedServices */
|
||||
$computedServices = app()->make(StoreOrderComputedServices::class);
|
||||
$priceGroup = $computedServices->getOrderPriceGroup($uid, $validCartInfo, $addr, $storeFreePostage);
|
||||
$priceGroup['couponPrice'] = $cartGroup['couponPrice'] ?? 0;
|
||||
$priceGroup['firstOrderPrice'] = $cartGroup['firstOrderPrice'] ?? 0;
|
||||
$validCartInfo = array_merge($priceGroup['cartInfo'] ?? $validCartInfo, $giveCartList);
|
||||
$other = [
|
||||
'offlinePostage' => sys_config('offline_postage'),
|
||||
'integralRatio' => sys_config('integral_ratio'),
|
||||
'give_integral' => $cartGroup['giveIntegral'] ?? 0,
|
||||
'give_coupon' => $cartGroup['giveCoupon'] ?? [],
|
||||
'give_product' => $cartGroup['giveProduct'],
|
||||
'promotions' => $cartGroup['promotions']
|
||||
];
|
||||
$deduction = $cartGroup['deduction'];
|
||||
$data['product_type'] = $deduction['product_type'] ?? 0;
|
||||
$data['valid_count'] = count($validCartInfo);
|
||||
$data['addressInfo'] = $addr;
|
||||
$data['type'] = $deduction['type'] ?? 0;
|
||||
$data['activity_id'] = $deduction['activity_id'] ?? 0;
|
||||
$data['seckill_id'] = $deduction['type'] == 1 ? $deduction['activity_id'] : 0;
|
||||
$data['bargain_id'] = $deduction['type'] == 2 ? $deduction['activity_id'] : 0;
|
||||
$data['combination_id'] = $deduction['type'] == 3 ? $deduction['activity_id'] : 0;
|
||||
$data['storeIntegralId'] = $deduction['type'] == 4 ? $deduction['activity_id'] : 0;
|
||||
$data['discount_id'] = $deduction['type'] == 5 ? $deduction['activity_id'] : 0;
|
||||
$data['newcomer_id'] = $deduction['type'] == 7 ? $deduction['activity_id'] : 0;
|
||||
$data['deduction'] = in_array($deduction['product_type'], [1, 2]) || $deduction['activity_id'] > 0;
|
||||
$data['cartInfo'] = array_merge($cartGroup['cartInfo'], $giveCartList);
|
||||
// $data['giveCartInfo'] = $giveCartList;
|
||||
$data['custom_form'] = [];
|
||||
$data['give_integral'] = $other['give_integral'];
|
||||
$data['give_coupon'] = [];
|
||||
if ($other['give_coupon']) {
|
||||
/** @var StoreCouponIssueServices $couponIssueService */
|
||||
$couponIssueService = app()->make(StoreCouponIssueServices::class);
|
||||
$data['give_coupon'] = $couponIssueService->getColumn([['id', 'IN', $other['give_coupon']]], 'id,coupon_title');
|
||||
}
|
||||
$data['orderKey'] = $this->cacheOrderInfo($uid, $validCartInfo, $priceGroup, $other, $addr, $cartGroup['invalid'] ?? [], $deduction);
|
||||
unset($priceGroup['cartInfo']);
|
||||
$data['priceGroup'] = $priceGroup;
|
||||
|
||||
$userInfo = ['uid' => $user['uid'] ?? 0, 'nickname' => $user['nickname'] ?? '', 'avatar' => $user['avatar'] ?? '', 'phone' => $user['phone'] ?? '', 'now_money' => $user['now_money'] ?? 0, 'integral' => $user['integral'] ?? 0];
|
||||
//会员
|
||||
$userInfo['isMember'] = isset($user['is_money_level']) && $user['is_money_level'] > 0 ? 1 : 0;
|
||||
//等级
|
||||
$userInfo['level'] = $user['level'] ?? 0;
|
||||
$userInfo['level_status'] = 0;
|
||||
$userInfo['level_grade'] = '';
|
||||
$userInfo['vip'] = isset($priceGroup['vipPrice']) && $priceGroup['vipPrice'] > 0;
|
||||
$userInfo['vip_id'] = 0;
|
||||
$userInfo['discount'] = 0;
|
||||
//用户等级是否开启
|
||||
if (sys_config('member_func_status', 1)) {
|
||||
/** @var UserLevelServices $levelServices */
|
||||
$levelServices = app()->make(UserLevelServices::class);
|
||||
$userLevel = $levelServices->getUerLevelInfoByUid($uid);
|
||||
if ($userInfo['vip'] || $userLevel) {
|
||||
$userInfo['vip'] = true;
|
||||
$userInfo['vip_id'] = $userLevel['id'] ?? 0;
|
||||
$userInfo['discount'] = $userLevel['discount'] ?? 0;
|
||||
}
|
||||
if ($userInfo['level']) {
|
||||
/** @var SystemUserLevelServices $levelServices */
|
||||
$levelServices = app()->make(SystemUserLevelServices::class);
|
||||
$levelInfo = $levelServices->getOne(['id' => $userInfo['level']], 'id,name,grade');
|
||||
$userInfo['level_grade'] = $levelInfo['grade'] ?? '';
|
||||
$userInfo['level_status'] = 1;
|
||||
}
|
||||
}
|
||||
$userInfo['real_name'] = $user['real_name'] ?? $user['nickname'] ?? '';
|
||||
$userInfo['record_pone'] = $user['record_pone'] ?? $user['phone'] ?? '';
|
||||
$data['userInfo'] = $userInfo;
|
||||
$data['offlinePostage'] = $other['offlinePostage'];
|
||||
$data['integralRatio'] = $other['integralRatio'];
|
||||
$data['integral_ratio_status'] = (int)(sys_config('integral_ratio_status', 1) && in_array($data['type'], [0, 6]));
|
||||
$data['store_func_status'] = (int)(sys_config('store_func_status', 1));//门店是否开启
|
||||
$data['store_self_mention'] = (int)sys_config('store_self_mention');
|
||||
/** @var UserInvoiceServices $userInvoice */
|
||||
$userInvoice = app()->make(UserInvoiceServices::class);
|
||||
$invoice_func = $userInvoice->invoiceFuncStatus();
|
||||
$data['invoice_func'] = $invoice_func['invoice_func'];
|
||||
$data['special_invoice'] = $invoice_func['special_invoice'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算订单金额
|
||||
* @param int $uid
|
||||
* @param array $userInfo
|
||||
* @param array $cartGroup
|
||||
* @param int $addressId
|
||||
* @param string $payType
|
||||
* @param bool $useIntegral
|
||||
* @param int $couponId
|
||||
* @param int $shippingType
|
||||
* @return array
|
||||
*/
|
||||
public function computeOrder(int $uid, array $cartGroup, int $addressId, string $payType, bool $useIntegral = false, int $shippingType = 1)
|
||||
{
|
||||
$userInfo = [];
|
||||
if ($uid) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('用户不存在!');
|
||||
}
|
||||
}
|
||||
$cartInfo = $cartGroup['cartInfo'];
|
||||
$priceGroup = $cartGroup['priceGroup'];
|
||||
$deduction = $cartGroup['deduction'];
|
||||
$other = $cartGroup['other'];
|
||||
$promotions = $other['promotions'] ?? [];
|
||||
$payPrice = (float)$priceGroup['totalPrice'];
|
||||
$payIntegral = (int)$priceGroup['totalIntegral'] ?? 0;
|
||||
$couponPrice = (float)$priceGroup['couponPrice'];
|
||||
$firstOrderPrice = (float)$priceGroup['firstOrderPrice'];
|
||||
$type = (int)$deduction['type'] ?? 0;
|
||||
/** @var StoreOrderComputedServices $computeOrderService */
|
||||
$computeOrderService = app()->make(StoreOrderComputedServices::class);
|
||||
$promotionsPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'promotions_true_price');//优惠活动优惠
|
||||
$promotionsDetail = [];
|
||||
if ($promotions) {
|
||||
foreach ($promotions as $key => $value) {
|
||||
if (isset($value['details']['sum_promotions_price']) && $value['details']['sum_promotions_price']) {
|
||||
$promotionsDetail[] = ['id' => $value['id'], 'name' => $value['name'], 'title' => $value['title'], 'desc' => $value['desc'], 'promotions_price' => $value['details']['sum_promotions_price'], 'promotions_type' => $value['promotions_type']];
|
||||
}
|
||||
}
|
||||
if ($promotionsDetail) {
|
||||
$typeArr = array_column($promotionsDetail, 'promotions_type');
|
||||
array_multisort($typeArr, SORT_ASC, $promotionsDetail);
|
||||
}
|
||||
}
|
||||
$addr = $cartGroup['addr'] ?? [];
|
||||
$postage = $priceGroup;
|
||||
if (!$addr || $addr['id'] != $addressId) {
|
||||
/** @var UserAddressServices $addressServices */
|
||||
$addressServices = app()->make(UserAddressServices::class);
|
||||
$addr = $addressServices->getAdderssCache($addressId);
|
||||
//改变地址重新计算邮费
|
||||
$postage = [];
|
||||
}
|
||||
[$p, $payPostage, $storePostageDiscount, $storeFreePostage, $isStoreFreePostage] = $computeOrderService->computedPayPostage($uid, $shippingType, $payType, $cartInfo, $addr, $payPrice, $postage, $other);
|
||||
if ($couponPrice < $payPrice) {//优惠券金额
|
||||
$payPrice = bcsub((string)$payPrice, (string)$couponPrice, 2);
|
||||
} else {
|
||||
$payPrice = 0;
|
||||
}
|
||||
if ($firstOrderPrice < $payPrice) {//首单优惠金额
|
||||
$payPrice = bcsub((string)$payPrice, (string)$firstOrderPrice, 2);
|
||||
} else {
|
||||
$payPrice = 0;
|
||||
}
|
||||
if (sys_config('integral_ratio_status') && in_array($type, [0, 6])) {
|
||||
//使用积分
|
||||
[$payPrice, $deductionPrice, $usedIntegral, $SurplusIntegral] = $computeOrderService->useIntegral($useIntegral, $userInfo, $payPrice, $other);
|
||||
}
|
||||
$payPrice = (float)bcadd((string)$payPrice, (string)$payPostage, 2);
|
||||
return [
|
||||
'total_price' => $priceGroup['totalPrice'],
|
||||
'pay_price' => max($payPrice, 0),
|
||||
'pay_integral' => max($payIntegral, 0),
|
||||
'total_postage' => bcadd((string)$payPostage, (string)($storePostageDiscount ?? 0), 2),
|
||||
'pay_postage' => $payPostage,
|
||||
'first_order_price' => $firstOrderPrice ?? 0,
|
||||
'coupon_price' => $couponPrice ?? 0,
|
||||
'promotions_price' => $promotionsPrice,
|
||||
'promotions_detail' => $promotionsDetail,
|
||||
'deduction_price' => $deductionPrice ?? 0,
|
||||
'usedIntegral' => $usedIntegral ?? 0,
|
||||
'SurplusIntegral' => $SurplusIntegral ?? 0,
|
||||
'storePostageDiscount' => $storePostageDiscount ?? 0,
|
||||
'isStoreFreePostage' => $isStoreFreePostage ?? false,
|
||||
'storeFreePostage' => $storeFreePostage ?? 0,
|
||||
// 'cartInfo' => $cartInfo
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台用户优惠券
|
||||
* @param int $uid
|
||||
* @param int $storeId
|
||||
* @param array $cartIds
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getCouponList(int $uid, int $storeId, array $cartIds)
|
||||
{
|
||||
/** @var StoreCartServices $cartService */
|
||||
$cartService = app()->make(StoreCartServices::class);
|
||||
$cart = $cartService->getUserCartList($uid, 1, $cartIds, $storeId, 0, 4, 0, 0, 0, false);
|
||||
$cartInfo = $cart['valid'];
|
||||
if (!$cartInfo) {
|
||||
throw new ValidateException('购物车暂无货物!');
|
||||
}
|
||||
/** @var StoreCouponissueServices $couponIssueServices */
|
||||
$couponIssueServices = app()->make(StoreCouponissueServices::class);
|
||||
return $couponIssueServices->getCanUseCoupon($uid, $cartInfo, $cart['promotions'] ?? [], $storeId, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成订单
|
||||
* @param int $uid
|
||||
* @param array $userInfo
|
||||
* @param array $computeData
|
||||
* @param int $staffId
|
||||
* @param array $cartIds
|
||||
* @param string $payType
|
||||
* @param bool $integral
|
||||
* @param bool $coupon
|
||||
* @param string $remarks
|
||||
* @param string $changePrice
|
||||
* @param bool $isPrice
|
||||
* @param int $coupon_id
|
||||
* @param int $seckillId
|
||||
* @param $collate_code_id
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function createOrder(int $uid, string $key, array $cartGroup, int $addressId, string $payType, array $addressInfo, int $staffId, bool $useIntegral = false, $couponId = 0, $mark = '', $shippingType = 1, string $from = '')
|
||||
{
|
||||
//兼容门店虚拟用户下单
|
||||
$field = ['real_name', 'phone', 'province', 'city', 'district', 'street', 'detail'];
|
||||
$userInfo = [];
|
||||
if ($uid) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('用户不存在!');
|
||||
}
|
||||
$userInfo = $userInfo->toArray();
|
||||
}
|
||||
if (!$addressInfo) {
|
||||
foreach ($field as $key) {
|
||||
$addressInfo[$key] = '';
|
||||
}
|
||||
}
|
||||
/** @var StoreOrderComputedServices $computedServices */
|
||||
$computedServices = app()->make(StoreOrderComputedServices::class);
|
||||
$priceData = $computedServices->computedOrder($uid, $userInfo, $cartGroup, $addressId, $payType, $useIntegral, $couponId, $shippingType);
|
||||
$cartInfo = $cartGroup['cartInfo'];
|
||||
$priceGroup = $cartGroup['priceGroup'];
|
||||
$cartIds = [];
|
||||
$totalNum = 0;
|
||||
$gainIntegral = 0;
|
||||
foreach ($cartInfo as $cart) {
|
||||
$cartIds[] = $cart['id'];
|
||||
$totalNum += $cart['cart_num'];
|
||||
$cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul((string)$cart['cart_num'], (string)$cart['productInfo']['give_integral'], 0) : 0;
|
||||
$gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0);
|
||||
}
|
||||
|
||||
$cartInfo = $cartGroup['cartInfo'];
|
||||
$deduction = $cartGroup['deduction'];
|
||||
$promotions_give = [
|
||||
'give_integral' => $cartGroup['give_integral'] ?? 0,
|
||||
'give_coupon' => $cartGroup['giveCoupon'] ?? [],
|
||||
'give_product' => $cartGroup['giveProduct'] ?? [],
|
||||
'promotions' => $cartGroup['promotions'] ?? []
|
||||
];
|
||||
$type = (int)$deduction['type'] ?? 0;
|
||||
/** @var StoreOrderCreateServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderCreateServices::class);
|
||||
$product_type = (int)$deduction['product_type'] ?? 0;
|
||||
$orderInfo = [
|
||||
'uid' => $uid,
|
||||
'type' => $type,
|
||||
'order_id' => $orderServices->getNewOrderId(),
|
||||
'real_name' => $addressInfo['real_name'] ?: $userInfo['nickname'] ?? '',
|
||||
'user_phone' => $addressInfo['phone'] ?: $userInfo['phone'] ?? '',
|
||||
'user_address' => isset($addressInfo['addressInfo']) && $addressInfo['addressInfo'] ? $addressInfo['addressInfo'] : $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['street'] . ' ' . $addressInfo['detail'],
|
||||
'cart_id' => $cartIds,
|
||||
'clerk_id' => 0,
|
||||
'staff_id' => $staffId,
|
||||
'total_num' => $totalNum,
|
||||
'total_price' => $priceGroup['sumPrice'] ?? $priceGroup['totalPrice'],
|
||||
'total_postage' => $priceData['total_postage'] ?? $priceGroup['storePostage'],
|
||||
'coupon_id' => $couponId,
|
||||
'coupon_price' => $priceData['coupon_price'],
|
||||
'first_order_price' => $priceData['first_order_price'],
|
||||
'promotions_price' => $priceData['promotions_price'],
|
||||
'pay_integral' => $priceData['pay_integral'],
|
||||
'pay_price' => $priceData['pay_price'],
|
||||
'pay_postage' => $priceData['pay_postage'],
|
||||
'deduction_price' => $priceData['deduction_price'],
|
||||
'paid' => 0,
|
||||
'pay_type' => $payType,
|
||||
'use_integral' => $priceData['usedIntegral'],
|
||||
'gain_integral' => $gainIntegral,
|
||||
'mark' => htmlspecialchars($mark),
|
||||
'product_type' => $product_type,
|
||||
'activity_id' => 0,
|
||||
'pink_id' => 0,
|
||||
'cost' => $priceGroup['costPrice'],
|
||||
'is_channel' => 2,
|
||||
'unique' => $key,
|
||||
'add_time' => time(),
|
||||
'shipping_type' => $shippingType,
|
||||
'channel_type' => $userInfo['user_type'] ?? '',
|
||||
'province' => '',
|
||||
'spread_uid' => 0,
|
||||
'spread_two_uid' => 0,
|
||||
'promotions_give' => json_encode($promotions_give),
|
||||
'give_integral' => $promotions_give['give_integral'] ?? 0,
|
||||
'give_coupon' => implode(',', $promotions_give['give_coupon'] ?? []),
|
||||
'division_id' => $userInfo['division_id'] ?? 0,
|
||||
'division_agent_id' => $userInfo['agent_id'] ?? 0,
|
||||
'division_staff_id' => $userInfo['staff_id'] ?? 0,
|
||||
];
|
||||
if ($product_type == 4 || $shippingType == 2) {//次卡商品收银台购买
|
||||
$orderInfo['verify_code'] = $orderServices->getStoreCode();
|
||||
$orderInfo['shipping_type'] = 2;//修改门店自提
|
||||
}
|
||||
$order = $this->transaction(function () use ($key, $cartInfo, $type, $priceData, $orderInfo, $orderServices, $couponId, $userInfo, $useIntegral, $promotions_give, $payType) {
|
||||
/** @var StoreOrderCartInfoServices $cartServices */
|
||||
$cartServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$order = $orderServices->save($orderInfo);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单生成失败');
|
||||
}
|
||||
//使用优惠券
|
||||
if ($couponId) {
|
||||
/** @var StoreCouponUserServices $couponServices */
|
||||
$couponServices = app()->make(StoreCouponUserServices::class);
|
||||
$res1 = $couponServices->useCoupon($couponId, (int)($userInfo['uid'] ?? 0), $cartInfo, []);
|
||||
if (!$res1) {
|
||||
throw new ValidateException('使用优惠劵失败!');
|
||||
}
|
||||
}
|
||||
//积分抵扣
|
||||
$orderServices->deductIntegral($userInfo, $useIntegral, $priceData, (int)($userInfo['uid'] ?? 0), $key);
|
||||
//修改门店库存
|
||||
$orderServices->decGoodsStock($cartInfo, $type);
|
||||
//保存购物车商品信息
|
||||
$cartServices->setCartInfo($order['id'], $cartInfo, $userInfo['uid'] ?? 0, $promotions_give['promotions'] ?? []);
|
||||
return $order->toArray();
|
||||
});
|
||||
|
||||
|
||||
$news = false;
|
||||
$addressId = $type = $activity_id = 0;
|
||||
$delCart = true;
|
||||
//扣除优惠活动赠品限量
|
||||
StorePromotionsJob::dispatchDo('changeGiveLimit', [$promotions_give]);
|
||||
$group = compact('cartInfo', 'priceData', 'addressId', 'cartIds', 'news', 'delCart');
|
||||
$orderServices->delCart($group);
|
||||
$change_manager_id = $staffId;
|
||||
$change_manager_type = 'store';
|
||||
event('order.create', [$order, $userInfo, $group, compact('type', 'activity_id', 'change_manager_id', 'change_manager_type'), 0]);
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台支付
|
||||
* @param string $orderId
|
||||
* @param string $payType
|
||||
* @param string $userCode
|
||||
* @param string $authCode
|
||||
* @return array
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function paySuccess(string $orderId, string $payType, string $userCode, string $authCode = '')
|
||||
{
|
||||
/** @var StoreOrderSuccessServices $orderService */
|
||||
$orderService = app()->make(StoreOrderSuccessServices::class);
|
||||
$orderInfo = $orderService->get(['order_id' => $orderId]);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('没有查询到订单信息');
|
||||
}
|
||||
if ($orderInfo->paid) {
|
||||
throw new ValidateException('订单已支付');
|
||||
}
|
||||
if ($orderInfo->is_del) {
|
||||
throw new ValidateException('订单已取消');
|
||||
}
|
||||
switch ($payType) {
|
||||
case PayServices::YUE_PAY://余额支付
|
||||
$is_cashier_yue_pay_verify = (int)sys_config('is_cashier_yue_pay_verify'); // 收银台余额支付是否需要验证【是/否】
|
||||
if (!$orderInfo['uid']) {
|
||||
throw new ValidateException('余额支付用户信息不存在无法支付');
|
||||
}
|
||||
if (!$userCode && $is_cashier_yue_pay_verify) {
|
||||
throw new ValidateException('缺少扫码支付参数');
|
||||
}
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userInfo = $userService->getUserInfo($orderInfo->uid, ['uid', 'rand_code']);
|
||||
//读取缓存用户code
|
||||
$rand_code = CacheService::redisHandler()->get('user_rand_code' . $orderInfo->uid);
|
||||
CacheService::redisHandler()->delete('user_rand_code' . $orderInfo->uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('余额支付用户不存在');
|
||||
}
|
||||
if ($rand_code != $userCode && $is_cashier_yue_pay_verify) {
|
||||
throw new ValidateException('二维码已使用或不正确,请确认后重新扫码');
|
||||
}
|
||||
/** @var YuePayServices $payService */
|
||||
$payService = app()->make(YuePayServices::class);
|
||||
$pay = $payService->yueOrderPay($orderInfo->toArray(), $orderInfo->uid);
|
||||
if ($pay['status'] === true)
|
||||
return ['status' => 'SUCCESS'];
|
||||
else if ($pay['status'] === 'pay_deficiency') {
|
||||
throw new ValidateException($pay['msg']);
|
||||
} else {
|
||||
return ['status' => 'ERROR', 'message' => is_array($pay) ? $pay['msg'] ?? '余额支付失败' : $pay];
|
||||
}
|
||||
case PayServices::WEIXIN_PAY://微信支付
|
||||
case PayServices::ALIPAY_PAY://支付宝支付
|
||||
if (!$authCode) {
|
||||
throw new ValidateException('缺少支付付款二维码CODE');
|
||||
}
|
||||
|
||||
$pay = new PayServices();
|
||||
/** @var StoreOrderCartInfoServices $orderInfoServices */
|
||||
$orderInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$body = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id']);
|
||||
$body = substrUTf8($body, 30);
|
||||
try {
|
||||
//扫码支付
|
||||
$response = $pay->setAuthCode($authCode)->pay($payType, '', $orderInfo->order_id, $orderInfo->pay_price, 'product', $body);
|
||||
} catch (\Throwable $e) {
|
||||
\think\facade\Log::error('收银端' . $payType . '扫码支付失败,原因:' . $e->getMessage());
|
||||
return ['status' => 'ERROR', 'message' => '支付失败,原因:' . $e->getMessage()];
|
||||
}
|
||||
//支付成功paid返回1
|
||||
if ($response['paid']) {
|
||||
if (!$orderService->paySuccess($orderInfo->toArray(), $payType, ['trade_no' => $response['payInfo']['transaction_id'] ?? ''])) {
|
||||
return ['status' => 'ERROR', 'message' => '支付失败'];
|
||||
}
|
||||
//支付成功刪除購物車
|
||||
/** @var StoreCartServices $cartServices */
|
||||
$cartServices = app()->make(StoreCartServices::class);
|
||||
$cartServices->deleteCartStatus($orderInfo['cart_id'] ?? []);
|
||||
return ['status' => 'SUCCESS'];
|
||||
} else {
|
||||
if ($payType === PayServices::WEIXIN_PAY) {
|
||||
if (isset($response['payInfo']['err_code']) && in_array($response['payInfo']['err_code'], ['AUTH_CODE_INVALID', 'NOTENOUGH'])) {
|
||||
return ['status' => 'ERROR', 'message' => '支付失败'];
|
||||
}
|
||||
//微信付款码支付需要同步更改状态
|
||||
$secs = 5;
|
||||
if (isset($order_info['payInfo']['err_code']) && $order_info['payInfo']['err_code'] === 'USERPAYING') {
|
||||
$secs = 10;
|
||||
}
|
||||
//放入队列执行
|
||||
MicroPayOrderJob::dispatchSece($secs, [$orderInfo['order_id'], 0]);
|
||||
}
|
||||
return ['status' => 'PAY_ING', 'message' => $response['message']];
|
||||
}
|
||||
break;
|
||||
case PayServices::CASH_PAY://收银台现金支付
|
||||
if (!$orderService->paySuccess($orderInfo->toArray(), $payType)) {
|
||||
return ['status' => 'ERROR', 'message' => '支付失败'];
|
||||
} else {
|
||||
return ['status' => 'SUCCESS'];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ValidateException('暂无支付方式,无法支付');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
294
app/services/order/store/BranchOrderServices.php
Normal file
294
app/services/order/store/BranchOrderServices.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order\store;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\OtherOrderServices;
|
||||
use app\services\order\StoreOrderRefundServices;
|
||||
use app\services\order\StoreOrderServices;
|
||||
use app\services\order\StoreOrderStatusServices;
|
||||
use app\services\user\UserRechargeServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class StoreOrderWapServices
|
||||
* @package app\services\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class BranchOrderServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 获取订单数量
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderData(int $store_id, int $staff_id = 0)
|
||||
{
|
||||
$where = ['pid' => 0, 'refund_status' => [0, 3], 'is_del' => 0, 'is_system_del' => 0];
|
||||
$data['order_count'] = (string)$this->dao->count($where);
|
||||
$where = $where + ['paid' => 1];
|
||||
$data['sum_price'] = (string)$this->dao->sum($where, 'pay_price', true);
|
||||
|
||||
$countWhere = ['store_id' => $store_id];
|
||||
if ($staff_id) {
|
||||
$countWhere['staff_id'] = $staff_id;
|
||||
}
|
||||
$pid_where = ['pid' => 0];
|
||||
$not_pid_where = ['not_pid' => 1];
|
||||
$data['unpaid_count'] = (string)$this->dao->count(['status' => 0] + $countWhere + $pid_where);
|
||||
$data['unshipped_count'] = (string)$this->dao->count(['status' => 1] + $countWhere + $pid_where);
|
||||
$data['unwriteoff_count'] = (string)$this->dao->count(['status' => 5] + $countWhere + $pid_where);
|
||||
$data['received_count'] = (string)$this->dao->count(['status' => 2] + $countWhere + $pid_where);
|
||||
$data['evaluated_count'] = (string)$this->dao->count(['status' => 3] + $countWhere + $pid_where);
|
||||
$data['complete_count'] = (string)$this->dao->count(['status' => 4] + $countWhere + $pid_where);
|
||||
/** @var StoreOrderRefundServices $storeOrderRefundServices */
|
||||
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
$refund_where = ['is_cancel' => 0];
|
||||
$data['refunding_count'] = (string)$storeOrderRefundServices->count($refund_where + ['refund_type' => [0, 1, 2, 4, 5]]);
|
||||
$data['refunded_count'] = (string)$storeOrderRefundServices->count($refund_where + ['refund_type' => [3, 6]]);
|
||||
$data['refund_count'] = (string)$storeOrderRefundServices->count($refund_where);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单统计详情列表
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param int $type
|
||||
* @param array $time
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function time(int $store_id, int $staff_id = 0, int $type = 1, array $time = [])
|
||||
{
|
||||
if (!$time) {
|
||||
return [[], []];
|
||||
}
|
||||
[$start, $stop, $front, $front_stop] = $time;
|
||||
$order_where = ['pid' => 0, 'is_del' => 0, 'paid' => 1];
|
||||
if ($type != 3) {
|
||||
$order_where['refund_status'] = [0, 3];
|
||||
}
|
||||
if ($staff_id) $order_where['staff_id'] = $staff_id;
|
||||
switch ($type) {
|
||||
case 1://配送
|
||||
case 2://配送
|
||||
$order_where['type'] = 7;
|
||||
break;
|
||||
case 3://退款
|
||||
$order_where['status'] = -3;
|
||||
break;
|
||||
case 4://收银订单
|
||||
$order_where['type'] = 6;
|
||||
break;
|
||||
case 5://核销
|
||||
$order_where['type'] = 5;
|
||||
break;
|
||||
}
|
||||
if ($type == 2) {//数量
|
||||
$frontPrice = $this->dao->count($order_where + ['time' => [$front, $front_stop]]);
|
||||
$nowPrice = $this->dao->count($order_where + ['time' => [$start, $stop]]);
|
||||
} else {//金额
|
||||
$frontPrice = $this->dao->sum($order_where + ['time' => [$front, $front_stop]], 'pay_price', true);
|
||||
$nowPrice = $this->dao->sum($order_where + ['time' => [$start, $stop]], 'pay_price', true);
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getOrderList($order_where + ['time' => [$start, $stop]], ['id', 'order_id', 'uid', 'spread_uid', 'pay_price', 'add_time'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
return [[$nowPrice, $frontPrice], $list];
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单每月统计数据(按天分组)
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderDataPriceCount(array $where, array $field = ['sum(pay_price) as price', 'count(id) as count', 'FROM_UNIXTIME(add_time, \'%m-%d\') as time'])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$order_where = ['is_del' => 0, 'is_system_del' => 0, 'paid' => 1, 'refund_status' => [0, 3]];
|
||||
$where = array_merge($where, $order_where);
|
||||
return $this->dao->getOrderDataPriceCount($where, $field, $page, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表
|
||||
* @param array $where
|
||||
* @param array $with
|
||||
* @param false $is_count
|
||||
* @return array|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getStoreOrderList(array $where, array $field = ['*'], array $with = [], $is_count = false)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getOrderList($where, $field, $page, $limit, $with, 'id desc');
|
||||
if ($is_count) {
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
/** @var StoreOrderServices $orderServices */
|
||||
$orderServices = app()->make(StoreOrderServices::class);
|
||||
$list = $orderServices->tidyOrderList($list);
|
||||
foreach ($list as &$item) {
|
||||
$refund_num = array_sum(array_column($item['refund'], 'refund_num'));
|
||||
$cart_num = 0;
|
||||
foreach ($item['_info'] as $items) {
|
||||
if (isset($items['cart_info']['is_gift']) && $items['cart_info']['is_gift']) continue;
|
||||
$cart_num += $items['cart_info']['cart_num'];
|
||||
}
|
||||
$item['is_all_refund'] = $refund_num == $cart_num;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* @param $id
|
||||
* @param int $store_id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function cancelOrder($id, int $store_id = 0)
|
||||
{
|
||||
$where = ['id' => $id, 'is_del' => 0];
|
||||
|
||||
$order = $this->dao->getOne($where);
|
||||
if (!$order) {
|
||||
throw new ValidateException('没有查到此订单');
|
||||
}
|
||||
if ($order->paid) {
|
||||
throw new ValidateException('订单已经支付无法取消');
|
||||
}
|
||||
/** @var StoreOrderRefundServices $refundServices */
|
||||
$refundServices = app()->make(StoreOrderRefundServices::class);
|
||||
$this->transaction(function () use ($refundServices, $order) {
|
||||
//回退积分和优惠卷
|
||||
$res = $refundServices->integralAndCouponBack($order);
|
||||
//回退库存和销量
|
||||
$res = $res && $refundServices->regressionStock($order);
|
||||
$order->is_del = 1;
|
||||
if (!($res && $order->save())) {
|
||||
throw new ValidateException('取消订单失败');
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
* @param $uni
|
||||
* @param $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function removeOrder(string $uni, int $uid)
|
||||
{
|
||||
$order = $this->getUserOrderDetail($uni, $uid);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在!');
|
||||
}
|
||||
$order = $this->tidyOrder($order);
|
||||
if ($order['_status']['_type'] != 0 && $order['_status']['_type'] != -2 && $order['_status']['_type'] != 4)
|
||||
throw new ValidateException('该订单无法删除!');
|
||||
|
||||
$order->is_del = 1;
|
||||
/** @var StoreOrderStatusServices $statusService */
|
||||
$statusService = app()->make(StoreOrderStatusServices::class);
|
||||
$res = $statusService->save([
|
||||
'oid' => $order['id'],
|
||||
'change_type' => 'remove_order',
|
||||
'change_message' => '删除订单',
|
||||
'change_time' => time()
|
||||
]);
|
||||
if ($order->save() && $res) {
|
||||
//未支付和已退款的状态下才可以退积分退库存退优惠券
|
||||
if ($order['_status']['_type'] == 0 || $order['_status']['_type'] == -2) {
|
||||
/** @var StoreOrderRefundServices $refundServices */
|
||||
$refundServices = app()->make(StoreOrderRefundServices::class);
|
||||
$this->transaction(function () use ($order, $refundServices) {
|
||||
//回退积分和优惠卷
|
||||
$res = $refundServices->integralAndCouponBack($order);
|
||||
//回退库存
|
||||
$res = $res && $refundServices->regressionStock($order);
|
||||
if (!$res) {
|
||||
throw new ValidateException('取消订单失败!');
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
throw new ValidateException('订单删除失败!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页交易统计
|
||||
* @param int $store_id
|
||||
* @param array $time
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function orderChart(int $store_id, array $time)
|
||||
{
|
||||
$chartdata = [];
|
||||
$where = ['time' => $time, 'pid' => 0];
|
||||
if ($store_id) $where['store_id'] = $store_id;
|
||||
|
||||
$order_where = ['paid' => 1, 'pid' => 0, 'is_system_del' => 0, 'refund_status' => [0, 3]];
|
||||
|
||||
$list = $this->dao->getOrderList($where + $order_where, ['id', 'order_id', 'uid', 'pay_price', 'pay_time'], 0, 10);
|
||||
$chartdata['order_list'] = $list;
|
||||
|
||||
$chartdata['bing_xdata'] = ['收银订单', '充值订单', '分配订单', '核销订单', '付费会员订单'];
|
||||
$color = ['#2EC479', '#7F7AE5', '#FFA21B', '#46A3FF', '#FF6046'];
|
||||
//收银订单
|
||||
$pay[] = $this->dao->sum(['type' => 106] + $order_where + $where, 'pay_price', true);
|
||||
/** @var UserRechargeServices $userRecharge */
|
||||
$userRecharge = app()->make(UserRechargeServices::class);
|
||||
$pay[] = $userRecharge->sum(['paid' => 1] + $where, 'price', true);
|
||||
//分配订单
|
||||
$pay[] = $this->dao->sum(['type' => 107] + $order_where + $where, 'pay_price', true);
|
||||
//核销订单
|
||||
$pay[] = $this->dao->sum(['type' => 105] + $order_where + $where, 'pay_price', true);
|
||||
|
||||
/** @var OtherOrderServices $vipOrderServices */
|
||||
$vipOrderServices = app()->make(OtherOrderServices::class);
|
||||
$pay[] = $vipOrderServices->sum(['paid' => 1, 'type' => [0, 1, 2, 4]] + $where, 'pay_price', true);
|
||||
foreach ($pay as $key => $item) {
|
||||
$bing_data[] = ['name' => $chartdata['bing_xdata'][$key], 'value' => $pay[$key], 'itemStyle' => ['color' => $color[$key]]];
|
||||
}
|
||||
$chartdata['bing_data'] = $bing_data;
|
||||
return $chartdata;
|
||||
}
|
||||
|
||||
}
|
||||
423
app/services/order/store/WriteOffOrderServices.php
Normal file
423
app/services/order/store/WriteOffOrderServices.php
Normal file
@@ -0,0 +1,423 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order\store;
|
||||
|
||||
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\message\service\StoreServiceServices;
|
||||
use app\services\order\StoreOrderCartInfoServices;
|
||||
use app\services\order\StoreOrderCreateServices;
|
||||
use app\services\order\StoreOrderRefundServices;
|
||||
use app\services\order\StoreOrderTakeServices;
|
||||
use app\services\activity\combination\StorePinkServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\store\SystemStoreStaffServices;
|
||||
use app\services\store\DeliveryServiceServices;
|
||||
use app\services\user\UserServices;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 核销订单
|
||||
* Class StoreOrderWriteOffServices
|
||||
* @package app\sservices\order
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class WriteOffOrderServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 验证核销订单权限
|
||||
* @param int $uid
|
||||
* @param array $orderInfo
|
||||
* @param int $auth
|
||||
* @param int $staff_id
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAuth(int $uid, array $orderInfo, int $auth = 1)
|
||||
{
|
||||
if (($auth > 0 && !$uid) || !$orderInfo) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$info = $this->checkUserAuth($uid, $auth);
|
||||
$isAuth = false;
|
||||
switch ($auth) {
|
||||
case 0://平台
|
||||
$isAuth = true;
|
||||
break;
|
||||
case 1://前端客服
|
||||
if (isset($info['user_service']) && $info['user_service']) {
|
||||
$isAuth = true;
|
||||
}
|
||||
break;
|
||||
case 2://配送员
|
||||
if (in_array($orderInfo['shipping_type'], [1, 3]) && $info && $orderInfo['delivery_type'] == 'send' && $orderInfo['delivery_uid'] == $uid) {
|
||||
$isAuth = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$isAuth) {
|
||||
throw new ValidateException('您无权限核销此订单,请联系管理员');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证核销权限
|
||||
* @param int $uid
|
||||
* @param int $auth
|
||||
* @return array|\think\Model
|
||||
*/
|
||||
public function checkUserAuth(int $uid, int $auth = 1)
|
||||
{
|
||||
if ($auth > 0 && !$uid) {
|
||||
throw new ValidateException('用户不存在');
|
||||
}
|
||||
$isAuth = false;
|
||||
$info = [];
|
||||
switch ($auth) {
|
||||
case 0://平台客服
|
||||
$isAuth = true;
|
||||
break;
|
||||
case 1://前端客服
|
||||
/** @var StoreServiceServices $storeService */
|
||||
$storeService = app()->make(StoreServiceServices::class);
|
||||
$userService = $storeService->checkoutIsService(['uid' => $uid, 'status' => 1, 'account_status' => 1, 'customer' => 1]);
|
||||
if ($userService) {
|
||||
$isAuth = true;
|
||||
$info['user_service'] = $userService;
|
||||
}
|
||||
break;
|
||||
case 2://配送员
|
||||
/** @var DeliveryServiceServices $deliverServiceServices */
|
||||
$deliverServiceServices = app()->make(DeliveryServiceServices::class);
|
||||
try {
|
||||
$info = $deliverServiceServices->getDeliveryInfoByUid($uid, 0);
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
}
|
||||
if ($info) {
|
||||
$isAuth = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$isAuth) {
|
||||
throw new ValidateException('您无权限核销,请联系超级管理员');
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户码获取待核销订单列表
|
||||
* @param int $uid
|
||||
* @param string $code
|
||||
* @param int $auth
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function userUnWriteoffOrder(int $uid, string $code, int $auth = 1, array $userInfo = [])
|
||||
{
|
||||
if (!$userInfo) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getOne(['bar_code' => $code]);
|
||||
}
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('该用户不存在');
|
||||
}
|
||||
$info = $this->checkUserAuth($uid, $auth);
|
||||
$where = [];
|
||||
if ($info && $auth > 0) {
|
||||
if ($auth == 1 && isset($info['user_service']) && $info['user_service']) {
|
||||
$where = ['delivery_uid' => 0];
|
||||
} elseif ($auth == 2) {
|
||||
$where = ['delivery_uid' => $info['uid']];
|
||||
}
|
||||
$unWriteoffOrder = $this->dao->getUnWirteOffList(['uid' => $userInfo['uid']] + $where, ['id']);
|
||||
} else {
|
||||
$unWriteoffOrder = $this->dao->getUnWirteOffList(['uid' => $userInfo['uid']], ['id']);
|
||||
}
|
||||
$data = [];
|
||||
if ($unWriteoffOrder) {
|
||||
foreach ($unWriteoffOrder as $item) {
|
||||
try {
|
||||
$orderInfo = $this->writeoffOrderInfo($uid, '', $auth, $item['id']);
|
||||
} catch (\Throwable $e) {//无权限或其他异常不返回订单信息
|
||||
$orderInfo = [];
|
||||
}
|
||||
if ($orderInfo) $data[] = $orderInfo;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取核销订单信息
|
||||
* @param int $uid
|
||||
* @param string $code
|
||||
* @param int $auth
|
||||
* @param int $oid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function writeoffOrderInfo(int $uid, string $code = '', int $auth = 1, int $oid = 0, int $staff_id = 0)
|
||||
{
|
||||
if ($oid) {
|
||||
//订单
|
||||
$orderInfo = $this->dao->getOne(['id' => $oid, 'is_del' => 0], '*', ['user', 'pink']);
|
||||
} else {
|
||||
//订单
|
||||
$orderInfo = $this->dao->getOne(['verify_code' => $code, 'is_del' => 0], '*', ['user', 'pink']);
|
||||
}
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('Write off order does not exist');
|
||||
}
|
||||
if (!$orderInfo['paid']) {
|
||||
throw new ValidateException('订单还未完成支付');
|
||||
}
|
||||
if ($orderInfo['refund_status'] != 0) {
|
||||
throw new ValidateException('该订单状态暂不支持核销');
|
||||
}
|
||||
$orderInfo = $orderInfo->toArray();
|
||||
//验证权限
|
||||
$this->checkAuth($uid, $orderInfo, $auth);
|
||||
/** @var StoreOrderCartInfoServices $cartServices */
|
||||
$cartServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfo = $cartServices->getCartInfoList(['oid' => $orderInfo['id']], ['id', 'oid', 'write_times', 'write_surplus_times', 'write_start', 'write_end']);
|
||||
$orderInfo['write_off'] = $orderInfo['write_times'] = 0;
|
||||
$orderInfo['write_day'] = '';
|
||||
$cart = $cartInfo[0] ?? [];
|
||||
if ($orderInfo['product_type'] == 4 && $cart) {//次卡商品
|
||||
$orderInfo['write_off'] = max(bcsub((string)$cart['write_times'], (string)$cart['write_surplus_times'], 0), 0);
|
||||
$orderInfo['write_times'] = $cart['write_times'] ?? 0;
|
||||
$start = $cart['write_start'] ?? 0;
|
||||
$end = $cart['write_end'] ?? 0;
|
||||
if (!$start && !$end) {
|
||||
$orderInfo['write_day'] = '不限时';
|
||||
} else {
|
||||
$orderInfo['write_day'] = ($start ? date('Y-m-d', $start) : '') . '/' . ($end ? date('Y-m-d', $end) : '');
|
||||
}
|
||||
}
|
||||
return $orderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单商品信息
|
||||
* @param int $uid
|
||||
* @param int $id
|
||||
* @param int $auth
|
||||
* @param int $staff_id
|
||||
* @param bool $isCasher
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOrderCartInfo(int $uid, int $id, int $auth = 1, int $staff_id = 0, bool $isCasher = false)
|
||||
{
|
||||
if ($isCasher) {//获取订单信息 暂时不验证权限
|
||||
$orderInfo = $this->dao->getOne(['id' => $id], '*', ['user', 'pink']);
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('Write off order does not exist');
|
||||
}
|
||||
$orderInfo = $orderInfo->toArray();
|
||||
} else {
|
||||
$orderInfo = $this->writeoffOrderInfo($uid, '', $auth, $id, $staff_id);
|
||||
}
|
||||
$writeoff_count = 0;
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$cartInfo = $cartInfoServices->getCartColunm(['oid' => $orderInfo['id']], 'id,cart_id,cart_num,surplus_num,is_writeoff,cart_info,product_type,is_support_refund,is_gift,write_times,write_surplus_times');
|
||||
foreach ($cartInfo as &$item) {
|
||||
$_info = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
|
||||
if (!isset($_info['productInfo'])) $_info['productInfo'] = [];
|
||||
//缩略图处理
|
||||
if (isset($_info['productInfo']['attrInfo'])) {
|
||||
$_info['productInfo']['attrInfo'] = get_thumb_water($_info['productInfo']['attrInfo']);
|
||||
}
|
||||
$_info['productInfo'] = get_thumb_water($_info['productInfo']);
|
||||
$item['cart_info'] = $_info;
|
||||
if ($item['write_times'] > $item['write_surplus_times']) {
|
||||
$writeoff_count = bcadd((string)$writeoff_count, (string)bcsub((string)$item['write_times'], (string)$item['write_surplus_times']));
|
||||
}
|
||||
$item['surplus_num'] = $item['write_surplus_times'];
|
||||
unset($_info);
|
||||
}
|
||||
$orderInfo['cart_count'] = count($cartInfo);
|
||||
$orderInfo['writeoff_count'] = $writeoff_count;
|
||||
$orderInfo['cart_info'] = $cartInfo;
|
||||
return $orderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销订单
|
||||
* @param int $uid
|
||||
* @param array $orderInfo
|
||||
* @param array $cartIds
|
||||
* @param int $auth
|
||||
* @return array|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function writeoffOrder(int $uid, array $orderInfo, array $cartIds = [], int $auth = 1, int $staff_id = 0, int $admin_id = 0)
|
||||
{
|
||||
if (!$orderInfo) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$time = time();
|
||||
if (!$orderInfo['verify_code'] || ($orderInfo['shipping_type'] != 2 && $orderInfo['delivery_type'] != 'send')) {
|
||||
throw new ValidateException('此订单不能被核销');
|
||||
}
|
||||
/** @var StoreOrderRefundServices $storeOrderRefundServices */
|
||||
$storeOrderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
if ($storeOrderRefundServices->count(['store_order_id' => $orderInfo['id'], 'refund_type' => [1, 2, 4, 5, 6], 'is_cancel' => 0, 'is_del' => 0])) {
|
||||
throw new ValidateException('订单有售后申请请先处理');
|
||||
}
|
||||
if (isset($orderInfo['pinkStatus']) && $orderInfo['pinkStatus'] != 2) {
|
||||
throw new ValidateException('拼团未完成暂不能发货!');
|
||||
}
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
if ($orderInfo['status'] >= 2 && !$cartInfoServices->count(['oid' => $orderInfo['id'], 'is_writeoff' => 0])) {
|
||||
throw new ValidateException('订单已核销');
|
||||
}
|
||||
$store_id = $orderInfo['store_id'];
|
||||
if ($orderInfo['type'] == 3 && $orderInfo['activity_id'] && $orderInfo['pink_id']) {
|
||||
/** @var StorePinkServices $services */
|
||||
$services = app()->make(StorePinkServices::class);
|
||||
$res = $services->getCount([['id', '=', $orderInfo['pink_id']], ['status', '<>', 2]]);
|
||||
if ($res) throw new ValidateException('Failed to write off the group order');
|
||||
}
|
||||
|
||||
$cartInfo = [];
|
||||
if ($cartIds) {//商城存在部分核销
|
||||
$ids = array_unique(array_column($cartIds, 'cart_id'));
|
||||
//订单下原商品信息
|
||||
$cartInfo = $cartInfoServices->getCartColunm(['oid' => $orderInfo['id'], 'cart_id' => $ids, 'is_writeoff' => 0], 'cart_id,cart_num,surplus_num,product_id,write_times,write_surplus_times,write_start,write_end', 'cart_id');
|
||||
if (count($ids) != count($cartInfo)) {
|
||||
throw new ValidateException('订单中有商品已核销');
|
||||
}
|
||||
foreach ($cartIds as $cart) {
|
||||
$info = $cartInfo[$cart['cart_id']] ?? [];
|
||||
if (!$info) {
|
||||
throw new ValidateException('核销商品不存在');
|
||||
}
|
||||
if ($cart['cart_num'] > $info['write_surplus_times']) {
|
||||
throw new ValidateException('核销数量超出剩余总核销次数');
|
||||
}
|
||||
}
|
||||
} else {//整单核销
|
||||
$cartInfo = $cartInfoServices->getCartColunm(['oid' => $orderInfo['id'], 'is_writeoff' => 0], 'id,cart_id,cart_num,surplus_num,product_id,write_times,write_surplus_times,write_start,write_end', 'cart_id');
|
||||
}
|
||||
foreach ($cartInfo as $info) {
|
||||
if ($info['write_start'] && $time < $info['write_start']) {
|
||||
throw new ValidateException('还未到指定核销的开始时间,无法核销');
|
||||
}
|
||||
if ($info['write_end'] && $time > $info['write_end']) {
|
||||
throw new ValidateException('已经超过指定核销的结束时间,无法核销');
|
||||
}
|
||||
}
|
||||
|
||||
$data = ['clerk_id' => $uid];
|
||||
$cartData = ['writeoff_time' => time()];
|
||||
if ($auth == 1) {//前端客服 下面数据暂时记录前端客服uid
|
||||
$data['staff_id'] = $uid ?? 0;
|
||||
$cartData['staff_id'] = $uid ?? 0;
|
||||
} else if ($auth == 2) {//配送员
|
||||
/** @var DeliveryServiceServices $deliverServiceServices */
|
||||
$deliverServiceServices = app()->make(DeliveryServiceServices::class);
|
||||
$deliveryInfo = $deliverServiceServices->getDeliveryInfoByUid($uid, $store_id);
|
||||
$cartData['delivery_id'] = $deliveryInfo['id'] ?? 0;
|
||||
}
|
||||
$data = $this->transaction(function () use ($orderInfo, $staff_id, $data, $cartIds, $cartInfoServices, $cartData, $auth, $cartInfo) {
|
||||
if ($cartIds) {//选择商品、件数核销
|
||||
foreach ($cartIds as $cart) {
|
||||
$write_surplus_num = $cartInfo[$cart['cart_id']]['write_surplus_times'] ?? 0;
|
||||
if (!isset($cartInfo[$cart['cart_id']]) || !$write_surplus_num) continue;
|
||||
if ($cart['cart_num'] >= $write_surplus_num) {//拆分完成
|
||||
$cartData['write_surplus_times'] = 0;
|
||||
$cartData['is_writeoff'] = 1;
|
||||
} else {//拆分部分数量
|
||||
$cartData['write_surplus_times'] = bcsub((string)$write_surplus_num, $cart['cart_num'], 0);
|
||||
$cartData['is_writeoff'] = 0;
|
||||
}
|
||||
//修改原来订单商品信息
|
||||
$cartInfoServices->update(['oid' => $orderInfo['id'], 'cart_id' => $cart['cart_id']], $cartData);
|
||||
}
|
||||
} else {//整单核销
|
||||
//修改原来订单商品信息
|
||||
$cartData['is_writeoff'] = 1;
|
||||
$cartData['write_surplus_times'] = 0;
|
||||
$cartInfoServices->update(['oid' => $orderInfo['id']], $cartData);
|
||||
}
|
||||
if (!$cartInfoServices->count(['oid' => (int)$orderInfo['id'], 'is_writeoff' => 0])) {//全部核销
|
||||
$data['status'] = 2;
|
||||
/** @var StoreOrderTakeServices $storeOrdeTask */
|
||||
$storeOrdeTask = app()->make(StoreOrderTakeServices::class);
|
||||
$re = $storeOrdeTask->storeProductOrderUserTakeDelivery($orderInfo, true, false);
|
||||
if (!$re) {
|
||||
throw new ValidateException('Write off failure');
|
||||
}
|
||||
} else {//部分核销
|
||||
/** @var StoreOrderCreateServices $storeOrderCreateServices */
|
||||
$storeOrderCreateServices = app()->make(StoreOrderCreateServices::class);
|
||||
$data['verify_code'] = $storeOrderCreateServices->getStoreCode();
|
||||
$data['status'] = 5;
|
||||
}
|
||||
if (!$this->dao->update($orderInfo['id'], $data)) {
|
||||
throw new ValidateException('Write off failure');
|
||||
}
|
||||
return $data;
|
||||
});
|
||||
event('order.writeoff', [$orderInfo, $auth, $data, $cartIds, $cartInfo,$admin_id]);
|
||||
return $orderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 次卡商品核销表单
|
||||
* @param int $id
|
||||
* @param int $staffId
|
||||
* @param int $cart_num
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function writeOrderFrom(int $id, int $cart_num = 1)
|
||||
{
|
||||
$orderInfo = $this->getOrderCartInfo(0, (int)$id, 0);
|
||||
$cartInfo = $orderInfo['cart_info'] ?? [];
|
||||
if (!$cartInfo) {
|
||||
throw new ValidateException('核销订单商品信息不存在');
|
||||
}
|
||||
if ($orderInfo['product_type'] != 4) {
|
||||
throw new ValidateException('订单商品不支持此类型核销');
|
||||
}
|
||||
$name = ($cartInfo[0]['write_surplus_times'] ?? 0) . '/' . ($cartInfo[0]['write_times'] ?? 0);
|
||||
$f[] = Form::hidden('cart_id', $cartInfo[0]['cart_id'] ?? 0);
|
||||
$f[] = Form::input('name', '核销数', $name)->disabled(true);
|
||||
$f[] = Form::number('cart_num', '本次核销数量', min(max($cart_num, 1), $cartInfo[0]['write_surplus_times'] ?? 0))->min(1)->max($cartInfo[0]['write_surplus_times'] ?? 1);
|
||||
return create_form('次卡核销', $f, $this->url('/order/write/form/' . $id), 'POST');
|
||||
}
|
||||
|
||||
}
|
||||
308
app/services/order/supplier/SupplierOrderServices.php
Normal file
308
app/services/order/supplier/SupplierOrderServices.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\order\supplier;
|
||||
|
||||
use app\jobs\notice\SocketPushJob;
|
||||
use app\services\order\StoreOrderRefundServices;
|
||||
use think\annotation\Inject;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use crmeb\services\CacheService;
|
||||
use think\exception\ValidateException;
|
||||
use app\services\order\StoreOrderCartInfoServices;
|
||||
|
||||
/**
|
||||
* 供应商订单
|
||||
* Class SupplierOrderServices
|
||||
* @package app\sservices\order\supplier
|
||||
* @mixin StoreOrderDao
|
||||
*/
|
||||
class SupplierOrderServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 支付类型
|
||||
* @var string[]
|
||||
*/
|
||||
public array $pay_type = ['weixin' => '微信支付', 'yue' => '余额支付', 'offline' => '线下支付', 'alipay' => '支付宝支付', 'cash' => '现金支付', 'automatic' => '自动转账', 'store' => '微信支付'];
|
||||
|
||||
/**
|
||||
* @var StoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected StoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* 配货单信息
|
||||
* @param array $id
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getDistribution(array $id): array
|
||||
{
|
||||
$orderList = $this->dao->getList(['id' => $id], ['id', 'order_id', 'trade_no', 'real_name', 'user_phone', 'user_address', 'pay_time', 'pay_type', 'pay_postage as freight_price', 'coupon_price', 'deduction_price', 'use_integral', 'pay_price', 'mark', 'first_order_price', 'channel_price']);
|
||||
if (!$orderList) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
|
||||
/** @var StoreOrderCartInfoServices $services */
|
||||
$cartServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
foreach ($orderList as &$order) {
|
||||
$order['pay_type_name'] = $this->pay_type[$order['pay_type']] ?? '其他方式';
|
||||
$order['pay_time'] = $order['pay_time'] ? date('Y-m-d H:i:s', (int)$order['pay_time']) : '';
|
||||
|
||||
$cartInfos = $cartServices->getCartColunm(['oid' => $order['id']], 'cart_num,is_writeoff,surplus_num,cart_info,refund_num,product_type,is_support_refund,is_gift,promotions_id', 'unique');
|
||||
|
||||
$i = 1;
|
||||
$list = [];
|
||||
|
||||
//核算优惠金额
|
||||
$vipTruePrice = 0;
|
||||
foreach ($cartInfos as $cartInfo) {
|
||||
$cart = json_decode($cartInfo['cart_info'], true);
|
||||
$vipTruePrice = bcadd((string)$vipTruePrice, bcmul($cart['vip_truePrice'], $cart['cart_num'] ?: 1, 2), 2);
|
||||
|
||||
$list[] = [
|
||||
'index' => $i++,
|
||||
'store_name' => $cart['productInfo']['store_name'],
|
||||
'suk' => $cart['productInfo']['attrInfo']['suk'],
|
||||
'bar_code' => $cart['productInfo']['attrInfo']['bar_code'],
|
||||
'code' => $cart['productInfo']['attrInfo']['code'],
|
||||
'truePrice' => sprintf("%.2f", $cart['sum_price']),
|
||||
'cart_num' => $cart['cart_num'],
|
||||
'subtotal' => bcmul((string)$cart['sum_price'], (string)$cart['cart_num'], 2)
|
||||
];
|
||||
}
|
||||
$order['user_address'] = str_replace(' ', '', $order['user_address']);
|
||||
$order['vip_true_price'] = $vipTruePrice;
|
||||
$order['list'] = $list;
|
||||
}
|
||||
|
||||
return $orderList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 供应商首页头部统计
|
||||
* @param int $supplierId
|
||||
* @param array $time
|
||||
* @return array
|
||||
*/
|
||||
public function homeStatics(int $supplierId, array $time): array
|
||||
{
|
||||
$data = [];
|
||||
$where = ['time' => $time, 'supplier_id' => $supplierId];
|
||||
if ($supplierId < 1) {
|
||||
$where['supplier_id'] = -1;
|
||||
}
|
||||
$orderWhere = ['paid' => 1, 'is_system_del' => 0, 'refund_status' => 0];
|
||||
$refundWhere = ['refund_type' => 6];
|
||||
|
||||
// 订单金额
|
||||
$data['pay_price'] = $this->dao->sum($where + $orderWhere, 'pay_price', true);
|
||||
// 订单量
|
||||
$data['pay_count'] = $this->dao->count($where + $orderWhere);
|
||||
/** @var StoreOrderRefundServices $orderRefundServices */
|
||||
$orderRefundServices = app()->make(StoreOrderRefundServices::class);
|
||||
// 退款金额
|
||||
$data['refund_price'] = $orderRefundServices->sum($where + $refundWhere, 'refund_price', true);
|
||||
// 退款订单数
|
||||
$data['refund_count'] = $orderRefundServices->count($where + $refundWhere);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单图表
|
||||
* @param int $supplierId
|
||||
* @param array $time
|
||||
* @return array
|
||||
*/
|
||||
public function orderCharts(int $supplierId, array $time): array
|
||||
{
|
||||
if (is_int($time[0]) && is_int($time[1])) {
|
||||
$dayCount = (strtotime(date('Y-m-d', $time[1])) - strtotime(date('Y-m-d', $time[0]))) / 86400 + 1;
|
||||
} else {
|
||||
$time[0] = strtotime($time[0]);
|
||||
$time[1] = strtotime($time[1]);
|
||||
$dayCount = ($time[1] - $time[0]) / 86400 + 1;
|
||||
}
|
||||
if ($dayCount == 1) {
|
||||
$num = 0;
|
||||
} elseif ($dayCount > 1 && $dayCount <= 31) {
|
||||
$num = 1;
|
||||
} elseif ($dayCount > 31 && $dayCount <= 92) {
|
||||
$num = 3;
|
||||
} elseif ($dayCount > 92) {
|
||||
$num = 30;
|
||||
}
|
||||
|
||||
if ($supplierId) {
|
||||
$where = ['supplier_id' => $supplierId];
|
||||
} else {
|
||||
$where = [['supplier_id', '>', 0]];
|
||||
}
|
||||
|
||||
$data = $xAxis = $series = [];
|
||||
if ($num == 0) {
|
||||
$xAxis = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
|
||||
$timeType = '%H';
|
||||
} elseif ($num != 0) {
|
||||
$dt_start = $time[0];
|
||||
$dt_end = $time[1];
|
||||
while ($dt_start <= $dt_end) {
|
||||
if ($num == 30) {
|
||||
$xAxis[] = date('Y-m', $dt_start);
|
||||
$dt_start = strtotime("+1 month", $dt_start);
|
||||
$timeType = '%Y-%m';
|
||||
} else {
|
||||
$xAxis[] = date('m-d', $dt_start);
|
||||
$dt_start = strtotime("+$num day", $dt_start);
|
||||
$timeType = '%m-%d';
|
||||
}
|
||||
}
|
||||
}
|
||||
$pay_price = array_column($this->dao->getOrderStatistics($where, $time, $timeType, 'add_time', 'sum(pay_price)', 'pay'), 'num', 'days');
|
||||
$pay_count = array_column($this->dao->getOrderStatistics($where, $time, $timeType, 'add_time', 'count(id)', 'pay'), 'num', 'days');
|
||||
$refund_price = array_column($this->dao->getOrderStatistics($where, $time, $timeType, 'add_time', 'sum(refund_price)', 'refund'), 'num', 'days');
|
||||
$refund_count = array_column($this->dao->getOrderStatistics($where, $time, $timeType, 'add_time', 'count(id)', 'refund'), 'num', 'days');
|
||||
|
||||
foreach ($xAxis as $item) {
|
||||
$data['订单金额'][] = isset($pay_price[$item]) ? floatval($pay_price[$item]) : 0;
|
||||
$data['订单量'][] = isset($pay_count[$item]) ? floatval($pay_count[$item]) : 0;
|
||||
$data['退款金额'][] = isset($refund_price[$item]) ? floatval($refund_price[$item]) : 0;
|
||||
$data['退款订单量'][] = isset($refund_count[$item]) ? floatval($refund_count[$item]) : 0;
|
||||
}
|
||||
foreach ($data as $key => $item) {
|
||||
$series[] = [
|
||||
'name' => $key,
|
||||
'data' => $item,
|
||||
'type' => 'line',
|
||||
];
|
||||
}
|
||||
return compact('xAxis', 'series');
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单来源
|
||||
* @param int $supplierId
|
||||
* @param array string
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderChannel(int $supplierId, array $time): array
|
||||
{
|
||||
$bing_xdata = ['公众号', '小程序', 'H5', 'PC', 'APP'];
|
||||
$color = ['#6DD230', '#FFAB2B', '#4BCAD5', '#1890FF', '#B37FEB'];
|
||||
$bing_data = [];
|
||||
if ($supplierId) {
|
||||
$where = ['supplier_id' => $supplierId];
|
||||
} else {
|
||||
$where = ['supplier_id' => -1];
|
||||
}
|
||||
|
||||
foreach ($bing_xdata as $key => $item) {
|
||||
$bing_data[] = [
|
||||
'name' => $item,
|
||||
'value' => $this->dao->count(['paid' => 1, 'pid' => 0, 'is_channel' => $key, 'time' => $time] + $where),
|
||||
'itemStyle' => ['color' => $color[$key]]
|
||||
];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$count = array_sum(array_column($bing_data, 'value'));
|
||||
foreach ($bing_data as $item) {
|
||||
$list[] = [
|
||||
'name' => $item['name'],
|
||||
'value' => $item['value'],
|
||||
'percent' => $count != 0 ? floatval(bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2)) : 0,
|
||||
];
|
||||
}
|
||||
array_multisort(array_column($list, 'value'), SORT_DESC, $list);
|
||||
return compact('bing_xdata', 'bing_data', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单类型
|
||||
* @param int $supplierId
|
||||
* @param array string
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderType(int $supplierId, array $time): array
|
||||
{
|
||||
$bing_xdata = [0 => '普通订单', 1 => '秒杀订单', 2 => '砍价订单', 3 => '拼团订单', 4 => '积分订单', 5 => '套餐订单', 6 => '预售订单', 7 => '新人专享', 8 => '抽奖订单'];
|
||||
$color = ['#64a1f4', '#3edeb5', '#70869f', '#ffc653', '#ffc653', '#fc7d6a', '#fc7d2a', '#ffc653', '#ffc653'];
|
||||
$bing_data = [];
|
||||
|
||||
if ($supplierId) {
|
||||
$where = ['supplier_id' => $supplierId];
|
||||
} else {
|
||||
$where = ['supplier_id' => -1];
|
||||
}
|
||||
foreach ($bing_xdata as $key => $item) {
|
||||
if (empty($item)) continue;
|
||||
$bing_data[] = [
|
||||
'name' => $item,
|
||||
'value' => $this->dao->together(['paid' => 1, 'pid' => 0, 'type' => $key, 'time' => $time] + $where, 'pay_price', 'sum'),
|
||||
'itemStyle' => ['color' => $color[$key]]
|
||||
];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$count = array_sum(array_column($bing_data, 'value'));
|
||||
foreach ($bing_data as $item) {
|
||||
$list[] = [
|
||||
'name' => $item['name'],
|
||||
'value' => $item['value'],
|
||||
'percent' => $count != 0 ? floatval(bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2)) : 0,
|
||||
];
|
||||
}
|
||||
unset($bing_xdata[4]);
|
||||
$bing_xdata = array_values($bing_xdata);
|
||||
array_multisort(array_column($list, 'value'), SORT_DESC, $list);
|
||||
return compact('bing_xdata', 'bing_data', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 提醒发货
|
||||
* @param int $supplierId
|
||||
* @param int $id
|
||||
* @return bool
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function deliverRemind(int $supplierId, int $id)
|
||||
{
|
||||
$order = $this->dao->get($id);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单不存在');
|
||||
}
|
||||
$expire = 600;
|
||||
$val = time() + $expire;
|
||||
$order = $order->toArray();
|
||||
|
||||
$cacheName = 'order_deliver_remind_' . $id;
|
||||
if (CacheService::has($cacheName)) {
|
||||
$interval = CacheService::get($cacheName);
|
||||
$remain = $interval - time();
|
||||
if ($remain > 0) {
|
||||
throw new ValidateException('请' . ceil($remain / 60) . '分钟后再次提醒');
|
||||
}
|
||||
CacheService::delete($cacheName);
|
||||
} else {
|
||||
CacheService::set($cacheName, $val, $expire);
|
||||
}
|
||||
|
||||
//向供应商后台发送待发货订单消息
|
||||
SocketPushJob::dispatch([$supplierId, 'WAIT_DELIVER_ORDER', ['order_id' => $order['order_id']], 'supplier']);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user