diff --git a/app/common/dao/store/order/StoreCartDao.php b/app/common/dao/store/order/StoreCartDao.php index 52db69e..aeba8c6 100644 --- a/app/common/dao/store/order/StoreCartDao.php +++ b/app/common/dao/store/order/StoreCartDao.php @@ -121,7 +121,19 @@ class StoreCartDao extends BaseDao $query->where('uid', $uid); }, 'config' => function ($query) { - $query->whereIn('config_key', ['mer_integral_status', 'mer_integral_rate', 'mer_store_stock', 'mer_take_status', 'mer_take_name', 'mer_take_phone', 'mer_take_address', 'mer_take_location', 'mer_take_day', 'mer_take_time']); + $query->whereIn('config_key',[ + 'mer_integral_status', + 'mer_integral_rate', + 'mer_integral_money', + 'mer_store_stock', + 'mer_take_status', + 'mer_take_name', + 'mer_take_phone', + 'mer_take_address', + 'mer_take_location', + 'mer_take_day', + 'mer_take_time' + ]); }, 'merchantCategory' ]); diff --git a/app/common/repositories/store/order/StoreOrderCreateRepository.php b/app/common/repositories/store/order/StoreOrderCreateRepository.php index 3e80f7d..37be2fb 100644 --- a/app/common/repositories/store/order/StoreOrderCreateRepository.php +++ b/app/common/repositories/store/order/StoreOrderCreateRepository.php @@ -19,26 +19,25 @@ use app\common\repositories\store\product\{ ProductRepository, StoreDiscountRepository }; -use app\common\repositories\user\{ +use app\common\repositories\user\{IntegralRepository, MemberinterestsRepository, UserAddressRepository, UserBillRepository, UserMerchantRepository, - UserRepository -}; + UserRepository}; use app\validate\api\{ OrderVirtualFieldValidate, UserAddressValidate }; -use think\facade\{Cache, Db, Queue}; +use think\facade\{Cache,Db,Log,Queue}; class StoreOrderCreateRepository extends StoreOrderRepository { - public function v2CartIdByOrderInfo($user, array $cartId, array $takes = null, array $useCoupon = null, bool $useIntegral = false, int $addressId = null, $createOrder = false) + public function v2CartIdByOrderInfo($user, array $cartId, array $takes = null, array $useCoupon = null, bool $usePlatformIntegral = false, bool $useMerIntegral = false, int $addressId = null, $createOrder = false) { $uid = $user->uid; - $userIntegral = $user->integral; - $key = md5(json_encode(compact('cartId', 'takes', 'useCoupon', 'useIntegral', 'addressId'))) . $uid; + // $userIntegral = $user->integral; + $key = md5(json_encode(compact('cartId', 'takes', 'useCoupon', 'usePlatformIntegral','useMerIntegral', 'addressId'))) . $uid; //去掉过期的优惠券信息 app()->make(StoreCouponUserRepository::class)->failCoupon(); @@ -739,76 +738,129 @@ class StoreOrderCreateRepository extends StoreOrderRepository } //积分配置 + $is_has_integral_use = 0;// 是否存在积分使用情况 $sysIntegralConfig = systemConfig(['integral_money', 'integral_status', 'integral_order_rate']); $merIntegralFlag = false; $order_total_integral = 0; $order_total_integral_price = 0; $order_total_give_integral = 0; $allow_no_address = true; + $order_use_mer_integral = 0;// 使用的商户积分(总) + $order_use_mer_integral_price = 0;// 使用的商户积分抵扣的金额 + $order_use_platform_integral = 0;// 使用的平台积分(总) + $order_use_platform_integral_price = 0;// 使用平台积分抵扣的金额 + $hold_mer_integral = 0;// 用户持有的当前订单相关商户总商户积分 + $hold_platform_integral = app()->make(IntegralRepository::class)->getMerIntegral((int)$uid,(int)0);// 用户持有的平台积分总数 foreach ($merchantCartList as &$merchantCart) { + // 获取用户在当前店铺的积分 || 平台积分 + $integralInfo = app()->make(IntegralRepository::class)->getUseIntegral((int)$uid,(int)$merchantCart['mer_id']); + $integralInfo['integral'] = bcsub($hold_platform_integral,$order_use_platform_integral,2);// 剩余可用平台积分 + $integralInfo['convert_integral'] = (float)sprintf("%.2f",$integralInfo['integral'] / $integralInfo['convert_rate']);// 剩余可用平台积分转换后的积分 + + $hold_mer_integral = bcadd($hold_mer_integral,$integralInfo['mer_integral'],2);// 持有商户积分叠加 + if(!$useMerIntegral) $integralInfo['mer_integral'] = (float)0;// 不使用本商户积分 + if(!$usePlatformIntegral) $integralInfo['convert_integral'] = (float)0;// 不使用平台积分 + // 配置信息 $merchantCart['take'] = [ - 'mer_integral_rate' => 0, + 'mer_integral_rate' => 0, 'mer_integral_status' => 0, + 'mer_integral_money' => 0, ]; $allow_no_address = $allow_no_address && $merchantCart['order']['isTake']; foreach ($merchantCart['config'] as $config) { $merchantCart['take'][$config['config_key']] = $config['value']; } $merIntegralConfig = $merchantCart['take']; + unset($merchantCart['config']); $merIntegralConfig['mer_integral_rate'] = min(1, $merIntegralConfig['mer_integral_rate'] > 0 ? bcdiv($merIntegralConfig['mer_integral_rate'], 100, 4) : $merIntegralConfig['mer_integral_rate']); - $total_integral = 0; - $total_integral_price = 0; - $merIntegralFlag = $merIntegralFlag || ((bool)$merIntegralConfig['mer_integral_status']); - $integralFlag = $useIntegral && $sysIntegralConfig['integral_status'] && $sysIntegralConfig['integral_money'] > 0 && $merIntegralConfig['mer_integral_status']; + $total_integral = 0;// 总使用积分 + $total_integral_price = 0;// 总抵扣金额 + $use_mer_integral = 0;// 使用的商户积分(本商户订单) + $use_mer_integral_price = 0;// 使用商户积分抵扣的金额(本商户订单) + $use_platform_integral = 0;// 使用的平台积分(本商户订单) + $use_platform_integral_price = 0;// 使用平台积分抵扣的金额(本商户订单) + $merIntegralFlag = $merIntegralFlag || ((bool)$merIntegralConfig['mer_integral_status']); + // 是否使用积分抵扣 使用抵扣、平台开启、商户开启、积分抵用金额大于0 + $integralMoney = (float)$merIntegralConfig['mer_integral_money'] > 0 ? (float)$merIntegralConfig['mer_integral_money'] : (float)$sysIntegralConfig['integral_money']; + $integralFlag = $sysIntegralConfig['integral_status'] && $merIntegralConfig['mer_integral_status'] && $integralMoney > 0; + + // Log::info('积分抵扣 - 持有积分信息:'.var_export(['商户id'=>$merchantCart['mer_id'],'用户持有'=>$integralInfo],1)); //计算积分抵扣 foreach ($merchantCart['list'] as &$cart) { - //只有普通商品可以抵扣 - if ($cart['product_type'] == 0 && $integralFlag && $userIntegral > 0 && $merchantCart['order']['true_price'] > 0) { - $integralRate = $cart['product']['integral_rate']; - if ($integralRate < 0) { - $integralRate = $merIntegralConfig['mer_integral_rate']; - } else if($integralRate > 0){ - $integralRate = min(bcdiv($integralRate, 100, 4), 1); - } + // 获取积分抵扣比例 可以使用积分抵扣商品支付金额的比例 + $integralRate = $cart['product']['integral_rate'];// 商品单独设置比例 + if ($integralRate < 0) $integralRate = $merIntegralConfig['mer_integral_rate'];// 商户统一设置比例 + else if($integralRate > 0) $integralRate = min(bcdiv($integralRate, 100, 4), 1); + // 判断:当前商品是否可以参与积分抵扣 + $isParticipation = $merchantCart['order']['true_price'] > 0 && $cart['product_type'] == 0 && $integralFlag && $integralRate > 0; + if($isParticipation) $is_has_integral_use = 1;// 是否存在积分使用情况 只要存在一个则存在 + // 只有普通商品可以抵扣 + if ($isParticipation && ($integralInfo['mer_integral'] > 0 || $integralInfo['convert_integral'] > 0) && ($usePlatformIntegral || $useMerIntegral)) { + // 计算积分抵扣 if ($integralRate > 0) { - $productIntegralPrice = min(bcmul(bcmul($this->cartByPrice($cart), $cart['cart_num'], 2), $integralRate, 2), $cart['true_price']); - if ($productIntegralPrice > 0) { - $productIntegral = ceil(bcdiv($productIntegralPrice, $sysIntegralConfig['integral_money'], 3)); - if ($productIntegral <= $userIntegral) { - $userIntegral = bcsub($userIntegral, $productIntegral, 0); - //使用多少积分抵扣了多少金额 - $cart['integral'] = [ - 'use' => $productIntegral, - 'price' => $productIntegralPrice - ]; - } else { - $productIntegralPrice = bcmul($userIntegral, $sysIntegralConfig['integral_money'], 2); - //使用多少积分抵扣了多少金额 - $cart['integral'] = [ - 'use' => $userIntegral, - 'price' => $productIntegralPrice - ]; - $userIntegral = 0; + // 当前商品可以抵扣的金额 + $productIntegralPrice = (float)min(bcmul(bcmul($this->cartByPrice($cart), $cart['cart_num'], 2), $integralRate, 2), $cart['true_price']); + // 抵扣需要的积分 + $productIntegral = (int)ceil(bcdiv($productIntegralPrice, $integralMoney, 3)); + if ($productIntegral > 0 && ($productIntegral <= $integralInfo['mer_integral'] || $productIntegral <= $integralInfo['convert_integral'])) { + // 默认使用商户积分抵扣 + $integralInfo['mer_integral'] = (float)bcsub($integralInfo['mer_integral'], $productIntegral, 2); + $integralInfo['use_integral_type'] = 'mer_integral'; + // 商户积分不足 使用平台积分抵扣 + if($integralInfo['mer_integral'] < 0) { + // 将商户积分加回来 + $integralInfo['mer_integral'] = bcadd($integralInfo['mer_integral'], $productIntegral, 2); + // 使用平台积分抵扣 + $integralInfo['convert_integral'] = bcsub($integralInfo['convert_integral'], $productIntegral, 2);// 减少转换后的积分 + $productIntegral = bcmul($productIntegral, $integralInfo['convert_rate'],2);// 刷新使用积分(使用平台积分,需要根据比例刷新平台积分减少数量) + $integralInfo['integral'] = bcsub($integralInfo['integral'], $productIntegral, 2);// 减少未转化的平台积分 + $integralInfo['use_integral_type'] = 'platform_integral'; } + // 使用多少积分抵扣了多少金额 + $cart['integral'] = [ + 'use' => $productIntegral, + 'price' => $productIntegralPrice, + 'use_integral_type' => $integralInfo['use_integral_type'] + ]; + + // 抵扣后的处理 $cart['true_price'] = bcsub($cart['true_price'], $cart['integral']['price'], 2); $merchantCart['order']['true_price'] = bcsub($merchantCart['order']['true_price'], $cart['integral']['price'], 2); + + if($integralInfo['use_integral_type'] == 'mer_integral') { + $use_mer_integral = bcadd($use_mer_integral, $productIntegral, 2);// 使用的商户积分 + $use_mer_integral_price = bcadd($use_mer_integral_price,$productIntegralPrice,2);// 使用商户积分抵扣的金额 + } + else { + $use_platform_integral = bcadd($use_platform_integral, $productIntegral, 2);;// 使用的平台积分 + $use_platform_integral_price = bcadd($use_platform_integral_price, $productIntegralPrice, 2);;// 使用平台积分抵扣的金额 + } + + $total_integral_price = bcadd($total_integral_price, $cart['integral']['price'], 2); - $total_integral = bcadd($total_integral, $cart['integral']['use'], 0); + $total_integral = bcadd($total_integral, $cart['integral']['use'], 2); continue; } } } $cart['integral'] = null; } + unset($cart); - $order_total_integral = bcadd($order_total_integral, $total_integral, 0); + $order_total_integral = bcadd($order_total_integral, $total_integral, 2); $order_total_integral_price = bcadd($order_total_integral_price, $total_integral_price, 2); + $order_use_mer_integral = bcadd($order_use_mer_integral, $use_mer_integral, 2); + $order_use_mer_integral_price = bcadd($order_use_mer_integral_price, $use_mer_integral_price, 2); + $order_use_platform_integral = bcadd($order_use_platform_integral, $use_platform_integral, 2); + $order_use_platform_integral_price = bcadd($order_use_platform_integral_price, $use_platform_integral_price, 2); + + $_pay_price = $merchantCart['order']['true_price']; $valid_total_price = $merchantCart['order']['valid_total_price']; $total_price = $merchantCart['order']['total_price']; @@ -849,6 +901,11 @@ class StoreOrderCreateRepository extends StoreOrderRepository $callback(); } + + $merchantCart['order']['use_mer_integral'] = $use_mer_integral; + $merchantCart['order']['use_mer_integral_price'] = $use_mer_integral_price; + $merchantCart['order']['use_platform_integral'] = $use_platform_integral; + $merchantCart['order']['use_platform_integral_price'] = $use_platform_integral_price; $merchantCart['order']['order_type'] = $order_type; $merchantCart['order']['total_give_integral'] = $total_give_integral; $merchantCart['order']['total_integral_price'] = $total_integral_price; @@ -894,6 +951,13 @@ class StoreOrderCreateRepository extends StoreOrderRepository 'usePlatformCouponId', 'order_total_integral', 'order_total_integral_price', + 'order_use_mer_integral', + 'order_use_mer_integral_price', + 'order_use_platform_integral', + 'order_use_platform_integral_price', + 'is_has_integral_use', + 'hold_mer_integral', + 'hold_platform_integral', 'order_total_give_integral', 'order_svip_discount', 'total_platform_coupon_price', @@ -902,7 +966,8 @@ class StoreOrderCreateRepository extends StoreOrderRepository 'status', 'address', 'openIntegral', - 'useIntegral', + 'usePlatformIntegral', + 'useMerIntegral', 'key', 'order_refund_switch', 'order' @@ -911,10 +976,9 @@ class StoreOrderCreateRepository extends StoreOrderRepository return $data; } - public function v2CreateOrder($key, int $pay_type, $user, array $cartId, array $extend, array $mark, array $receipt_data, array $takes = null, array $useCoupon = null, bool $useIntegral = false, int $addressId = null, array $post) + public function v2CreateOrder($key, int $pay_type, $user, array $cartId, array $extend, array $mark, array $receipt_data, array $takes = null, array $useCoupon = null, int $addressId = null, array $post) { $uid = $user->uid; -// $orderInfo = $this->v2CartIdByOrderInfo($user, $cartId, $takes, $useCoupon, $useIntegral, $addressId, true); $orderInfo = Cache::get('order_create_cache' . $uid . '_' . $key); if(!$orderInfo){ throw new ValidateException('订单操作超时,请刷新页面'); diff --git a/app/common/repositories/store/product/ProductRepository.php b/app/common/repositories/store/product/ProductRepository.php index 8c0e367..1d883b4 100644 --- a/app/common/repositories/store/product/ProductRepository.php +++ b/app/common/repositories/store/product/ProductRepository.php @@ -790,10 +790,8 @@ class ProductRepository extends BaseRepository $data['content'] = $content; // 查找该商品积分抵扣比例 - if(!empty($data['merchant'])){ - $data['merchant']['mer_integral_status'] = merchantConfig($data['merchant']['mer_id'],'mer_integral_status'); - $data['merchant']['mer_integral_rate'] = merchantConfig($data['merchant']['mer_id'],'mer_integral_rate'); - } + if(!empty($data['merchant'])) $data['merchant'] = merchantConfig($data['merchant']['mer_id'],['mer_integral_status','mer_integral_rate','mer_integral_money']); + // 拼接商品分类 if (!empty($data['storeCategory'])) { diff --git a/app/common/repositories/user/IntegralRepository.php b/app/common/repositories/user/IntegralRepository.php index 38827b8..6830770 100644 --- a/app/common/repositories/user/IntegralRepository.php +++ b/app/common/repositories/user/IntegralRepository.php @@ -15,6 +15,8 @@ namespace app\common\repositories\user; use app\common\dao\user\IntegralDao; use app\common\repositories\BaseRepository; +use app\common\repositories\system\merchant\MerchantRepository; +use think\facade\Log; /** * Common: ... @@ -54,6 +56,61 @@ class IntegralRepository extends BaseRepository $info->number = (float)sprintf("%.2f",$info->number + $changeNumber); $info->save(); } + /** + * Common: 获取当前商户积分、平台积分及平台转换后的积分数量 + * Author: wu-hui + * Time: 2023/11/07 18:01 + * @param int $uid + * @param int $mer_id + * @return float[] + */ + public function getUseIntegral(int $uid,int $mer_id):array{ + $convert_rate = (float)app()->make(MerchantRepository::class)->getSearch(['mer_id' => $mer_id])->value('mer_integral_merchant_rate'); + return [ + 'mer_integral' => (float)$this->getMerIntegral($uid,$mer_id),// 当前商户积分 + 'convert_rate' => (float)$convert_rate,// 平台积分转商户积分转换比例 + ]; + } + /** + * Common: 获取指定商户积分 + * Author: wu-hui + * Time: 2023/11/07 17:38 + * @param int $uid + * @param int $mer_id + * @return float + */ + public function getMerIntegral(int $uid,int $mer_id):float{ + $integralInfo = $this->dao->findOrCreate([ + 'uid' => $uid, + 'mer_id' => $mer_id + ]); + + return (float)$integralInfo->number; + } + /** + * Common: 获取平台积分 + * Author: wu-hui + * Time: 2023/11/07 18:01 + * @param int $uid + * @param int $mer_id + * @return array + */ + public function getIntegral(int $uid,int $mer_id = 0):array{ + // 获取平台积分 + $integral = $this->getMerIntegral($uid,(int)0); + // 是否转换为某个商户的商户积分 + $convert_integral = 0; + $convert_rate = 0; + if($mer_id > 0 && $integral > 0){ + $convert_rate = (float)app()->make(MerchantRepository::class)->getSearch(['mer_id' => $mer_id])->value('mer_integral_merchant_rate'); + if($convert_rate > 0) $convert_integral = (float)sprintf("%.2f",$integral / $convert_rate); + } + + return compact('integral','convert_integral','convert_rate'); + } + + + diff --git a/app/common/repositories/user/UserRepository.php b/app/common/repositories/user/UserRepository.php index 8924dbd..848a229 100644 --- a/app/common/repositories/user/UserRepository.php +++ b/app/common/repositories/user/UserRepository.php @@ -413,33 +413,37 @@ class UserRepository extends BaseRepository * @author xaboy * @day 2020-05-07 */ - public function changeIntegral($id, $adminId, $type, $integral) - { + public function changeIntegral($id, $adminId, $type, $integral){ $user = $this->dao->get($id); Db::transaction(function () use ($id, $adminId, $user, $type, $integral) { - $integral = (int)$integral; - $balance = $type == 1 ? bcadd($user->integral, $integral, 0) : bcsub($user->integral, $integral, 0); + // 总积分变更 + $integral = (float)$integral; + $balance = $type == 1 ? bcadd($user->integral, $integral, 2) : bcsub($user->integral, $integral, 2); $user->save(['integral' => $balance]); + // 积分记录变更 & 商户积分变更(这里是管理后台操作 固定变更平台积分) /** @var UserBillRepository $make */ $make = app()->make(UserBillRepository::class); + $billData = [ + 'link_id' => $adminId, + 'status' => 1, + 'number' => $integral, + 'balance' => $balance + ]; if ($type == 1) { - $make->incBill($id, 'integral', 'sys_inc', [ - 'link_id' => $adminId, - 'status' => 1, - 'title' => '系统增加积分', - 'number' => $integral, - 'mark' => '系统增加了' . $integral . '积分', - 'balance' => $balance - ]); + // 总积分变更 + $billData['title'] = '系统增加积分'; + $billData['mark'] = '系统增加了'.$integral.'积分'; + $make->incBill($id, 'integral', 'sys_inc', $billData); + // 商户积分变更 + app()->make(IntegralRepository::class)->changeIntegral((int)$id,(int)0,$integral); } else { - $make->decBill($id, 'integral', 'sys_dec', [ - 'link_id' => $adminId, - 'status' => 1, - 'title' => '系统减少积分', - 'number' => $integral, - 'mark' => '系统减少了' . $integral . '积分', - 'balance' => $balance - ]); + // 总积分变更 + $billData['title'] = '系统减少积分'; + $billData['mark'] = '系统减少了'.$integral.'积分'; + $make->decBill($id, 'integral', 'sys_dec', $billData); + // 商户积分变更 + $decIntegral = (float)sprintf("%.2f",0 - $integral); + app()->make(IntegralRepository::class)->changeIntegral((int)$id,(int)0,$decIntegral); } }); } diff --git a/app/controller/admin/system/merchant/Merchant.php b/app/controller/admin/system/merchant/Merchant.php index aef4d38..cb82752 100644 --- a/app/controller/admin/system/merchant/Merchant.php +++ b/app/controller/admin/system/merchant/Merchant.php @@ -193,7 +193,28 @@ class Merchant extends BaseController */ public function checkParam(MerchantValidate $validate, $isUpdate = false) { - $data = $this->request->params([['category_id', 0], ['type_id', 0], 'mer_name', 'commission_rate', 'real_name', 'mer_phone', 'mer_keyword', 'mer_address', 'mark', ['sort', 0], ['status', 0], ['is_audit', 0], ['is_best', 0], ['is_bro_goods', 0], ['is_bro_room', 0], ['is_trader', 0],'sub_mchid',['commission_switch',0]]); + $data = $this->request->params([ + ['category_id',0], + ['type_id',0], + 'mer_name', + 'commission_rate', + 'real_name', + 'mer_phone', + 'mer_keyword', + 'mer_address', + 'mark', + ['sort',0], + ['status',0], + ['is_audit',0], + ['is_best',0], + ['is_bro_goods',0], + ['is_bro_room',0], + ['is_trader',0], + 'sub_mchid', + ['commission_switch',0], + ['mer_integral_platform_rate',0], + ['mer_integral_merchant_rate',0] + ]); if (!$isUpdate) { $data += $this->request->params(['mer_account', 'mer_password']); }else { diff --git a/app/controller/api/store/order/StoreOrder.php b/app/controller/api/store/order/StoreOrder.php index ef38d95..cc32a4f 100644 --- a/app/controller/api/store/order/StoreOrder.php +++ b/app/controller/api/store/order/StoreOrder.php @@ -58,12 +58,13 @@ class StoreOrder extends BaseController $addressId = (int)$this->request->param('address_id'); $couponIds = (array)$this->request->param('use_coupon', []); $takes = (array)$this->request->param('takes', []); - $useIntegral = (bool)$this->request->param('use_integral', false); + $usePlatformIntegral = (bool)$this->request->param('use_platform_integral', false); + $useMerIntegral = (bool)$this->request->param('use_mer_integral', false); $user = $this->request->userInfo(); $uid = $user->uid; if (!($count = count($cartId)) || $count != count($cartRepository->validIntersection($cartId, $uid))) return app('json')->fail('数据无效'); - $orderInfo = $orderCreateRepository->v2CartIdByOrderInfo($user, $cartId, $takes, $couponIds, $useIntegral, $addressId); + $orderInfo = $orderCreateRepository->v2CartIdByOrderInfo($user, $cartId, $takes, $couponIds, $usePlatformIntegral,$useMerIntegral, $addressId); return app('json')->success($orderInfo); } @@ -106,8 +107,8 @@ class StoreOrder extends BaseController // if (!$addressId) // return app('json')->fail('请选择地址'); - $groupOrder = app()->make(LockService::class)->exec('order.create', function () use ($key, $orderCreateRepository, $receipt_data, $mark, $extend, $cartId, $payType, $takes, $couponIds, $useIntegral, $addressId, $post) { - return $orderCreateRepository->v2CreateOrder($key, array_search($payType, StoreOrderRepository::PAY_TYPE), $this->request->userInfo(), $cartId, $extend, $mark, $receipt_data, $takes, $couponIds, $useIntegral, $addressId, $post); + $groupOrder = app()->make(LockService::class)->exec('order.create', function () use ($key, $orderCreateRepository, $receipt_data, $mark, $extend, $cartId, $payType, $takes, $couponIds, $addressId, $post) { + return $orderCreateRepository->v2CreateOrder($key, array_search($payType, StoreOrderRepository::PAY_TYPE), $this->request->userInfo(), $cartId, $extend, $mark, $receipt_data, $takes, $couponIds, $addressId, $post); }); if ($groupOrder['pay_price'] == 0) {