<?php
|
|
namespace app\common\model\order;
|
|
use app\common\enum\order\OrderSourceEnum;
|
use app\common\enum\supplier\SupplierType;
|
use app\common\exception\BaseException;
|
use app\common\library\easywechat\AppWx;
|
use app\common\library\easywechat\wx\WxOrder;
|
use app\common\model\BaseModel;
|
use app\common\enum\settings\DeliveryTypeEnum;
|
use app\common\enum\order\OrderPayStatusEnum;
|
use app\common\enum\order\OrderTypeEnum;
|
use app\common\enum\order\OrderPayTypeEnum;
|
use app\common\library\helper;
|
use app\common\model\settings\Express as ExpressModel;
|
use app\common\model\settings\Setting as SettingModel;
|
use app\common\service\order\OrderService;
|
use app\common\service\order\OrderCompleteService;
|
use app\common\model\store\Order as StoreOrderModel;
|
use app\common\service\order\OrderRefundService;
|
use app\common\service\product\factory\ProductFactory;
|
use app\common\model\plus\coupon\UserCoupon as UserCouponModel;
|
use app\common\model\user\User as UserModel;
|
use app\common\service\message\MessageService;
|
use app\shop\model\user\BalanceOrder as BalanceOrderModel;
|
use app\shop\model\user\CardRecord as CardRecordModel;
|
use app\supplier\model\store\Clerk as ClerkModel;
|
use app\supplier\model\store\Store as StoreModel;
|
use app\supplier\model\supplier\Supplier as SupplierModel;
|
use app\common\model\order\OrderSettled as OrderSettledModel;
|
use app\common\model\supplier\Capital as SupplierCapitalModel;
|
use app\common\model\app\AppWx as AppWxModel; //by lyzflash 2024.01.25
|
|
/**
|
* 订单模型模型
|
*/
|
class Order extends BaseModel
|
{
|
protected $pk = 'order_id';
|
protected $name = 'order';
|
|
/**
|
* 追加字段
|
* @var string[]
|
*/
|
protected $append = [
|
'state_text',
|
'order_source_text',
|
'pay_end_time_text',
|
];
|
/**
|
* 关联预售定金订单
|
* @return \think\model\relation\HasOne
|
*/
|
public function advance()
|
{
|
return $this->hasOne('app\\common\\model\\order\\OrderAdvance', 'order_id', 'order_id');
|
}
|
|
/**
|
* 订单商品列表
|
*/
|
public function product()
|
{
|
return $this->hasMany('app\\common\\model\\order\\OrderProduct', 'order_id', 'order_id')->hidden(['content']);
|
}
|
|
|
/**
|
* 关联订单收货地址表
|
*/
|
public function address()
|
{
|
return $this->hasOne('app\\common\\model\\order\\OrderAddress');
|
}
|
|
/**
|
* 关联自提订单联系方式
|
*/
|
public function extract()
|
{
|
return $this->hasOne('app\\common\\model\\order\\OrderExtract');
|
}
|
|
/**
|
* 关联物流公司表
|
*/
|
public function express()
|
{
|
return $this->belongsTo('app\\common\\model\\settings\\Express', 'express_id', 'express_id');
|
}
|
|
/**
|
* 关联自提门店表
|
*/
|
public function extractStore()
|
{
|
return $this->belongsTo('app\\common\\model\\store\\Store', 'extract_store_id', 'store_id');
|
}
|
|
/**
|
* 关联门店店员表
|
*/
|
public function extractClerk()
|
{
|
return $this->belongsTo('app\\common\\model\\store\\Clerk', 'extract_clerk_id');
|
}
|
|
/**
|
* 关联用户表
|
*/
|
public function user()
|
{
|
return $this->belongsTo('app\\common\\model\\user\\User', 'user_id', 'user_id');
|
}
|
|
/**
|
* 关联用户表
|
*/
|
public function room()
|
{
|
return $this->belongsTo('app\\common\\model\\plus\\live\\Room', 'room_id', 'room_id');
|
}
|
|
/**
|
* 关联供应商表
|
*/
|
public function supplier()
|
{
|
return $this->belongsTo('app\\common\\model\\supplier\\Supplier', 'shop_supplier_id', 'shop_supplier_id')->field(['shop_supplier_id', 'name', 'user_id', 'referee_id','supplier_type','gift_type']);
|
}
|
|
/**
|
* 预售结束时间
|
*/
|
public function getPayEndTimeTextAttr($value, $data)
|
{
|
return (isset($data['pay_end_time']) && $data['pay_end_time'] && is_numeric($data['pay_end_time'])) ? date('Y-m-d H:i:s', $data['pay_end_time']) : '';
|
}
|
|
/**
|
* 关联虚拟商品核销信息
|
* @return \think\model\relation\HasOne
|
*/
|
public function verify()
|
{
|
return $this->hasOne('app\\common\\model\\order\\OrderVerify');
|
}
|
|
/**
|
* 订单状态文字描述
|
* @param $value
|
* @param $data
|
* @return string
|
*/
|
public function getStateTextAttr($value, $data)
|
{
|
// 订单状态
|
if (in_array($data['order_status'], [20, 30])) {
|
$orderStatus = [20 => '已取消', 30 => '已完成'];
|
return $orderStatus[$data['order_status']];
|
}
|
// 付款状态
|
if ($data['pay_status'] == 10) {
|
return '待付款';
|
}
|
// 拼团状态
|
if ($data['order_source'] == OrderSourceEnum::ASSEMBLE) {
|
$assemble_status = $this->getAssembleStatus($data);
|
if ($assemble_status != '') {
|
return $assemble_status;
|
}
|
}
|
// 发货状态
|
if ($data['delivery_status'] == 10) {
|
return '已付款,待发货';
|
}
|
if ($data['receipt_status'] == 10) {
|
return '已发货,待收货';
|
}
|
return $value;
|
}
|
|
/**
|
* 拼团订单状态
|
*/
|
private function getAssembleStatus($data)
|
{
|
// 发货状态
|
if ($data['assemble_status'] == 10) {
|
return '已付款,未成团';
|
}
|
if ($data['assemble_status'] == 20 && $data['delivery_status'] == 10) {
|
return '拼团成功,待发货';
|
}
|
if ($data['assemble_status'] == 30) {
|
return '拼团失败';
|
}
|
return '';
|
}
|
|
/**
|
* 付款状态
|
* @param $value
|
* @return array
|
*/
|
public function getPayTypeAttr($value)
|
{
|
return ['text' => OrderPayTypeEnum::data()[$value]['name'], 'value' => $value];
|
}
|
|
/**
|
* 订单来源
|
* @param $value
|
* @return array
|
*/
|
public function getOrderSourceTextAttr($value, $data)
|
{
|
return OrderSourceEnum::data()[$data['order_source']]['name'];
|
}
|
|
/**
|
* 付款状态
|
* @param $value
|
* @return array
|
*/
|
public function getPayStatusAttr($value)
|
{
|
return ['text' => OrderPayStatusEnum::data()[$value]['name'], 'value' => $value];
|
}
|
|
/**
|
* 改价金额(差价)
|
* @param $value
|
* @return array
|
*/
|
public function getUpdatePriceAttr($value)
|
{
|
return [
|
'symbol' => $value < 0 ? '-' : '+',
|
'value' => sprintf('%.2f', abs($value))
|
];
|
}
|
|
/**
|
* 发货状态
|
* @param $value
|
* @return array
|
*/
|
public function getDeliveryStatusAttr($value)
|
{
|
$status = [10 => '待发货', 20 => '已发货'];
|
return ['text' => $status[$value], 'value' => $value];
|
}
|
|
/**
|
* 收货状态
|
* @param $value
|
* @return array
|
*/
|
public function getReceiptStatusAttr($value)
|
{
|
$status = [10 => '待收货', 20 => '已收货'];
|
return ['text' => $status[$value], 'value' => $value];
|
}
|
|
/**
|
* 收货状态
|
* @param $value
|
* @return array
|
*/
|
public function getOrderStatusAttr($value)
|
{
|
$status = [10 => '进行中', 20 => '已取消', 21 => '待取消', 30 => '已完成'];
|
return ['text' => $status[$value], 'value' => $value];
|
}
|
|
/**
|
* 配送方式
|
* @param $value
|
* @return array
|
*/
|
public function getDeliveryTypeAttr($value)
|
{
|
return ['text' => DeliveryTypeEnum::data()[$value]['name'], 'value' => $value];
|
}
|
|
/**
|
* 订单详情
|
* @param $where
|
* @param string[] $with
|
* @return array|\think\Model|null
|
* @throws \think\db\exception\DataNotFoundException
|
* @throws \think\db\exception\DbException
|
* @throws \think\db\exception\ModelNotFoundException
|
*/
|
public static function detail($where, $with = ['user', 'address', 'product' => ['image', 'refund'], 'extract', 'express', 'extractStore.logo', 'extractClerk', 'supplier', 'verify', 'advance'])
|
{
|
is_array($where) ? $filter = $where : $filter['order_id'] = (int)$where;
|
return (new static())->with($with)->where($filter)->find();
|
}
|
|
/**
|
* 订单详情
|
*/
|
public static function detailByNo($order_no, $with = ['user', 'address', 'product' => ['image', 'refund'], 'extract', 'express', 'extractStore.logo', 'extractClerk', 'supplier'])
|
{
|
return (new static())->with($with)->where('order_no', '=', $order_no)->find();
|
}
|
|
/**
|
* 批量获取订单列表
|
*/
|
public function getListByIds($orderIds, $with = [])
|
{
|
$data = $this->getListByInArray('order_id', $orderIds, $with);
|
return helper::arrayColumn2Key($data, 'order_id');
|
}
|
|
/**
|
* 批量更新订单
|
*/
|
public function onBatchUpdate($orderIds, $data)
|
{
|
return $this->where('order_id', 'in', $orderIds)->save($data);
|
}
|
|
/**
|
* 批量获取订单列表
|
*/
|
private function getListByInArray($field, $data, $with = [])
|
{
|
return $this->with($with)
|
->where($field, 'in', $data)
|
->where('is_delete', '=', 0)
|
->select();
|
}
|
|
/**
|
* 生成订单号
|
*/
|
public function orderNo()
|
{
|
return OrderService::createOrderNo();
|
}
|
|
/**
|
* 确认核销(自提订单)
|
*/
|
public function verificationOrder($extractClerkId,$storeId=0,$shop_supplier_id=0)
|
{
|
if (
|
$this['pay_status']['value'] != 20
|
|| ($this['delivery_type']['value'] != DeliveryTypeEnum::EXTRACT && $this['delivery_type']['value'] != DeliveryTypeEnum::NO_EXPRESS && $this['delivery_type']['value'] != DeliveryTypeEnum::STORESS)
|
// || $this['delivery_status']['value'] == 20 // 已发货的也可核销,比如门店配送的 by lyzflash
|
|| $this['receipt_status'] == 20
|
|| in_array($this['order_status']['value'], [20, 21])
|
) {
|
$this->error = '该订单不满足核销条件';
|
return false;
|
}
|
if (empty($extractClerkId)){
|
$this->error = '核销人员不能为空';
|
return false;
|
}
|
//获取核销门店 计算配送点提成(上门自提跟门店配送都有门店提成)
|
$extractStore=StoreModel::detail($this['extract_store_id']);
|
$commission = 0;
|
if(!empty($extractStore)){
|
$commission=$extractStore['commission_rate']>0?$this['order_price']*$extractStore['commission_rate']/100:0;
|
|
$storeMoney=$extractStore['money']+$commission;
|
$storeTotalMoney=$extractStore['total_money']+$commission;
|
$extractStore->save(['money'=>$storeMoney,'total_money'=>$storeTotalMoney]);
|
}
|
|
$delivery_fee=0;
|
if($this['delivery_type']['value']==40){//门店配送订单才有配送费
|
if($extractStore['delivery_type']==0){
|
$delivery_fee=$extractStore['delivery_rate']>0?$this['order_price']*$extractStore['delivery_rate']/100:0;
|
}else{
|
$delivery_fee=$extractStore['delivery_fee'];
|
}
|
$extractClerk=ClerkModel::detail($extractClerkId);
|
$clerkMoney=$extractClerk['money']+$delivery_fee;
|
$clerkTotalMoney=$extractClerk['total_money']+$delivery_fee;
|
$extractClerk->save(['money'=>$clerkMoney,'total_money'=>$clerkTotalMoney]);
|
}
|
|
//判断是否券商品 by yj 2024.1.10
|
$add_supplier_money = 0;
|
$extractSupplier = SupplierModel::detail($shop_supplier_id);//核销的商户
|
if(!empty($this['is_virtual']) && $this['is_virtual'] == 2){
|
|
//优先判断是不是自营商户的券商品
|
$orderSupplier = SupplierModel::detail($this['shop_supplier_id']);//订单的商户
|
//普通商户的券商品
|
if(!empty($orderSupplier["store_type"]) && $orderSupplier["store_type"] == 10 && !empty($extractSupplier) && $orderSupplier["shop_supplier_id"] != $extractSupplier["shop_supplier_id"]){
|
$this->error = '核销失败,您不是该券所属商户的核销员';
|
return false;
|
}
|
|
//自营商户的券商品
|
if(!empty($orderSupplier["store_type"]) && $orderSupplier["store_type"] == 20 && !empty($extractSupplier) && $orderSupplier["shop_supplier_id"] != $extractSupplier["shop_supplier_id"]){
|
//其他商户核销自营商户的券商品,则把券的抵扣金额计算给核销的商户
|
$add_supplier_money = $this["product"][0]["deduction_price"];
|
}
|
|
}
|
|
return $this->transaction(function () use ($extractClerkId,$commission,$delivery_fee,$storeId,$add_supplier_money,$extractSupplier) {
|
// 更新订单状态:已发货、已收货
|
$data = [
|
'extract_clerk_id' => $extractClerkId, // 核销员
|
'delivery_status' => 20,
|
'receipt_status' => 20,
|
'receipt_time' => time(),
|
'order_status' => 30
|
];
|
// 门店配送的订单不需要更新配送时间 by lyzflash
|
if (empty($this['delivery_time'])) {
|
$data['delivery_time'] = time();
|
}
|
$status = $this->save($data);
|
// 新增订单核销记录
|
$extractStoreId = empty($this['extract_store_id']) ? $storeId : $this['extract_store_id'];
|
StoreOrderModel::add(
|
$this['order_id'],
|
$extractStoreId,
|
$this['extract_clerk_id'],
|
$this['shop_supplier_id'],
|
OrderTypeEnum::MASTER,
|
$commission,
|
$delivery_fee
|
);
|
//增加核销券 的抵扣金额 by yj 2024.1.10
|
if(!empty($add_supplier_money) && $add_supplier_money > 0 && !empty($extractSupplier)){
|
$this->addSupplierMoney($this,$add_supplier_money,$extractSupplier);
|
}
|
// 执行订单完成后的操作
|
$OrderCompleteService = new OrderCompleteService(OrderTypeEnum::MASTER);
|
$OrderCompleteService->complete([$this], static::$app_id);
|
return $status;
|
});
|
}
|
|
/**
|
* 供应商金额=券商品的抵扣金额 by yj 2024.1.10
|
*/
|
private function addSupplierMoney($order,$add_supplier_money,$extractSupplier)
|
{
|
|
$orderSettledData = [
|
'order_id' => $order['order_id'],
|
'shop_supplier_id' => $extractSupplier['shop_supplier_id'],//核销的商户
|
'order_money' => $add_supplier_money,
|
'pay_money' => $add_supplier_money,
|
'express_money' => 0,
|
'supplier_money' => $add_supplier_money,
|
'real_supplier_money' => $add_supplier_money,
|
'sys_money' => 0,
|
'real_sys_money' => 0,
|
'agent_money' => 0,
|
'team_money' => 0,
|
'region_money' => 0,
|
'shareholder_money' => 0,
|
'refund_money' => 0,
|
'refund_supplier_money' => 0,
|
'refund_sys_money' => 0,
|
'app_id' => $order['app_id']
|
];
|
// 商家结算记录
|
$supplierCapitalData = [
|
'shop_supplier_id' => $extractSupplier['shop_supplier_id'],
|
'money' => $add_supplier_money,
|
'describe' => '核销券商品结算,订单号:' . $order['order_no'],
|
'app_id' => $order['app_id']
|
];
|
(new supplierModel())->where(['shop_supplier_id' => $extractSupplier['shop_supplier_id']])
|
->inc('total_money', $add_supplier_money)
|
->inc('money', $add_supplier_money)
|
->update();
|
// 修改平台结算金额
|
(new OrderSettledModel())->save($orderSettledData);
|
// 供应商结算明细金额
|
(new SupplierCapitalModel())->save($supplierCapitalData);
|
return true;
|
}
|
|
|
/**
|
* 获取已付款订单总数 (可指定某天)
|
*/
|
public function getOrderData($startDate = null, $endDate = null, $type, $shop_supplier_id = 0)
|
{
|
$model = $this;
|
|
!is_null($startDate) && $model = $model->where('pay_time', '>=', strtotime($startDate));
|
|
if (is_null($endDate)) {
|
!is_null($startDate) && $model = $model->where('pay_time', '<', strtotime($startDate) + 86400);
|
} else {
|
$model = $model->where('pay_time', '<', strtotime($endDate) + 86400);
|
}
|
|
if ($shop_supplier_id > 0) {
|
$model = $model->where('shop_supplier_id', '=', $shop_supplier_id);
|
}
|
|
$model = $model->where('is_delete', '=', 0)
|
->where('pay_status', '=', 20)
|
->where('order_status', '<>', 20);
|
|
|
if ($type == 'order_total') {
|
// 订单数量
|
return $model->count();
|
} else if ($type == 'order_total_price') {
|
// 订单总金额
|
return $model->sum('pay_price');
|
} else if ($type == 'order_user_total') {
|
// 支付用户数
|
return count($model->distinct(true)->column('user_id'));
|
}
|
return 0;
|
}
|
|
/**
|
* 修改订单价格
|
*/
|
public function updatePrice($data)
|
{
|
if ($this['pay_status']['value'] != 10) {
|
$this->error = '该订单不合法';
|
return false;
|
}
|
if ($this['order_source'] != 10) {
|
$this->error = '该订单不合法';
|
return false;
|
}
|
// 实际付款金额
|
$payPrice = bcadd($data['update_price'], $data['update_express_price'], 2);
|
if ($payPrice <= 0) {
|
$this->error = '订单实付款价格不能为0.00元';
|
return false;
|
}
|
return $this->save([
|
'order_no' => $this->orderNo(), // 修改订单号, 否则微信支付提示重复
|
'order_price' => $data['update_price'],
|
'pay_price' => $payPrice,
|
'update_price' => helper::bcsub($data['update_price'], helper::bcsub($this['total_price'], $this['coupon_money'])),
|
'express_price' => $data['update_express_price']
|
]) !== false;
|
}
|
|
/**
|
* 后台取消订单
|
*/
|
public function orderCancel($data)
|
{
|
// 判断订单是否可以取消
|
if ($this['delivery_status']['value'] == 20 || $this['order_status']['value'] != 10 || $this['pay_status']['value'] != 20) {
|
$this->error = "订单不允许取消";
|
return false;
|
}
|
// 订单取消事件
|
$status = $this->transaction(function () use ($data) {
|
// 执行退款操作
|
(new OrderRefundService)->execute($this);
|
// 回退商品库存
|
ProductFactory::getFactory($this['order_source'])->backProductStock($this['product'], true);
|
// 回退用户优惠券
|
$this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
|
$this['coupon_id_sys'] > 0 && UserCouponModel::setIsUse($this['coupon_id_sys'], false);
|
// 回退用户积分
|
$user = UserModel::detail($this['user_id']);
|
$describe = "订单取消:{$this['order_no']}";
|
$this['points_num'] > 0 && $user->setIncPoints($this['points_num'], $describe);
|
//预售订单
|
if ($this['order_source'] == OrderSourceEnum::ADVANCE) {
|
if ($this['advance']['money_return'] == 1) {//预售订单退定金
|
if ((new OrderRefundService)->execute($this['advance'])) {
|
// 更新订单状态
|
$this['advance']->save([
|
'is_refund' => 1,
|
'refund_money' => $this['advance']['pay_price'],
|
]);
|
}
|
}
|
$this['advance']->save(['order_status' => 20]);
|
}
|
// 减少用户购买商品次数
|
UserModel::decreasePurchaseCount($this['user_id'], $this['product'], $this['app_id']);
|
// 更新订单状态
|
return $this->save(['order_status' => 20,'is_refund' => 1,'refund_money' => $this['pay_price'], 'cancel_remark' => $data['cancel_remark']]);
|
});
|
return $status;
|
}
|
|
/**
|
* 审核:用户取消订单
|
*/
|
public function confirmCancel($data)
|
{
|
// 判断订单是否有效
|
if ($this['pay_status']['value'] != 20) {
|
$this->error = '该订单不合法';
|
return false;
|
}
|
// 订单取消事件
|
$status = $this->transaction(function () use ($data) {
|
if ($data['is_cancel'] == true) {
|
// 执行退款操作
|
(new OrderRefundService)->execute($this);
|
// 回退商品库存
|
ProductFactory::getFactory($this['order_source'])->backProductStock($this['product'], true);
|
// 回退用户优惠券
|
$this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
|
$this['coupon_id_sys'] > 0 && UserCouponModel::setIsUse($this['coupon_id_sys'], false);
|
// 回退用户积分
|
$user = UserModel::detail($this['user_id']);
|
$describe = "订单取消:{$this['order_no']}";
|
$this['points_num'] > 0 && $user->setIncPoints($this['points_num'], $describe,0,true,($this['supplier']['supplier_type'] == SupplierType::GROUPBUYING?1:0));
|
//预售订单
|
if ($this['order_source'] == OrderSourceEnum::ADVANCE) {
|
if ($this['advance']['money_return'] == 1) {//预售订单退定金
|
if ((new OrderRefundService)->execute($this['advance'])) {
|
// 更新订单状态
|
$this['advance']->save([
|
'is_refund' => 1,
|
'refund_money' => $this['advance']['pay_price'],
|
]);
|
}
|
}
|
$this['advance']->save(['order_status' => 20]);
|
}
|
}
|
// 减少用户购买商品次数
|
UserModel::decreasePurchaseCount($this['user_id'], $this['product'], $this['app_id']);
|
// 更新订单状态
|
//return $this->save(['order_status' => $data['is_cancel'] ? 20 : 10]);
|
return $this->save([
|
'order_status' => $data['is_cancel'] ? 20 : 10,
|
'is_refund' => $data['is_cancel'] ? 1 : 0,
|
'refund_money' => $data['is_cancel'] ? $this['pay_price'] : 0,
|
]);
|
});
|
return $status;
|
}
|
|
/**
|
* 确认发货(单独订单)
|
*/
|
public function delivery($data)
|
{
|
// 转义为订单列表
|
$orderList = [$this];
|
// 验证订单是否满足发货条件
|
if (!$this->verifyDelivery($orderList)) {
|
return false;
|
}
|
// 整理更新的数据
|
$updateList = [[
|
'order_id' => $this['order_id'],
|
'express_id' => $data['express_id'],
|
'express_no' => $data['express_no']
|
]];
|
|
// 更新订单发货状态
|
if ($status = $this->updateToDelivery($updateList)) {
|
// 获取已发货的订单
|
$completed = self::detail($this['order_id'], ['user', 'address', 'product', 'express']);
|
// 发送消息通知
|
$this->sendDeliveryMessage([$completed]);
|
}
|
return $status;
|
}
|
|
/**
|
* 确认发货后发送消息通知
|
*/
|
public function sendDeliveryMessage($orderList)
|
{
|
// 实例化消息通知服务类
|
$Service = new MessageService;
|
foreach ($orderList as $item) {
|
// 获取已发货的订单
|
$order = self::detail($item['order_id'], ['user', 'address', 'product', 'express']);
|
// 原生微信支付时才操作
|
if ($order['wx_delivery_status'] == 10 && $order["transaction_id"]) {
|
$order->sendWxExpress($order['express_id'], $order['express_no']);
|
}
|
// 发送消息通知
|
$Service->delivery($item, OrderTypeEnum::MASTER);
|
}
|
return true;
|
}
|
|
/**
|
* 更新订单发货状态(批量)
|
*/
|
private function updateToDelivery($orderList)
|
{
|
$data = [];
|
foreach ($orderList as $item) {
|
$data[] = [
|
'data' => [
|
'order_id' => $item['order_id'],
|
'express_no' => $item['express_no'],
|
'express_id' => $item['express_id'],
|
'delivery_status' => 20,
|
'delivery_time' => time(),
|
],
|
'where' => [
|
'order_id' => $item['order_id']
|
]
|
];
|
}
|
return $this->updateAll($data);
|
}
|
|
/**
|
* 验证订单是否满足发货条件
|
*/
|
private function verifyDelivery($orderList)
|
{
|
foreach ($orderList as $order) {
|
if (
|
$order['pay_status']['value'] != 20
|
|| ($order['delivery_type']['value'] != DeliveryTypeEnum::EXPRESS
|
&& $order['delivery_type']['value'] != DeliveryTypeEnum::STORESS)
|
|| $order['delivery_status']['value'] != 10
|
) {
|
$this->error = "订单号[{$order['order_no']}] 不满足发货条件!";
|
return false;
|
}
|
}
|
return true;
|
}
|
|
/**
|
* 获取收入概况
|
*/
|
public function getOrderIncome($days,$shop_supplier_id,$postData)
|
{
|
$data = [];
|
$user_ids=[];
|
$in = true;
|
$total_pay_balance=0;
|
$total_pay_wx=0;
|
$total_pay_cash=0;
|
$total_pay_other=0;
|
$total_coupon=0;
|
$total_fullreduce=0;
|
$total_points=0;
|
$total_refund_money=0;
|
$total_wx_refund_money=0;
|
foreach ($days as $day) {
|
//计算微信支付
|
$order_wx = $this->getOrderIncomeByDate($day, $shop_supplier_id,20,"online_money",$user_ids,$in);//订单微信支付
|
$wx_refund_money = $this->getOrderIncomeByDate($day, $shop_supplier_id,20,"refund_money",$user_ids,$in);//微信退款
|
$balance_wx = (new BalanceOrderModel)->getTotalPayByDate($day,$user_ids,$in);//订单余额充值
|
$user_wx = (new CardRecordModel)->getTotalPayByDate($day,$user_ids,$in);//订单会员卡购买支付
|
$pay_wx = $order_wx + $balance_wx + $user_wx - $wx_refund_money;
|
$total_pay_wx += $pay_wx;
|
$total_wx_refund_money +=$wx_refund_money;
|
|
//计算余额支付
|
$order_balance = $this->getOrderIncomeByDate($day, $shop_supplier_id,[30,40],"balance",$user_ids,$in);//订单余额支付
|
$balance_refund_money = $this->getOrderIncomeByDate($day, $shop_supplier_id,10,"refund_money",$user_ids,$in);//余额退款
|
$pay_balance = $order_balance - $balance_refund_money;
|
$total_pay_balance += $pay_balance;
|
|
//计算现金支付
|
$pay_cash = $this->getOrderIncomeByDate($day, $shop_supplier_id,40,"pay_price",$user_ids,$in);
|
$total_pay_cash += $pay_cash;
|
//其他支付
|
$pay_other = $this->getOrderIncomeByDate($day, $shop_supplier_id,[10,20,40],"pay_price",$user_ids,$in);
|
$total_pay_other += $pay_other;
|
//优惠券
|
$coupon = $this->getOrderIncomeByDate($day, $shop_supplier_id,'',"coupon_money",$user_ids,$in);
|
$total_coupon += $coupon;
|
//满减
|
$fullreduce=$this->getOrderIncomeByDate($day, $shop_supplier_id,'',"fullreduce_money",$user_ids,$in);
|
$total_fullreduce += $fullreduce;
|
//积分
|
$points = $this->getOrderIncomeByDate($day, $shop_supplier_id,'',"points_money",$user_ids,$in);
|
$total_points += $points;
|
//余额加微信总退款
|
$refund_money = $this->getOrderIncomeByDate($day, $shop_supplier_id,'',"refund_money",$user_ids,$in);
|
$total_refund_money += $refund_money;
|
$data[] = [
|
'day' => $day,
|
"pay_balance" =>round($pay_balance,2),//余额支付
|
"pay_wx" =>round($pay_wx,2),//微信支付
|
"pay_cash" =>round($pay_cash,2),//现金支付
|
"pay_other" =>round($pay_other,2),//其他支付
|
"coupon" =>$coupon,//优惠券
|
"fullreduce" =>$fullreduce,//满减
|
"points" =>$points,//积分
|
"refund_money" =>round($refund_money,2),//余额加微信退款
|
"wx_refund_money" =>round($wx_refund_money,2),//仅仅微信退款 用于测试
|
];
|
}
|
$data[] = [
|
'day' => '合计',
|
"pay_balance" =>round($total_pay_balance,2),//余额支付
|
"pay_wx" =>round($total_pay_wx,2),//微信支付
|
"pay_cash" =>round($total_pay_cash,2),//现金支付
|
"pay_other" =>round($total_pay_other,2),//其他支付
|
"coupon" =>round($total_coupon,2),//优惠券
|
"fullreduce" =>round($total_fullreduce,2),//满减
|
"points" =>round($total_points,2),//积分
|
"refund_money" =>round($total_refund_money,2),//余额加微信退款
|
"total_wx_refund_money" =>round($total_wx_refund_money,2),//仅仅微信退款 用于测试
|
];
|
return $data;
|
|
}
|
|
/**
|
* 根据时间获取收入概况
|
*/
|
public function getOrderIncomeByDate($day,$shop_supplier_id,$pay_type='',$field="pay_price",$user_ids=[],$in='true')
|
{
|
$model = $this;
|
$start = strtotime($day);
|
$end = strtotime($day) + 86399;
|
if($field == "refund_money"){
|
$model = $model->where('update_time', 'between', "$start,$end");
|
}else{
|
$model = $model->where('pay_time', 'between', "$start,$end");
|
}
|
//$model = $model->where('create_time', 'between', "$start,$end");
|
|
if ($shop_supplier_id) {
|
$model = $model->where('shop_supplier_id', '=', $shop_supplier_id);
|
}
|
if (!empty($user_ids)) {
|
if($in){
|
$model = $model->where('user_id', 'in', $user_ids);
|
}else{
|
$model = $model->where('user_id', 'not in', $user_ids);
|
}
|
}
|
|
if(!empty($pay_type)){
|
if(is_array($pay_type)){
|
$model = $model->where('pay_type', 'not in', $pay_type);
|
}else{
|
$model = $model->where('pay_type', '=', $pay_type);
|
}
|
}
|
$money = $model->where('pay_status', '=', 20)
|
//->where('order_status', '<>', 20)
|
->where('is_delete', '=', 0)
|
->sum($field);
|
|
return $money;
|
}
|
|
/**
|
* 主订单购买的数量 by yj
|
* 未取消的订单
|
*/
|
public static function getHasBuyProductNum($user_id, $product_id, $is_complete = false, $now_order_id = 0)
|
{
|
$model = new static();
|
$model = $model->alias('order')->where('order.user_id', '=', $user_id)
|
->join('order_product', 'order_product.order_id = order.order_id', 'left')
|
->where('order_product.product_id', '=', $product_id)
|
->where('order.order_source', '=', OrderSourceEnum::MASTER);
|
if ($now_order_id) {
|
$model = $model->where('order.order_id', '<>', $now_order_id);
|
}
|
if ($is_complete) {
|
$model = $model->where('order.order_status', '=', 30);
|
} else {
|
$model = $model->where('order.order_status', '<>', 21);
|
}
|
$count = $model->sum('total_num');
|
log_write($user_id.'-'.'$product_id:'.$count);
|
return $count;
|
}
|
|
|
public function sendWxExpress($express_id, $express_no)
|
{
|
//判断后台是否设置了微信发货 by yj 2024.4.10
|
$store_setting = SettingModel::getItem('store');
|
if(empty($store_setting["is_send_wx"])){
|
//后台没有设置微信发货
|
return true;
|
}
|
// 如果是小程序微信支付,则提交
|
if ($this['pay_type']['value'] != 20 || $this['pay_source'] != 'wx' || $this['transaction_id'] == '') {
|
return false;
|
}
|
$express = null;
|
if ($this['delivery_type']['value'] == 10) {
|
$express = ExpressModel::detail($express_id);
|
$logistics_type = 1;
|
if (!$express['wx_code']) {
|
$logistics_type = 4;
|
}
|
} elseif ($this['delivery_type']['value'] == 20) {
|
$logistics_type = 4;
|
} elseif ($this['delivery_type']['value'] == 30) {
|
$logistics_type = 3;
|
}
|
// 请求参数
|
$params_arr = [
|
// 订单,需要上传物流信息的订单
|
'order_key' => [
|
// 订单单号类型,用于确认需要上传详情的订单。枚举值1,使用下单商户号和商户侧单号;枚举值2,使用微信支付单号。
|
"order_number_type" => 2,
|
// 原支付交易对应的微信订单号
|
"transaction_id" => $this['transaction_id']
|
],
|
// 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
|
"delivery_mode" => 1,
|
// 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
|
"logistics_type" => $logistics_type,//$this->getLogisticsType($this['delivery_type']),
|
// 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]
|
"shipping_list" => [
|
[
|
// 物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
|
"tracking_no" => $this['delivery_type']['value'] == 10 ? $express_no : '',
|
// 物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
|
"express_company" => $this['delivery_type']['value'] == 10 ? $express['wx_code'] : '',
|
// 商品信息,例如:微信红包抱枕*1个,限120个字以内
|
"item_desc" => $this['product'][0]['product_name'],
|
// 联系方式,当发货的物流公司为顺丰时,联系方式为必填,收件人或寄件人联系方式二选一
|
"contact" => [
|
// 收件人联系方式,收件人联系方式为,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
|
"receiver_contact" => $this['delivery_type'] == 10 ? $this->desensitize($this['address']['phone'], 3, 4) : ''
|
]
|
]
|
],
|
// 上传时间,用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00`
|
"upload_time" => $this->getUploadTime(),
|
// 支付者,支付者信息
|
"payer" => [
|
// 用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
|
"openid" => $this['user']['open_id']
|
]
|
];
|
log_write('==sendWxExpress=======================');
|
log_write($params_arr);
|
// 小程序配置信息
|
$app = AppWx::getApp();
|
$model = new WxOrder($app);
|
if ($model->uploadExpress($params_arr)) {
|
$this->save(['wx_delivery_status' => 20]);
|
return true;
|
} else {
|
throw new BaseException($model->getError());
|
}
|
}
|
|
private function getUploadTime()
|
{
|
$microtime = microtime();
|
list($microSeconds, $timeSeconds) = explode(' ', $microtime);
|
$milliseconds = round($microSeconds * 1000);
|
return date('Y-m-d') . 'T' . date('H:i:s') . '.' . $milliseconds . '+08:00';
|
}
|
|
/**
|
* 脱敏
|
*
|
* @authors: Msy
|
* @Created-Time: 2022/10/17 17:54
|
* @param $string 需要脱敏的字符
|
* @param $start 开始位置
|
* @param $length 脱敏长度
|
* @param $re 替换字符
|
* @return string
|
*/
|
public function desensitize($string, $start = 0, $length = 0, $re = '*')
|
{
|
if (empty($string) || empty($length) || empty($re)) return $string;
|
$end = $start + $length;
|
$strlen = mb_strlen($string);
|
$str_arr = array();
|
for ($i = 0; $i < $strlen; $i++) {
|
if ($i >= $start && $i < $end) {
|
$str_arr[] = $re;
|
} else {
|
$str_arr[] = mb_substr($string, $i, 1);
|
}
|
}
|
return implode('', $str_arr);
|
}
|
|
/**
|
* 统计平台的优惠券金额
|
*/
|
public static function getCouponMoneyBySupplier($shop_supplier_id,$create_time='')
|
{
|
$model = new static();
|
//搜索时间段
|
if (!empty($create_time)) {
|
$sta_time = array_shift($create_time);
|
$end_time = array_pop($create_time);
|
$model = $model->whereBetweenTime('settled_time', $sta_time, date('Y-m-d 23:59:59', strtotime($end_time)));
|
}
|
$money = $model->where('pay_status', '=', 20)
|
->where('order_status', '=', 30)
|
->where('is_settled', '=', 1)
|
->where('shop_supplier_id', '=', $shop_supplier_id)
|
->where('is_delete', '=', 0)
|
->sum("coupon_money_sys");
|
|
return $money;
|
}
|
|
/**
|
* 统计平台的优惠券数量
|
*/
|
public static function getCouponNumBySupplier($shop_supplier_id,$create_time='')
|
{
|
$model = new static();
|
//搜索时间段
|
if (!empty($create_time)) {
|
$sta_time = array_shift($create_time);
|
$end_time = array_pop($create_time);
|
$model = $model->whereBetweenTime('settled_time', $sta_time, date('Y-m-d 23:59:59', strtotime($end_time)));
|
}
|
$num = $model->where('pay_status', '=', 20)
|
->where('order_status', '=', 30)
|
->where('is_settled', '=', 1)
|
->where('shop_supplier_id', '=', $shop_supplier_id)
|
->where('is_delete', '=', 0)
|
->count();
|
|
return $num;
|
}
|
|
/**
|
* 获取用户是否购买过指定商品
|
* @param int $user_id 用户ID
|
* @param array $product_ids 商品ID数组
|
* @param bool $is_complete 是否只查询已完成的订单
|
* @return array|bool
|
*/
|
public static function getOrderProductIds($user_id, $product_ids = [], $is_complete = false)
|
{
|
// 构建查询条件
|
$model = (new static())->alias('o')
|
->join('order_product op', 'o.order_id = op.order_id')
|
->where('o.user_id', '=', $user_id)
|
->where('o.order_source', '=', OrderSourceEnum::MASTER)
|
->where('o.is_delete', '=', 0);
|
// 如果指定了商品ID,则只查询这些商品
|
if (!empty($product_ids)) {
|
$model->where('op.product_id', 'in', $product_ids);
|
}
|
|
// 如果只查询已完成的订单
|
if ($is_complete) {
|
$model->where('o.order_status', '=', 30); // 已完成状态
|
} else {
|
// 排除已取消的订单
|
$model->where('o.order_status', '<>', 20);
|
}
|
|
// 查询用户购买过的商品ID
|
$result = $model->group('op.product_id')->column('op.product_id');
|
return $result ?true:false;
|
}
|
}
|