You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yanzong/app/api/model/Order.php

651 lines
24 KiB

12 months ago
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\api\model;
use app\api\model\{Goods as GoodsModel, OrderRefund as OrderRefundModel, Setting as SettingModel, user\UserCoupon};
9 months ago
use app\api\model\order\Delivery as DeliveryModel;
10 months ago
use app\api\service\{order\source\Factory as OrderSourceFactory, User as UserService};
use app\api\service\Store as StoreService;
use app\common\enum\{order\DeliveryStatus as DeliveryStatusEnum,
12 months ago
order\DeliveryType as DeliveryTypeEnum,
10 months ago
order\OrderStatus as OrderStatusEnum,
order\PayStatus as PayStatusEnum,
12 months ago
order\ReceiptStatus as ReceiptStatusEnum,
10 months ago
OrderType,
RecoveryStatusEnum,
Setting as SettingEnum};
12 months ago
use app\common\library\helper;
10 months ago
use app\common\model\Order as OrderModel;
use app\common\model\TransferRecord;
use app\common\service\{Order as OrderService, order\Complete as OrderCompleteService};
12 months ago
use cores\exception\BaseException;
10 months ago
12 months ago
/**
* 订单模型
* Class Order
* @package app\api\model
*/
class Order extends OrderModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'merchant_remark',
'transaction_id',
'order_source_data',
'is_settled',
'is_delete',
'update_time'
];
// 信息提示
private string $message = '';
/**
* 待支付订单详情
* @param string $orderNo 订单号
* @return null|static
*/
public static function getPayDetail(string $orderNo): ?Order
{
$where = ['order_no' => $orderNo, 'is_delete' => 0];
return self::detail($where, ['goods', 'user']);
}
/**
* 立即购买:获取订单商品列表
* @param int $goodsId 商品ID
* @param string $goodsSkuId 商品SKU
* @param int $goodsNum 购买数量
* @return mixed
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderGoodsListByNow(int $goodsId, string $goodsSkuId, int $goodsNum)
{
// 获取商品列表
$model = new GoodsModel;
$goodsList = $model->setEnableGradeMoney(false)->getListByIdsFromApi([$goodsId]);
8 months ago
12 months ago
if ($goodsList->isEmpty()) {
throwError('未找到商品信息');
}
8 months ago
// echo "<pre>";
// print_r($goodsList->toArray());
// exit();
12 months ago
// 隐藏冗余的属性
$goodsList->hidden(GoodsModel::getHidden(['content', 'goods_images', 'images']));
foreach ($goodsList as &$item) {
// 商品sku信息
$item['skuInfo'] = GoodsModel::getSkuInfo($item, $goodsSkuId, false);
// 商品封面 (优先sku封面)
$item['goods_image'] = $item['skuInfo']['goods_image'] ?: $item['goods_image'];
10 months ago
12 months ago
// 商品单价
8 months ago
$item['goods_price'] = $item['skuInfo']['goods_price'];//\app\api\service\Goods::getGoodsPrice($item['goods_id'], $item['skuInfo']['goods_price'], $item['skuInfo']['cost_price']);
12 months ago
// 商品购买数量
$item['total_num'] = $goodsNum;
// 商品SKU索引
$item['goods_sku_id'] = $item['skuInfo']['goods_sku_id'];
// 商品购买总金额
$item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
}
8 months ago
// echo "<pre>";
// print_r($goodsList->toArray());
// exit();
12 months ago
return $goodsList;
}
/**
* 获取用户订单列表
* @param string $dataType 订单类型 (all全部 payment待付款 deliver待发货 received待收货 comment待评价)
* @return \think\Paginator
* @throws BaseException
* @throws \think\db\exception\DbException
*/
11 months ago
public function getList(string $dataType = 'all')
12 months ago
{
// 设置订单类型条件
$dataTypeFilter = $this->getFilterDataType($dataType);
9 months ago
//判断当前用户身份
9 months ago
$userId = UserService::getCurrentLoginUserId();
9 months ago
$where = [];
if (!UserService::isStore()) {
9 months ago
$where['user_id'] = $userId;
9 months ago
}
12 months ago
// 当前用户ID
$query = $this->with(['goods.image']);
$query->where($dataTypeFilter)
9 months ago
->where($where)
12 months ago
->where('is_delete', '=', 0)
11 months ago
->order(['create_time' => 'desc']);
10 months ago
$list = $query->paginate(15)->toArray();
10 months ago
//这边后面改成多商户的话需要根据storeid去获取信息
$service = new StoreService;
10 months ago
$info = $service->data();
10 months ago
if (!empty($info['storeInfo'])) {
$info = $info['storeInfo']->toArray();
foreach ($list['data'] as &$v) {
$v['storeInfo'] = $info;
$total_num = 0;
foreach ($v['goods'] as $value) {
$total_num += $value['total_num'] ?? 0;
}
$v['total_num'] = $total_num;
9 months ago
$v['delivery'] = DeliveryModel::where('order_id', $v['order_id'])->find();
10 months ago
}
}
return $list;
11 months ago
}
/**
* 删除订单
* @return bool|mixed
*/
public function del()
{
$userId = UserService::getCurrentLoginUserId();
$res = Order::where([
'user_id' => $userId,
'order_id' => $_GET['order_id'],
])->update(['is_delete' => 1]);
return $res;
12 months ago
}
11 months ago
public function orderfast()
11 months ago
{
//催货 这边暂时没有逻辑
10 months ago
return true;
11 months ago
}
12 months ago
/**
* 取消订单
* @return bool|mixed
*/
public function cancel()
{
// 判断订单是否允许取消
$orderSource = OrderSourceFactory::getFactory($this['order_source']);
if (!$orderSource->checkOrderByCancel($this)) {
$this->error = $orderSource->getError();
return false;
}
//订单已取消提示
if ($this['order_status'] == OrderStatusEnum::CANCELLED) {
$this->error = '订单已取消成功,无需重复操作';
return false;
}
if ($this['order_status'] == OrderStatusEnum::APPLY_CANCEL) {
$this->error = '订单已申请取消,需等待后台审核';
return false;
}
12 months ago
// 订单是否已支付
$isPay = $this['pay_status'] == PayStatusEnum::SUCCESS;
// 提示信息
$this->message = $isPay ? '订单已申请取消,需等待后台审核' : '订单已取消成功';
// 订单取消事件
return $this->transaction(function () use ($isPay) {
// 订单取消事件
!$isPay && OrderService::cancelEvent($this);
// 更新订单状态: 已付款的订单设置为"待取消", 等待后台审核
return $this->save(['order_status' => $isPay ? OrderStatusEnum::APPLY_CANCEL : OrderStatusEnum::CANCELLED]);
});
}
/**
* 确认收货
* @return bool|mixed
*/
public function receipt()
{
// 验证订单是否合法
// 条件1: 订单必须已发货
// 条件2: 订单必须未收货
if (
$this['delivery_status'] != DeliveryStatusEnum::DELIVERED
|| $this['receipt_status'] != ReceiptStatusEnum::NOT_RECEIVED
) {
$this->error = '该订单不合法';
return false;
}
return $this->transaction(function () {
// 更新订单状态
$status = $this->save([
'receipt_status' => ReceiptStatusEnum::RECEIVED,
'receipt_time' => time(),
'order_status' => OrderStatusEnum::COMPLETED
]);
// 执行订单完成后的操作
$OrderCompleteService = new OrderCompleteService();
$OrderCompleteService->complete([$this], static::$storeId);
return $status;
});
}
/**
* 获取当前用户订单数量
* @param string $dataType 订单类型 (all全部 payment待付款 deliver待发货 received待收货 comment待评价)
* @return int
* @throws BaseException
*/
public function getCount(string $dataType = 'all', $dealer_order_ids = []): int
12 months ago
{
// 设置订单类型条件
$dataTypeFilter = $this->getFilterDataType($dataType);
// 当前用户ID
$userId = UserService::getCurrentLoginUserId();
// 查询数据
$query = $this;
// 非店长不带入user_id查询
10 months ago
if (!UserService::isStore()) {
$query = $this->where('user_id', '=', $userId);
}
if ($dealer_order_ids) {
$query->whereIn('order_id', $dealer_order_ids);
}
return $query->where('order_status', '<>', 20)
12 months ago
->where($dataTypeFilter)
->where('is_delete', '=', 0)
->count();
}
10 months ago
12 months ago
/**
* 设置订单类型条件
* @param string $dataType
* @return array
*/
private function getFilterDataType(string $dataType): array
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($dataType) {
case 'all':
break;
10 months ago
case 'pay':
11 months ago
case 'payment':
$filter[] = ['pay_status', '=', PayStatusEnum::PENDING];
$filter[] = ['order_status', '=', OrderStatusEnum::NORMAL];
break;
11 months ago
//待付款
//待发货
12 months ago
case 'delivery':
$filter = [
['pay_status', '=', PayStatusEnum::SUCCESS],
['delivery_status', '<>', DeliveryStatusEnum::DELIVERED],
['order_status', 'in', [OrderStatusEnum::NORMAL]],
// ['order_status', 'in', [OrderStatusEnum::NORMAL, OrderStatusEnum::APPLY_CANCEL]]
12 months ago
];
break;
11 months ago
//待收货
10 months ago
case 'received':
11 months ago
case 'receipt':
12 months ago
$filter = [
['pay_status', '=', PayStatusEnum::SUCCESS],
['delivery_status', '=', DeliveryStatusEnum::DELIVERED],
['receipt_status', '=', ReceiptStatusEnum::NOT_RECEIVED],
['order_status', '=', OrderStatusEnum::NORMAL]
];
break;
//待收货
11 months ago
//已完成
case 'complete':
$filter = [
['order_status', '=', OrderStatusEnum::COMPLETED]
];
break;
//待取消
case 'apply_cancel':
$filter = [
['order_status', '=', OrderStatusEnum::APPLY_CANCEL]
];
break;
//已取消
case 'cancel':
$filter = [
['order_status', '=', OrderStatusEnum::CANCELLED]
];
12 months ago
break;
//已评价
12 months ago
case 'comment':
$filter = [
['is_comment', '=', 0],
['order_status', '=', OrderStatusEnum::COMPLETED]
];
break;
}
10 months ago
//非售后订单
$filter[] = ['is_refund', '=', 10];
12 months ago
return $filter;
}
/**
* 设置订单类型条件(list查询用)
* @param string $dataType
* @return array
*/
private function getFilterDataTypeList(string $dataType): array
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($dataType) {
case 'all':
break;
case 'payment':
$filter[] = ['a.pay_status', '=', PayStatusEnum::PENDING];
$filter[] = ['a.order_status', '=', OrderStatusEnum::NORMAL];
break;
//待付款
case 'pay':
$filter[] = ['a.pay_status', '=', PayStatusEnum::PENDING];
$filter[] = ['a.order_status', '=', OrderStatusEnum::NORMAL];
10 months ago
break;
//待发货
case 'delivery':
$filter = [
['a.pay_status', '=', PayStatusEnum::SUCCESS],
['a.delivery_status', '<>', DeliveryStatusEnum::DELIVERED],
['a.order_status', 'in', [OrderStatusEnum::NORMAL, OrderStatusEnum::APPLY_CANCEL]]
];
10 months ago
break;
//待收货
case 'receipt':
$filter = [
['a.pay_status', '=', PayStatusEnum::SUCCESS],
['a.delivery_status', '=', DeliveryStatusEnum::DELIVERED],
['a.receipt_status', '=', ReceiptStatusEnum::NOT_RECEIVED],
['a.order_status', '=', OrderStatusEnum::NORMAL]
];
10 months ago
break;
//待收货
case 'received':
$filter = [
['a.pay_status', '=', PayStatusEnum::SUCCESS],
['a.delivery_status', '=', DeliveryStatusEnum::DELIVERED],
['a.receipt_status', '=', ReceiptStatusEnum::NOT_RECEIVED],
['a.order_status', '=', OrderStatusEnum::NORMAL]
];
break;
//已完成
case 'complete':
$filter = [
['a.order_status', '=', OrderStatusEnum::COMPLETED]
];
break;
//待取消
case 'apply_cancel':
$filter = [
['a.order_status', '=', OrderStatusEnum::APPLY_CANCEL]
];
break;
//已取消
case 'cancel':
$filter = [
['a.order_status', '=', OrderStatusEnum::CANCELLED]
];
break;
//已评价
case 'comment':
$filter = [
['a.is_comment', '=', 0],
['a.order_status', '=', OrderStatusEnum::COMPLETED]
];
break;
}
return $filter;
}
12 months ago
/**
* 获取用户订单详情(含关联数据)
* @param int $orderId 订单ID
* @param bool $onlyCurrentUser 只查询当前登录用户的记录
* @return Order|array|null
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function getUserOrderDetail(int $orderId, bool $onlyCurrentUser = true)
{
// 查询订单记录
// $with = ['goods' => ['image', 'goods', 'refund'], 'extract_shop', 'delivery.express'];
$with = ['goods' => ['image', 'refund'], 'extract_shop', 'delivery.express'];
$order = static::getDetail($orderId, $with, $onlyCurrentUser);
9 months ago
12 months ago
// 附加数据
static::related($order, ['address']);
// 该订单是否允许申请售后
$order['isAllowRefund'] = static::isAllowRefund($order);
return $order;
}
/**
* 获取未支付的订单详情(用于订单支付)
* @param int $orderId 订单ID
* @return array
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function getUnpaidOrderDetail(int $orderId): array
{
// 获取订单详情
$orderInfo = static::getDetail($orderId);
// 验证订单状态
if ($orderInfo['order_status'] != OrderStatusEnum::NORMAL) {
throwError('当前订单状态不允许支付');
}
// 未支付订单的过期时间
$orderCloseTime = SettingModel::getOrderCloseTime() * 60 * 60;
// 订单超时截止时间
$expirationTime = $orderInfo->getData('create_time') + $orderCloseTime;
if ($orderCloseTime > 0 && $expirationTime <= time()) {
throwError('当前订单支付已超时,请重新下单');
}
// 仅返回需要的数据
return [
'orderId' => $orderInfo['order_id'],
'order_no' => $orderInfo['order_no'],
'pay_price' => $orderInfo['pay_price'],
'pay_status' => $orderInfo['pay_status'],
'order_status' => $orderInfo['order_status'],
'create_time' => $orderInfo['create_time'],
7 months ago
'store_id' => $orderInfo['store_id'],
'merchant_id' => $orderInfo['merchant_id'],
12 months ago
'showExpiration' => $orderCloseTime > 0,
'expirationTime' => format_time($expirationTime),
];
}
/**
* 获取用户订单详情(仅订单记录)
* @param int $orderId
* @param array $with
* @param bool $onlyCurrentUser 只查询当前登录用户的记录
* @return Order|array|null
* @throws BaseException
*/
public static function getDetail(int $orderId, array $with = [], bool $onlyCurrentUser = true)
{
// 查询条件
$where = ['order_id' => $orderId];
10 months ago
//$onlyCurrentUser && $where['user_id'] = UserService::getCurrentLoginUserId();
12 months ago
// 查询订单记录
$order = static::detail($where, $with);
empty($order) && throwError('订单不存在');
11 months ago
//这边后面改成多商户的话需要根据storeid去获取信息
$service = new StoreService;
10 months ago
$info = $service->data();
10 months ago
if (!empty($info['storeInfo'])) {
$order->storeInfo = $info['storeInfo']->toArray();
}
$total_num = 0;
7 months ago
if (isset($order->goods) && $order->goods) {
foreach ($order->goods as $value) {
$total_num += $value->total_num ?? 0;
}
}
7 months ago
$order->total_num = $total_num;
12 months ago
return $order;
}
/**
* 判断当前订单是否允许核销
* @param static $order
* @return bool
*/
public function checkExtractOrder(self $order): bool
{
if (
$order['pay_status'] == PayStatusEnum::SUCCESS
&& $order['delivery_type'] == DeliveryTypeEnum::EXTRACT
&& $order['delivery_status'] == DeliveryStatusEnum::NOT_DELIVERED
) {
return true;
}
$this->setError('很抱歉,该订单不能被核销');
return false;
}
/**
* 获取当前用户待处理的订单数量
* @return array
* @throws BaseException
*/
10 months ago
public function getTodoCounts($order_type): array
12 months ago
{
10 months ago
if ($order_type == OrderType::ORDER) {//商城
return [
'payment_number' => $this->getCount('payment'), // 待付款的订单
'delivery_number' => $this->getCount('delivery'), // 待发货的订单
'received_number' => $this->getCount('received'), // 待收货的订单
'finish_number' => $this->getCount('complete'), // 已完成
];
10 months ago
} elseif ($order_type == OrderType::SERVER) {//服务
$model = new Server\ServerOrder();
return [
'confirm_number' => $model->getCount('confirm'), // 待确认的订单
'service_number' => $model->getCount('service'), // 待发货的订单
'payment_number' => $model->getCount('payment'), // 待收货的订单
'check_number' => $model->getCount('complete'), // 已完成的订单
];
10 months ago
} elseif ($order_type == OrderType::RECOVERY) {
10 months ago
$model = new RecoveryOrder();
return [
'accepted_number' => $model->getCount(RecoveryStatusEnum::ACCEPTED), // 待确认的订单
'already_number' => $model->getCount(RecoveryStatusEnum::ALREADY), // 待发货的订单
'cancel_number' => $model->getCount(RecoveryStatusEnum::CANCEL), // 已取消的订单
'finish_number' => $model->getCount(RecoveryStatusEnum::FINISN), // 已完成的订单
];
10 months ago
} elseif ($order_type == OrderType::DEALER) {//分销
$model = new dealer\Order();
$dealer_order_ids = $model->where('user_id', UserService::getCurrentLoginUserId())->column('order_id');
return [
'payment_number' => $this->getCount('payment', $dealer_order_ids), // 待付款的订单
'delivery_number' => $this->getCount('delivery', $dealer_order_ids), // 待发货的订单
'received_number' => $this->getCount('received', $dealer_order_ids), // 待收货的订单
'finish_number' => $this->getCount('complete', $dealer_order_ids), // 已完成的订单
'refund_number' => OrderRefundModel::getCountByUnderway($dealer_order_ids), // 进行中的售后单
];
}
return [];
12 months ago
}
// 返回提示信息
public function getMessage(): string
{
return $this->message;
}
/**
* 当前订单是否允许申请售后
* @param Order $order
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private static function isAllowRefund(self $order): bool
{
// 不能是未发货的订单
if ($order['delivery_status'] == DeliveryStatusEnum::NOT_DELIVERED) {
return false;
}
// 允许申请售后期限(天)
$refundDays = SettingModel::getItem(SettingEnum::TRADE)['order']['refund_days'];
// 不允许售后
if ($refundDays == 0) {
return false;
}
// 当前时间超出允许申请售后期限
if (
$order['receipt_status'] == ReceiptStatusEnum::RECEIVED
&& time() > ($order->getData('receipt_time') + ((int)$refundDays * 86400))
) {
return false;
}
return true;
}
/**
* 更新订单来源记录ID
* @param int $orderId
* @param int $soureId
* @return bool
*/
public static function updateOrderSourceId(int $orderId, int $soureId): bool
{
return static::updateOne(['order_source_id' => $soureId], $orderId);
}
/**
* 获取当前用户行为数量
* @return array
* @throws BaseException
*/
public function getActionCounts(): array
{
$userId = UserService::getCurrentLoginUserId();
return [
10 months ago
'reservation_number' => PreSaleLog::where('user_id', $userId)->count(), // 上门预约待服务订单总数
'view_number' => GoodsBrowseLog::getCount(), // 浏览记录
'send_number' => TransferRecord::getCount(), // 发货数量
'integral_number' => User::get($userId)->points, // 积分数量
'coupon_number' => UserCoupon::getCount(), // 优惠券
'goods_collect_number' => 0, // 商品采集数量
'cart_number' => Cart::getCount(), // 购物车数量
10 months ago
'take_goods_number' => OrderModel::where('user_id', $userId)->where('delivery_type', 20)->count(), // 发货记录&提货记录
];
}
10 months ago
public function getZitiAddressAttr($value)
{
if (!empty($value)) return json_decode($value, true);
return $value;
}
12 months ago
}