重构: 积分抵扣重构 - 下单时积分抵扣显示内容修改、抵扣计算修改

This commit is contained in:
wuhui_zzw 2023-11-08 16:34:08 +08:00
parent e248e6b175
commit 03fe59ae83
7 changed files with 230 additions and 73 deletions

View File

@ -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'
]);

View File

@ -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('订单操作超时,请刷新页面');

View File

@ -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'])) {

View File

@ -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');
}

View File

@ -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);
}
});
}

View File

@ -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 {

View File

@ -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) {