915 lines
39 KiB
PHP
915 lines
39 KiB
PHP
<?php
|
||
|
||
namespace app\api\logic\order;
|
||
|
||
use app\common\enum\OrderEnum;
|
||
use app\common\enum\PayEnum;
|
||
use app\common\enum\UserShipEnum;
|
||
use app\common\enum\YesNoEnum;
|
||
use app\common\logic\BaseLogic;
|
||
use app\common\logic\CapitalFlowLogic;
|
||
use app\common\logic\PayNotifyLogic;
|
||
use app\common\logic\StoreFinanceFlowLogic;
|
||
use app\common\logic\UserSignLogic;
|
||
use app\common\model\Config;
|
||
use app\common\model\dict\DictData;
|
||
use app\common\model\dict\DictType;
|
||
use app\common\model\order\Cart;
|
||
use app\common\model\store_branch_product\StoreBranchProduct;
|
||
use app\common\model\store_category\StoreCategory;
|
||
use app\common\model\store_finance_flow\StoreFinanceFlow;
|
||
use app\common\model\store_finance_flow_product\StoreFinanceFlowProduct;
|
||
use app\common\model\store_order\StoreOrder;
|
||
use app\common\model\store_order_cart_info\StoreOrderCartInfo;
|
||
use app\common\model\store_product\StoreProduct;
|
||
use app\common\model\store_product_attr_value\StoreProductAttrValue;
|
||
use app\common\model\store_product_log\StoreProductLog;
|
||
use app\common\model\store_product_unit\StoreProductUnit;
|
||
use app\common\model\system_store\SystemStore;
|
||
use app\common\model\system_store\SystemStoreStaff;
|
||
use app\common\model\user\User;
|
||
use app\common\model\user\UserAddress;
|
||
use app\common\model\user_ship\UserShip;
|
||
use app\common\model\user_sign\UserSign;
|
||
use app\common\model\user_spread_log\UserSpreadLog;
|
||
use DateTime;
|
||
use Picqer\Barcode\BarcodeGeneratorJPG;
|
||
use Picqer\Barcode\BarcodeGeneratorPNG;
|
||
use support\exception\BusinessException;
|
||
use support\Log;
|
||
use taoser\exception\ValidateException;
|
||
use think\db\Raw;
|
||
use think\Exception;
|
||
use think\facade\Db;
|
||
use Workerman\Events\Select;
|
||
use Yansongda\Pay\Event\PayEnd;
|
||
|
||
/**
|
||
* 订单逻辑
|
||
* Class OrderLogic
|
||
* @package app\api\logic\order
|
||
*/
|
||
class OrderLogic extends BaseLogic
|
||
{
|
||
public static $total_price;
|
||
public static $pay_price;
|
||
public static $cost;
|
||
public static $store_price; //门店零售价
|
||
public static $activity_price;
|
||
public static $deduction_price;
|
||
public static $frozen_money; //返还金额
|
||
public static $fresh_price; //生鲜金额
|
||
/**
|
||
* @notes 获取购物车商品信息
|
||
* @param $params
|
||
* @return array|bool
|
||
*/
|
||
static public function cartIdByOrderInfo($cartId, $addressId, $user = null, $params = [], $createOrder = 0)
|
||
{
|
||
if (empty($params['store_id']) || $params['store_id'] <= 0) {
|
||
throw new BusinessException('请选择门店');
|
||
}
|
||
$source=0;
|
||
if (isset($params['source']) && $params['source'] >0) {
|
||
$source=$params['source'];
|
||
}
|
||
$where = ['is_pay' => 0];
|
||
$cart_select = Cart::whereIn('id', $cartId)->where($where)->field('id,product_id,cart_num,source')->select()->toArray();
|
||
if (empty($cart_select)) {
|
||
throw new BusinessException('购物车为空');
|
||
}
|
||
try {
|
||
self::$total_price = 0;
|
||
self::$pay_price = 0;
|
||
self::$cost = 0; //成本由采购价替代原成本为门店零售价
|
||
self::$activity_price = 0; //活动减少
|
||
self::$store_price = 0; //商户价
|
||
self::$deduction_price = 0;
|
||
self::$frozen_money = 0; //返还金额
|
||
$deduction_price = 0; //抵扣金额
|
||
self::$fresh_price = 0; //生鲜金额
|
||
/** 计算价格 */
|
||
$off_activity = Config::where('name', 'off_activity')->value('value');
|
||
$field = 'id,store_name,image,unit,price,vip_price,cost,purchase,cate_id,store_info,rose';
|
||
foreach ($cart_select as $k => $v) {
|
||
$source=$v['source'];
|
||
$find = StoreProduct::where(['id' => $v['product_id']])->field($field)->find();
|
||
|
||
if (!$find) {
|
||
throw new BusinessException('商品不存在');
|
||
}
|
||
if (convertNumber($v['cart_num']) == false) {
|
||
$is_bulk = StoreProductUnit::where('id', $find['unit'])->value('is_bulk');
|
||
if ($is_bulk == 0) {
|
||
throw new BusinessException('非计量商品,不能有小数,请编辑购物车');
|
||
}
|
||
}
|
||
$StoreCategory = StoreCategory::where('id', $find['cate_id'])->find();
|
||
$find['top_cate_id'] = $find['cate_id'];
|
||
if ($StoreCategory && $StoreCategory['pid'] > 0) {
|
||
$StoreCategory2 = StoreCategory::where('id', $StoreCategory['pid'])->find();
|
||
if ($StoreCategory2 && $StoreCategory2['pid'] > 0) {
|
||
$find['top_cate_id'] = $StoreCategory2['pid'];
|
||
} else {
|
||
$find['top_cate_id'] = $StoreCategory['pid'];
|
||
}
|
||
}
|
||
unset($cart_select[$k]['id']);
|
||
$cart_select[$k]['total_price'] = bcmul($v['cart_num'], $find['price'], 2); //订单总价
|
||
if ($v['source'] != 4) {
|
||
if ($off_activity == 1 || ($user != null && in_array($user['user_ship'], [4, 6, 7]))) {
|
||
$price = $find['cost'];
|
||
} else {
|
||
$price = $find['price'];
|
||
//单门店活动判断
|
||
if ($params['store_id'] == getenv('ACTIVITY_STORE_ID')) {
|
||
$storeBranchPrice = StoreBranchProduct::where('store_id', getenv('ACTIVITY_STORE_ID'))->where('product_id', $v['product_id'])->value('price');
|
||
if ($storeBranchPrice) {
|
||
$price = $storeBranchPrice;
|
||
}
|
||
}
|
||
}
|
||
if ($off_activity == 0 && $find['top_cate_id'] == 15189 && $user && $user['user_ship'] == 5) {
|
||
$price = $find['cost'];
|
||
}
|
||
} else {
|
||
$price = $find['price'];
|
||
}
|
||
|
||
$cart_select[$k]['price'] = $price;
|
||
$cart_select[$k]['cost'] = $find['cost'];
|
||
$cart_select[$k]['vip'] = 0;
|
||
$cart_select[$k]['unit_name'] = StoreProductUnit::where(['id' => $find['unit']])->value('name') ?? ''; //单位名称
|
||
|
||
//利润
|
||
// $cart_select[$k]['profit'] = bcmul($v['cart_num'], $onePrice, 2); //利润
|
||
$cart_select[$k]['purchase'] = bcmul($v['cart_num'], $find['purchase'], 2) ?? 0; //成本
|
||
$cart_select[$k]['pay_price'] = bcmul($v['cart_num'], $price, 2); //订单支付金额
|
||
$cart_select[$k]['store_price'] = bcmul($v['cart_num'], $find['cost'], 2) ?? 0; //商户价
|
||
$cart_select[$k]['vip_price'] = bcmul($v['cart_num'], $find['vip_price'], 2) ?? 0; //vip售价
|
||
if ($cart_select[$k]['total_price'] > $cart_select[$k]['pay_price']) {
|
||
$deduction_price = bcsub($cart_select[$k]['total_price'], $cart_select[$k]['pay_price'], 2);
|
||
$cart_select[$k]['deduction_price'] = $deduction_price; //抵扣金额
|
||
}
|
||
$cart_select[$k]['product_id'] = $find['id'];
|
||
$cart_select[$k]['old_cart_id'] = $v['id'];
|
||
$cart_select[$k]['cart_num'] = floatval($v['cart_num']);
|
||
$cart_select[$k]['verify_code'] = $params['verify_code'] ?? '';
|
||
$cart_select[$k]['vip_frozen_price'] = 0;
|
||
$cart_select[$k]['store_info'] = $find['store_info'];
|
||
$cart_select[$k]['rose'] = $find['rose'];
|
||
//会员待返回金额
|
||
// if ($user && $off_activity == 0) {
|
||
// if ($user['user_ship'] == 4) {
|
||
// //商户
|
||
// $cart_select[$k]['vip_frozen_price'] = bcsub($cart_select[$k]['pay_price'], $cart_select[$k]['store_price'], 2);
|
||
// } else {
|
||
// //其他会员
|
||
// $cart_select[$k]['vip_frozen_price'] = bcsub($cart_select[$k]['pay_price'], $cart_select[$k]['vip_price'], 2);
|
||
// }
|
||
// }
|
||
// d($cart_select[$k]['pay_price'],$cart_select[$k]['store_price'],$cart_select[$k]['vip_price'] );
|
||
$cartInfo = $cart_select[$k];
|
||
$cartInfo['name'] = $find['store_name'];
|
||
$cartInfo['image'] = $find['image'];
|
||
$cart_select[$k]['cart_info'] = json_encode($cartInfo);
|
||
//理论上每笔都是拆分了
|
||
$cart_select[$k]['name'] = $find['store_name'];
|
||
$cart_select[$k]['imgs'] = $find['image'];
|
||
$cart_select[$k]['store_id'] = $params['store_id'] ?? 0;
|
||
$cart_select[$k]['unit_name'] = StoreProductUnit::where(['id' => $find['unit']])->value('name');
|
||
$cart_select[$k]['total_price'] = $cart_select[$k]['pay_price'];
|
||
self::$total_price = bcadd(self::$total_price, $cart_select[$k]['total_price'], 2);
|
||
self::$pay_price = bcadd(self::$pay_price, $cart_select[$k]['pay_price'], 2);
|
||
self::$cost = bcadd(self::$cost, $cart_select[$k]['purchase'], 2);
|
||
self::$store_price = bcadd(self::$store_price, $cart_select[$k]['store_price'], 2); //商户价
|
||
self::$deduction_price = bcadd(self::$deduction_price, $deduction_price, 2); //抵扣金额
|
||
// self::$frozen_money = bcadd(self::$frozen_money, $cart_select[$k]['vip_frozen_price'], 2); //返还金额
|
||
//计算生鲜
|
||
if ($createOrder == 1 && $find['top_cate_id'] == 15201) {
|
||
self::$fresh_price = bcadd(self::$fresh_price, $cart_select[$k]['pay_price'], 2);
|
||
}
|
||
// self::$profit = bcadd(self::$profit, $cart_select[$k]['profit'], 2);
|
||
}
|
||
//加支付方式限制
|
||
// $pay_type = isset($params['pay_type']) ? $params['pay_type'] : 0;
|
||
// if ($user && $user['user_ship'] == 1 && $pay_type != 17) {
|
||
// $pay_price = self::$pay_price;
|
||
// } else {
|
||
|
||
|
||
$pay_price = self::$pay_price; // bcsub(self::$pay_price, self::$activity_price, 2); //减去活动优惠金额
|
||
//判断生鲜是否大于200
|
||
// if ($createOrder == 1 && self::$fresh_price > 0 &&$source!=2) {
|
||
// if (self::$pay_price < 200) {
|
||
// throw new BusinessException('订单包含生鲜产品,订单金额必须大于200元,才能下单');
|
||
// }
|
||
// }
|
||
if (isset($params['store_id']) && $params['store_id'] == getenv('ACTIVITY_STORE_ID')) {
|
||
$off_activity = 1;
|
||
}
|
||
// }
|
||
//成本价 收益
|
||
$order = [
|
||
'create_time' => time(),
|
||
'order_id' => $params['order_id'] ?? getNewOrderId('PF'),
|
||
'total_price' => self::$total_price, //总价
|
||
'cost' => self::$cost, //成本价1-
|
||
'pay_price' => $pay_price, //支付价
|
||
'vip_price' => 0,
|
||
'total_num' => count($cart_select), //总数
|
||
'pay_type' => $params['pay_type'] ?? 0,
|
||
'reservation_time' => $params['reservation_time'] ?? null,
|
||
'cart_id' => implode(',', $cartId),
|
||
'store_id' => $params['store_id'] ?? 0,
|
||
'shipping_type' => $params['shipping_type'] ?? 2, //配送方式 1=快递 ,2=门店自提
|
||
'activity' => '减免',
|
||
'activity_price' => 0,
|
||
'activities' => $off_activity,
|
||
'deduction_price' => self::$deduction_price, //抵扣金额
|
||
'frozen_money' => 0, //self::$frozen_money, //返还金额(活动关闭得时候有)
|
||
'source' => $source,
|
||
'is_storage' => $params['is_storage'] ?? 0,
|
||
'address_id' => 0,
|
||
];
|
||
$order['default_delivery'] = 0;
|
||
if ($params['store_id']) {
|
||
$order['default_delivery'] = SystemStore::where('id', $params['store_id'])->value('is_send');
|
||
}
|
||
|
||
if (isset($params['store_id']) && $params['store_id'] > 0) {
|
||
$store_id = $params['store_id'];
|
||
} else {
|
||
$store_id = getenv('STORE_ID') ?? 1;
|
||
}
|
||
$store['near_store'] = SystemStore::where('id', $store_id)->field('id,name,phone,address,detailed_address,latitude,longitude')->find() ?? [];
|
||
|
||
if ($user) {
|
||
$order['address_id'] = UserAddress::where('uid', $user['id'])->where('is_default', 1)->value('id') ?? 0;
|
||
}
|
||
$alert = '';
|
||
// 创建一个DateTime对象表示当前时间
|
||
$currentTime = new DateTime();
|
||
|
||
// 创建一个DateTime对象表示下午4点
|
||
$fourPM = new DateTime('16:00');
|
||
|
||
// 使用DateTime::format()方法获取时间并比较
|
||
if ($currentTime->format('H:i') > $fourPM->format('H:i')) {
|
||
$currentDate = date('Y-m-d');
|
||
$alert = '当前时间超过配送截止时间16:00,若下单,物品送达时间为' . date('Y-m-d', strtotime($currentDate . '+2 days'));
|
||
}
|
||
} catch (\Throwable $e) {
|
||
throw new BusinessException($e->getMessage());
|
||
}
|
||
return ['order' => $order, 'cart_list' => $cart_select, 'shopInfo' => $store['near_store'], 'alert' => $alert];
|
||
}
|
||
|
||
/**
|
||
* 创建新订单
|
||
* @return Object|bool|array
|
||
*/
|
||
static public function createOrder($cartId, $addressId, $user = null, $params = [])
|
||
{
|
||
$order_id = getNewOrderId('PF');
|
||
$code = rand(1, 10) . '-' . substr($order_id, -5);
|
||
$verify_code = createCode($code);
|
||
$params['order_id'] = $order_id;
|
||
$params['verify_code'] = $verify_code;
|
||
$orderInfo = self::cartIdByOrderInfo($cartId, $addressId, $user, $params, 1);
|
||
$uid = $user['id'] ?? 0;
|
||
$_order = $orderInfo['order'];
|
||
if ($_order['pay_price'] == 0) {
|
||
throw new BusinessException('支付金额不能为0');
|
||
}
|
||
$_order['uid'] = $uid;
|
||
$_order['spread_uid'] = $params['spread_uid'] ?? 0;
|
||
$_order['mark'] = $params['mark'] ?? '';
|
||
$_order['real_name'] = $user['real_name'] ?? '';
|
||
$_order['user_phone'] = $user['mobile'] ?? '';
|
||
$_order['pay_type'] = $orderInfo['order']['pay_type'];
|
||
$_order['verify_code'] = $verify_code;
|
||
$_order['reservation_time'] = null;
|
||
$_order['reservation'] = 0;
|
||
$params['reservation'] ?? 0; //是否需要预约
|
||
// if (isset($params['reservation_time']) && $params['reservation_time']) {
|
||
// $_order['reservation_time'] = $params['reservation_time'];
|
||
// $_order['reservation'] = YesNoEnum::YES;
|
||
// }
|
||
if ($uid > 0) {
|
||
$address = UserAddress::where(['uid' => $uid])->find();
|
||
if ($address) {
|
||
if ($address['area']) {
|
||
$_order['user_address'] = Db::name('geo_area')->where('area_code', $address['area'])->value('area_name') ?? '';
|
||
}
|
||
if ($address['street']) {
|
||
$street_name = Db::name('geo_street')->where('street_code', $address['street'])->value('street_name') ?? '';
|
||
$_order['user_address'] .= '/' . $street_name;
|
||
}
|
||
if ($address['village']) {
|
||
$village_name = Db::name('geo_village')->where('village_code', $address['village'])->value('village_name') ?? '';
|
||
$_order['user_address'] .= '/' . $village_name;
|
||
}
|
||
if ($address['brigade']) {
|
||
$_order['user_address'] .= '/' . $address['brigade'] ?? $address['brigade'] . '队';
|
||
}
|
||
}
|
||
}
|
||
if ($params['shipping_type'] == 2) {
|
||
$_order['status'] = 1;
|
||
}
|
||
if ($_order['pay_type'] == PayEnum::BALANCE_PAY && $user != null && $user['now_money'] < $_order['pay_price']) {
|
||
throw new BusinessException('余额不足');
|
||
}
|
||
//生成核销码
|
||
// $generator = new BarcodeGeneratorPNG();
|
||
// $barcode = $generator->getBarcode($verify_code, $generator::TYPE_CODE_128);
|
||
// $findPath = '/image/barcode/' . time() . '.png';
|
||
// $savePath = public_path() . $findPath;
|
||
// file_put_contents($savePath, $barcode);
|
||
// $_order['verify_img'] = $findPath;
|
||
Db::startTrans();
|
||
try {
|
||
$order = StoreOrder::create($_order);
|
||
$goods_list = $orderInfo['cart_list'];
|
||
|
||
|
||
foreach ($goods_list as $k => $v) {
|
||
$goods_list[$k]['oid'] = $order->id;
|
||
$goods_list[$k]['uid'] = $uid;
|
||
$goods_list[$k]['cart_id'] = implode(',', $cartId);
|
||
$goods_list[$k]['delivery_id'] = $params['store_id']; //商家id
|
||
}
|
||
(new StoreOrderCartInfo())->saveAll($goods_list);
|
||
$where = ['is_pay' => 0];
|
||
Cart::whereIn('id', $cartId)->where($where)->update(['is_pay' => 1]);
|
||
|
||
Db::commit();
|
||
return $order;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
throw new BusinessException($e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检验丢失
|
||
* @param $params
|
||
* @return array|false
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public static function checkLeft($params, $uid, $type = 0)
|
||
{
|
||
$where = [];
|
||
if (empty($type)) {
|
||
$where = ['is_pay' => 0];
|
||
}
|
||
$cart_select = Cart::whereIn('id', $params['cart_id'])
|
||
->where($where)->field('id,product_id,cart_num,store_id')->select()->toArray();
|
||
if (empty($cart_select)) {
|
||
throw new BusinessException('购物车为空');
|
||
}
|
||
$newArr = [];
|
||
//检查购物车对比店铺得商品数量差异
|
||
foreach ($cart_select as $v) {
|
||
$store = StoreBranchProduct::where([
|
||
'store_id' => $params['store_id'],
|
||
'product_id' => $v['product_id'],
|
||
])->field('id,store_name,stock')->withTrashed()->find();
|
||
if (empty($store)) {
|
||
$store['stock'] = 0;
|
||
}
|
||
if ($store['stock'] < $v['cart_num']) {
|
||
//缺失
|
||
$newArr[] = [
|
||
'uid' => $uid,
|
||
'store_id' => $params['store_id'],
|
||
'product_id' => $v['product_id'],
|
||
'missing_quantity' => $v['cart_num'] - $store['stock']
|
||
];
|
||
}
|
||
}
|
||
|
||
if ($newArr) {
|
||
return [
|
||
'detail' => $newArr,
|
||
'reservation' => 1
|
||
];
|
||
}
|
||
return [
|
||
'detail' => [],
|
||
'reservation' => 0
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @notes 获取订单号
|
||
* @param $type
|
||
* @return string
|
||
* @author likeadmin
|
||
* @date 2021/7/28 17:05
|
||
*/
|
||
static public function getNewOrderId($type)
|
||
{
|
||
list($msec, $sec) = explode(' ', microtime());
|
||
$msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
|
||
$orderId = $type . $msectime . mt_rand(10000, max(intval($msec * 10000) + 10000, 98369));
|
||
return $orderId;
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 订单支付成功
|
||
* @param $order 订单
|
||
* @param $CallbackData 回调数据
|
||
* @date 2021/7/8 00:40
|
||
*/
|
||
static function paySuccess($order, $CallbackData = [])
|
||
{
|
||
Db::startTrans();
|
||
try {
|
||
$order->money = $CallbackData['money'];
|
||
$order->paid = 1;
|
||
$order->save();
|
||
Log::info('支付成功');
|
||
// 提交事务
|
||
Db::commit();
|
||
return true;
|
||
} catch (\Throwable $e) {
|
||
// 回滚事务
|
||
Db::rollback();
|
||
Log::error('支付失败' . $e->getMessage() . '。like:' . $e->getLine());
|
||
throw new BusinessException('支付失败' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取用户常用购买记录
|
||
*/
|
||
public static function frequentlyPurchase($params)
|
||
{
|
||
try {
|
||
$goods_id = StoreOrderCartInfo::where('uid', Request()->userId)->page($params['page_no'])->limit(50)->column('product_id');
|
||
if (!$goods_id) {
|
||
return [];
|
||
}
|
||
$goods_arr = array_unique($goods_id);
|
||
$select = StoreProduct::where('id', 'in', $goods_arr)->with('unitName')->field('id,store_name,price,image,unit')->select();
|
||
return $select->toArray();
|
||
} catch (\Throwable $e) {
|
||
throw new BusinessException($e->getMessage());
|
||
}
|
||
}
|
||
|
||
public static function purchaseAgain($order_id)
|
||
{
|
||
$arr = StoreOrderCartInfo::where('oid', $order_id)->field('product_id,cart_num,staff_id,store_id')->select();
|
||
$data = [];
|
||
foreach ($arr as $k => $v) {
|
||
$data[$k]['product_id'] = $v['product_id'];
|
||
$data[$k]['cart_num'] = $v['cart_num'];
|
||
$data[$k]['type'] = '';
|
||
$data[$k]['uid'] = Request()->userId;
|
||
$data[$k]['store_id'] = $v['store_id'];
|
||
$data[$k]['staff_id'] = $v['staff_id'];
|
||
$data[$k]['combination_id'] = 0;
|
||
$data[$k]['status'] = 1;
|
||
$data[$k]['staff_id'] = 0;
|
||
$data[$k]['is_new'] = 0;
|
||
$data[$k]['is_del'] = 0;
|
||
$data[$k]['is_pay'] = 0;
|
||
}
|
||
if ($data) {
|
||
(new Cart())->saveAll($data);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
public static function detail($params, $url = '', $param = []): array
|
||
{
|
||
$find = StoreOrder::where($params)->findOrEmpty()->toArray();
|
||
if ($find) {
|
||
|
||
$find['goods_list'] = StoreOrderCartInfo::where('oid', $find['id'])
|
||
->field('product_id,cart_num nums,store_id')->select()->each(function ($item) use ($find) {
|
||
$find = StoreProduct::where('id', $item['product_id'])->withTrashed()->find();
|
||
|
||
$item['store_name'] = $find['store_name'];
|
||
$item['nums'] = floatval($item['nums']);
|
||
$item['image'] = $find['image'];
|
||
$item['price'] = $find['price'];
|
||
$item['unit_name'] = StoreProductUnit::where('id', $find['unit'])->value('name') ?? '';
|
||
$item['msg'] = '预计48小时发货';
|
||
return $item;
|
||
});
|
||
|
||
$store = SystemStore::where('id', $find['store_id'])->field('id,name,phone,address,detailed_address')->find();
|
||
$find['store_info'] = $store;
|
||
|
||
if ($find['verify_img']) {
|
||
$find['verify_img'] = $url . $find['verify_img'];
|
||
}
|
||
if ($find['is_writeoff'] == 0) {
|
||
$generator = new BarcodeGeneratorPNG();
|
||
$tmpFilename = $generator->getBarcode($find['verify_code'], $generator::TYPE_CODE_128);
|
||
$find['verify_base64'] = 'data:image/png;base64,' . base64_encode($tmpFilename);
|
||
}
|
||
//处理返回最近的店铺
|
||
if ($param['lat'] && $param['long']) {
|
||
$storeAll = SystemStore::field('id,name,phone,address,detailed_address,latitude,longitude')->select()->toArray();
|
||
$nearestStore = null;
|
||
$minDistance = PHP_FLOAT_MAX;
|
||
foreach ($storeAll as $value) {
|
||
$value['distance'] = haversineDistance($value['latitude'], $value['longitude'], $param['lat'], $param['long']);
|
||
if ($value['distance'] < $minDistance) {
|
||
$minDistance = $value['distance'];
|
||
$nearestStore = $value;
|
||
}
|
||
}
|
||
if ($nearestStore) {
|
||
$find['near_store'] = $nearestStore;
|
||
}
|
||
}
|
||
}
|
||
return $find;
|
||
}
|
||
|
||
//取消售后
|
||
public static function cancelSell($where)
|
||
{
|
||
return StoreOrder::where($where)->update(
|
||
[
|
||
'refund_status' => OrderEnum::CANCEL_SALE,
|
||
'status' => OrderEnum::CANCEL_ORDER,
|
||
'refund_cancle_time' => date('Y-m-d H:i:s', time())
|
||
]
|
||
);
|
||
}
|
||
|
||
|
||
//核销
|
||
/**
|
||
* @param $params
|
||
* @return bool
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
* @author: codeliu
|
||
* @Time: 2024/6/3 22:42
|
||
*/
|
||
public static function writeOff($params): bool
|
||
{
|
||
$order = StoreOrder::with('store')->where([
|
||
'verify_code' => $params['verify_code']
|
||
])->find();
|
||
if (empty($order)) {
|
||
throw new BusinessException('订单不存在');
|
||
}
|
||
Db::startTrans();
|
||
try {
|
||
StoreOrder::update([
|
||
'verify_code' => $params['verify_code'] . '-1',
|
||
'status' => OrderEnum::RECEIVED_GOODS,
|
||
'is_writeoff' => OrderEnum::IS_OK,
|
||
'update_time' => time(),
|
||
'store_id' => $params['store_id'],
|
||
'staff_id' => $params['staff_id'] ?? 0,
|
||
], ['id' => $order['id']]);
|
||
//修改商品统计记录标识
|
||
(new StoreProductLog())->where('oid', $order['id'])->update(['store_id' => $params['store_id']]);
|
||
(new StoreOrderCartInfo())->update([
|
||
'verify_code' => $params['verify_code'] . '-1',
|
||
'writeoff_time' => time(),
|
||
'is_writeoff' => YesNoEnum::YES,
|
||
'store_id' => $params['store_id'],
|
||
'status' => 1,
|
||
'staff_id' => $params['staff_id'] ?? 0,
|
||
'update_time' => time(),
|
||
], ['oid' => $order['id']]);
|
||
$financeFlow = new StoreFinanceFlow();
|
||
$res = $financeFlow->where('order_id', $order['id'])->update(['store_id' => $params['store_id'], 'staff_id' => $params['staff_id']]);
|
||
if ($res) {
|
||
$order['store_id'] = $params['store_id'];
|
||
}
|
||
$financeFlowLogic = new StoreFinanceFlowLogic();
|
||
//other_uid大于0的
|
||
$select_1 = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 1, 'status' => 0])->where('other_uid', '>', 0)->select();
|
||
foreach ($select_1 as $k => $v) {
|
||
if ($v['other_uid'] > 0) {
|
||
$financeFlowLogic->updateStatusUser($v['id'], $v['other_uid'], $v['number'], $v['order_id']);
|
||
}
|
||
}
|
||
|
||
$deposit = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 0, 'financial_type' => 11, 'status' => 0])->value('number') ?? 0;
|
||
$money = $financeFlow->where(['order_id' => $order['id'], 'financial_pm' => 1, 'financial_type' => 2, 'status' => 0])->value('number') ?? 0;
|
||
$financeFlowLogic->updateStatusStore($order['id'], $order['store_id'], $money, $deposit);
|
||
//积分结算
|
||
if ($order['is_storage'] == 0 && $order['source'] == 0) {
|
||
UserSignLogic::WriteOff($order);
|
||
}
|
||
Db::commit();
|
||
return true;
|
||
} catch (\Throwable $e) {
|
||
Db::rollback();
|
||
throw new BusinessException($e->getMessage());
|
||
}
|
||
}
|
||
|
||
|
||
public static function write_count($info, $params)
|
||
{
|
||
$store_id = SystemStoreStaff::where('phone', $info['mobile'])->value('store_id');
|
||
if (empty($store_id)) {
|
||
throw new BusinessException('该用户未绑定店铺请查看');
|
||
}
|
||
$query = StoreOrderCartInfo::alias('o')
|
||
->leftJoin('store_branch_product p', 'p.id = o.product_id')
|
||
->leftJoin('store_order s', 's.id = o.oid')
|
||
->field('o.oid,p.store_name,s.order_id')
|
||
->where('o.store_id', $store_id);
|
||
|
||
if (isset($params['name']) && $params['name']) {
|
||
if ($params['name'] && preg_match('/[\x{4e00}-\x{9fff}]+/u', $params['name']) == 1) {
|
||
$query->where('p.store_name', 'like', '%' . $params['name'] . '%');
|
||
} else {
|
||
$query->where('s.order_id', $params['name']);
|
||
}
|
||
}
|
||
$product = $query->select();
|
||
if (empty($product)) {
|
||
return [
|
||
'no_send' => 0,
|
||
'send' => 0
|
||
];
|
||
}
|
||
$oids = array_column($product->toArray(), 'oid');
|
||
$uniqueOids = array_unique($oids);
|
||
$no_send = StoreOrder::whereIn('id', $uniqueOids)
|
||
->where('status', 1)->count();
|
||
$send = StoreOrder::whereIn('id', $uniqueOids)
|
||
->where('status', 2)->count();
|
||
return [
|
||
'no_send' => $no_send,
|
||
'send' => $send
|
||
];
|
||
}
|
||
|
||
public static function getOne($code)
|
||
{
|
||
return StoreOrder::with(['store'])->where('verify_code', $code)
|
||
->select()->each(function ($item) {
|
||
$item['goods_list'] = StoreOrderCartInfo::where('oid', $item['id'])->with('goodsName')->field('product_id,cart_num,verify_code,is_writeoff,writeoff_time')->limit(3)->select();
|
||
$item['goods_count'] = count(explode(',', $item['cart_id']));
|
||
return $item; //返回处理后的数据。
|
||
})
|
||
->toArray();
|
||
}
|
||
|
||
public static function write_list($info, $status, $params)
|
||
{
|
||
|
||
$store_id = SystemStoreStaff::where('phone', $info['mobile'])->value('store_id');
|
||
if (empty($store_id)) {
|
||
throw new BusinessException('该用户未绑定店铺请查看');
|
||
}
|
||
|
||
//先查商品相似
|
||
$query = StoreOrderCartInfo::alias('o')
|
||
->leftJoin('store_branch_product p', 'p.id = o.product_id')
|
||
->leftJoin('store_order s', 's.id = o.oid')
|
||
->field('o.oid,p.store_name,s.order_id')
|
||
->where('o.store_id', $store_id);
|
||
|
||
if (isset($params['name']) && $params['name']) {
|
||
if ($params['name'] && preg_match('/[\x{4e00}-\x{9fff}]+/u', $params['name']) == 1) {
|
||
$query->where('p.store_name', 'like', '%' . $params['name'] . '%');
|
||
} else {
|
||
$query->where('s.order_id', $params['name']);
|
||
}
|
||
}
|
||
$product = $query->select();
|
||
if (empty($product)) {
|
||
return [
|
||
'list' => [],
|
||
'count' => 0
|
||
];
|
||
}
|
||
$oids = array_column($product->toArray(), 'oid');
|
||
$uniqueOids = array_unique($oids);
|
||
$query = StoreOrder::with(['store'])
|
||
->whereIn('id', $uniqueOids)
|
||
->where('status', $status);
|
||
$count = $query->count();
|
||
$list = $query
|
||
->page($params['page_no'], $params['page_size'])
|
||
->order(['id' => 'desc'])
|
||
->select()
|
||
->each(function ($item) {
|
||
$item['goods_list'] = StoreOrderCartInfo::where('oid', $item['id'])->with('goodsName')->field('product_id,cart_num,verify_code,is_writeoff,writeoff_time')->limit(3)->select();
|
||
$item['goods_count'] = count(explode(',', $item['cart_id']));
|
||
})
|
||
->toArray();
|
||
return [
|
||
'list' => $list,
|
||
'count' => $count
|
||
];
|
||
}
|
||
|
||
public static function dealRefund($uid, $params)
|
||
{
|
||
//todo 单子不是完成的不允许退款
|
||
//单笔不拆单子直接修改状态
|
||
$order = StoreOrder::where('id', $params['id'])->withTrashed()->findOrEmpty();
|
||
$params['refund_num'] = 1; //todo 拿实际数量
|
||
if (count($params['old_cart_id']) == 1) {
|
||
$order->refund_status = OrderEnum::REFUND_STATUS_YES;
|
||
$order->status = OrderEnum::ALREADY_REFUND;
|
||
$order->refund_reason_wap_explain = $params['refund_message'] ?? '';
|
||
$order->mark = $params['mark'] ?? '';
|
||
$order->refund_num = $params['refund_num'] ?? 1;
|
||
$refund_price_cart = StoreOrderCartInfo::where('oid', $params['id'])
|
||
->field('id,oid,cart_info')
|
||
->find()->toArray();
|
||
$vipPrice = $order['vip_price'];
|
||
$price = $refund_price_cart['cart_info']['price'] * $params['refund_num'];
|
||
$onePrice = 0;
|
||
bcscale(2);
|
||
if ($vipPrice) {
|
||
//每单的vip价格
|
||
$onePrice = bcdiv($vipPrice, $refund_price_cart['cart_info']['cart_num']);
|
||
}
|
||
if ($price > $onePrice) {
|
||
$price = bcsub($price, $onePrice);
|
||
}
|
||
$order->refund_price = $price;
|
||
$order->refund_type = $params['refund_type'];
|
||
$order->save();
|
||
} else {
|
||
// 多单的情况 拆主订单为新的2单 修改新的2单的核销码 修改cart_info的核销码 和订单id 退款直接退一单的钱
|
||
$order->delete_time = time();
|
||
$order->save();
|
||
Db::startTrans();
|
||
try {
|
||
$order = $order->toArray();
|
||
$cart_info = StoreOrderCartInfo::where('oid', $params['id'])
|
||
->whereNotIn('old_cart_id', $params['old_cart_id'])
|
||
->select()->toArray();
|
||
if ($cart_info) {
|
||
$leftOrder = self::dealCreateLeftOrder($order, $cart_info, $params);
|
||
self::dealChangeCartInfo($leftOrder);
|
||
}
|
||
$refundOrder = self::dealCreateRefundOrder($order, $params);
|
||
self::dealChangeCartInfo($refundOrder);
|
||
// d($leftOrder,$refundOrder);
|
||
Db::commit();
|
||
} catch (\Throwable $e) {
|
||
// 回滚事务
|
||
Db::rollback();
|
||
throw new BusinessException($e->getMessage());
|
||
}
|
||
}
|
||
|
||
return $order['status'] ?? 1;
|
||
}
|
||
|
||
|
||
public static function dealChangeCartInfo($leftOrder)
|
||
{
|
||
$code = $leftOrder->verify_code;
|
||
$new_oid = $leftOrder->id;
|
||
$old_id = $leftOrder->pid;
|
||
$car_id = explode(',', $leftOrder->cart_id);
|
||
return StoreOrderCartInfo::where('oid', $old_id)
|
||
->whereIn('old_cart_id', $car_id)
|
||
->update([
|
||
'oid' => $new_oid,
|
||
'verify_code' => $code
|
||
]);
|
||
}
|
||
|
||
|
||
public static function dealCreateLeftOrder($order, $cart_info, $params)
|
||
{
|
||
//查出不在这个退货中的数据
|
||
$order['order_id'] = $order['order_id'] . '-2';
|
||
$order['pid'] = $order['id'];
|
||
unset($order['id']);
|
||
$allOldCartIds = [];
|
||
$totalTotal = 0;
|
||
$totalPrice = 0;
|
||
$totalVipPrice = 0;
|
||
foreach ($cart_info as $value) {
|
||
if (isset($value['old_cart_id'])) {
|
||
$allOldCartIds[] = $value['old_cart_id'];
|
||
}
|
||
if (isset($value['cart_info'])) {
|
||
if (isset($value['cart_info']['total'])) {
|
||
$totalTotal += floatval($value['cart_info']['total']);
|
||
}
|
||
if (isset($value['cart_info']['price'])) {
|
||
$totalPrice += floatval($value['cart_info']['price']);
|
||
}
|
||
if (isset($value['cart_info']['vip_price'])) {
|
||
$totalVipPrice += floatval($value['cart_info']['vip_price']);
|
||
}
|
||
}
|
||
}
|
||
$order['cart_id'] = implode(',', $allOldCartIds);
|
||
$order['total_num'] = count($cart_info);
|
||
$order['refund_type'] = $params['refund_type'];
|
||
$order['total_price'] = number_format($totalTotal, 2);
|
||
$order['pay_price'] = number_format($totalPrice, 2);
|
||
$order['vip_price'] = number_format($totalVipPrice, 2);
|
||
$order['verify_code'] = verificationCode();
|
||
$order['create_time'] = time();
|
||
$order['update_time'] = null;
|
||
$order['delete_time'] = null;
|
||
return StoreOrder::create($order);
|
||
}
|
||
|
||
|
||
public static function dealCreateRefundOrder($order, $params)
|
||
{
|
||
$order['order_id'] = $order['order_id'] . '-1';
|
||
$order['pid'] = $order['id'];
|
||
unset($order['id']);
|
||
$order['cart_id'] = implode(',', $params['old_cart_id']);
|
||
|
||
$order['refund_status'] = OrderEnum::REFUND_STATUS_YES;
|
||
$order['status'] = OrderEnum::ALREADY_REFUND;
|
||
$order['refund_num'] = $params['refund_num']; //按数量整单退剩余的
|
||
$order['refund_reason_wap_explain'] = $params['refund_message'] ?? '';
|
||
$order['mark'] = $params['mark'] ?? '';
|
||
$order['total_num'] = count($params['old_cart_id']);
|
||
$refund_price_cart = StoreOrderCartInfo::whereIn('old_cart_id', $params['old_cart_id'])
|
||
->field('id,oid,cart_info')
|
||
->select()->toArray();
|
||
$totalTotals = array_column(array_column($refund_price_cart, 'cart_info'), 'total');
|
||
$totalTotal = array_reduce($totalTotals, function ($carry, $item) {
|
||
return $carry + $item;
|
||
}, 0);
|
||
$totalPrices = array_column(array_column($refund_price_cart, 'cart_info'), 'price');
|
||
$totalPrice = array_reduce($totalPrices, function ($carry, $item) {
|
||
return $carry + $item;
|
||
}, 0);
|
||
|
||
$totalVipPrices = array_column(array_column($refund_price_cart, 'cart_info'), 'vip_price');
|
||
$totalVipPrices = array_reduce($totalVipPrices, function ($carry, $item) {
|
||
return $carry + $item;
|
||
}, 0);
|
||
|
||
$order['total_price'] = number_format($totalTotal, 2);
|
||
$order['pay_price'] = number_format($totalPrice, 2);
|
||
$order['vip_price'] = number_format($totalVipPrices, 2);
|
||
$order['refund_price'] = number_format($totalPrice, 2);
|
||
$order['verify_code'] = verificationCode();
|
||
$order['refund_reason_time'] = time();
|
||
$order['create_time'] = time() + 1;
|
||
$order['update_time'] = null;
|
||
$order['delete_time'] = null;
|
||
return StoreOrder::create($order);
|
||
}
|
||
|
||
|
||
public static function dealVip($pay_price)
|
||
{
|
||
$check = DictType::where('type', 'activities')->find();
|
||
if (isset($check) && $check['status'] == 1) {
|
||
// $discountRate = '0.99';//首单逻辑
|
||
$discountRate = $check['remark'];
|
||
$discountRate = bcdiv($discountRate, '100', 2);
|
||
$pay_price = bcdiv(bcmul($pay_price, $discountRate, 4), '1', 2);
|
||
} else {
|
||
$userVip = User::where('id', \request()->userId)->value('user_ship');
|
||
if ($userVip) {
|
||
switch ($userVip) {
|
||
case UserShipEnum::VIP1:
|
||
$discountRate = UserShip::where('id', UserShipEnum::VIP1)->value('discount');
|
||
break;
|
||
case UserShipEnum::VIP2:
|
||
$discountRate = UserShip::where('id', UserShipEnum::VIP2)->value('discount');
|
||
break;
|
||
case UserShipEnum::VIP3:
|
||
$discountRate = UserShip::where('id', UserShipEnum::VIP3)->value('discount');
|
||
break;
|
||
case UserShipEnum::VIP4:
|
||
$discountRate = UserShip::where('id', UserShipEnum::VIP4)->value('discount');
|
||
break;
|
||
case UserShipEnum::VIP5:
|
||
$discountRate = UserShip::where('id', UserShipEnum::VIP5)->value('discount');
|
||
break;
|
||
default:
|
||
$discountRate = 1;
|
||
}
|
||
$discountRate = bcdiv($discountRate, '100', 2);
|
||
$pay_price = bcdiv(bcmul($pay_price, $discountRate, 4), '1', 2);
|
||
}
|
||
}
|
||
return $pay_price;
|
||
}
|
||
}
|