作为一个开发软件的程序员来说,要开发系统必先整理好产品需求,产品功能分析先行,站在商业模式角度来说,好的软件系统必须符合产品设计理念,产品的流量要以用户用户自驱,趣味性,奖励性,激励性的行为去展开,在开发惠乐优选系统的过程中,产品功能要点总结如下,欢迎大家探讨交流,微信号:toudouge
下面我从3个部分来说明惠乐优选系统的开发情况
一、会员功能介绍
二、激励奖励机制介绍
三、系统核心源码分享
一、系统的会员功能介绍
会员拼团行为设计
1.每个账号每天每个分类可以参与拼团20次
2.20人参与拼团,其中只有1人拼中
3.拼团人数满人既开团,60分钟不满人拼团解散,不满人数时拼团解散不扣当日拼团次数
4.根据每个商品设定的拼团人数,其中拼中者获得拼团商品,同类商品累积拼中5次,可以选择其中4件寄售,选择其中1件商品发货自用,拼不中退款,所有参加拼团的拼中或拼不中都可领取1个0.1元到3元的随机现金红包,收益部分T+0结算提现,10元起提(提现手续费6%)
5.SVIP补贴拼团1次,享受自动拼团,尊享会员是身份(普通会员可参团20次,SVIP会员可以开团21次)
6.前期开设5个专区,每个专区每天最多20次拼团收益;五个专区每天一共能拼100次(每团20人开团),每次拼团无论拼中与否,都有一个对应的红包奖励,最低门槛30元既可参团(中5次可寄售4件发货一件),红包金额0.1到3元不等
二、激励奖励机制介绍
奖金驱动设计
1.推荐奖
自邀首单5%现金奖励(实时到账,可提现)
2.晋升制度:
LV1:直推5个有效,好友红包收益的5%,团队红包收益2%,LV2:直推10个有效且团队30个有效,好友红包收益的10%,团队红包收益3%,LV3:直推30个有效且团队80个有效,好友红包收益的15%,团队红包收益4%,平级收益10%,LV2:直推50个有效且团队600个有效,好友红包收益的20%,团队红包收益5%,平级收益10%
3.奖金池分红设计
每拼中1单拿出拼中金额的5%进入排行榜奖金池,当日直邀有效会员人数前10名会员按照比例来分红
分红比例:
第1名30%,第2名18%,第3名12%,第4名8%,第5名7%,第6名6%,第7名6%,第8名5%,第9名5%,第10名3%;每天23点分红,分红结束奖金池清零,次日继续累积奖金池金额
三、系统部分核心源码分享
以下是系统分润核心源码
/**
* 拼团处理
* @param $cartInfo
* @return array
*/
public static function getCombinationOrderPriceGroup($cartInfo)
{
$storePostage = floatval(sys_config('store_postage')) ?: 0;
$storeFreePostage = floatval(sys_config('store_free_postage')) ?: 0;
$totalPrice = self::getCombinationOrderTotalPrice($cartInfo);
$costPrice = self::getCombinationOrderTotalPrice($cartInfo);
if (!$storeFreePostage) {
$storePostage = 0;
} else {
foreach ($cartInfo as $cart) {
if (!StoreCombination::where('id', $cart['combination_id'])->value('is_postage'))
$storePostage = bcadd($storePostage, StoreCombination::where('id', $cart['combination_id'])->value('postage'), 2);
}
if ($storeFreePostage <= $totalPrice) $storePostage = 0;
}
return compact('storePostage', 'storeFreePostage', 'totalPrice', 'costPrice');
}
/**
* 拼团价格
* @param $cartInfo
* @return float
*/
public static function getCombinationOrderTotalPrice($cartInfo)
{
$totalPrice = 0;
foreach ($cartInfo as $cart) {
if ($cart['combination_id']) {
$totalPrice = bcadd($totalPrice, bcmul($cart['cart_num'], StoreCombination::where('id', $cart['combination_id'])->value('price'), 2), 2);
}
}
return (float)$totalPrice;
}
/**
* 缓存订单信息
* @param $uid
* @param $cartInfo
* @param $priceGroup
* @param array $other
* @param int $cacheTime
* @return string
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public static function cacheOrderInfo($uid, $cartInfo, $priceGroup, $other = [], $cacheTime = 600)
{
$key = md5(time());
Cache::set('user_order_' . $uid . $key, compact('cartInfo', 'priceGroup', 'other'), $cacheTime);
return $key;
}
/**
* 获取订单缓存信息
* @param $uid
* @param $key
* @return mixed|null
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public static function getCacheOrderInfo($uid, $key)
{
$cacheName = 'user_order_' . $uid . $key;
if (!Cache::has($cacheName)) return null;
return Cache::get($cacheName);
}
/**
* 删除订单缓存
* @param $uid
* @param $key
*/
public static function clearCacheOrderInfo($uid, $key)
{
Cache::delete('user_order_' . $uid . $key);
}
/**
* 生成订单
* @param $uid
* @param $key
* @param $addressId
* @param $payType
* @param bool $useIntegral
* @param int $couponId
* @param string $mark
* @param int $combinationId
* @param int $pinkId
* @param int $seckill_id
* @param int $bargain_id
* @param bool $test
* @param int $isChannel
* @param int $shipping_type
* @param string $real_name
* @param string $phone
* @return StoreOrder|bool|\think\Model
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function cacheKeyCreateOrder($uid, $key, $addressId, $payType, $useIntegral = false, $couponId = 0, $mark = '', $combinationId = 0, $pinkId = 0, $seckill_id = 0, $bargain_id = 0, $test = false, $isChannel = 0, $shipping_type = 1, $real_name = '', $phone = '', $storeId = 0, $is_auto = 0)
{
self::beginTrans();
try {
$shipping_type = (int)$shipping_type;
$offlinePayStatus = (int)sys_config('offline_pay_status') ?? (int)2;
if ($offlinePayStatus == 2) unset(self::$payType['offline']);
if (!array_key_exists($payType, self::$payType)) return self::setErrorInfo('选择支付方式有误!', true);
if (self::be(['unique' => $key, 'uid' => $uid])) return self::setErrorInfo('请勿重复提交订单', true);
$userInfo = User::getUserInfo($uid);
if (!$userInfo) return self::setErrorInfo('用户不存在!', true);
$cartGroup = self::getCacheOrderInfo($uid, $key);
if (!$cartGroup) return self::setErrorInfo('订单已过期,请刷新当前页面!', true);
$cartInfo = $cartGroup['cartInfo'];
$check_hour = intval(date('H'));
//$check_goods_info = StoreProduct::field('start_hour,stop_hour')->where('id',$cartInfo[0]['productInfo']['id'])->find()->toArray();
if( $check_hour < 6
|| $check_hour >= 22
)
return self::setErrorInfo('还未到该团参与的时间', true);
if( StoreOrderSpell::where('uid="'.$uid.'" AND goods_id = "'.$cartInfo[0]['productInfo']['id'].'" AND is_pay = 1 AND status = 0')->count() > 0 )
return self::setErrorInfo('您已经在队列中,请勿重复参加!', true);
$priceGroup = $cartGroup['priceGroup'];
$other = $cartGroup['other'];
$payPrice = (float)$priceGroup['totalPrice'];
$addr = UserAddress::where('uid', $uid)->where('id', $addressId)->find();
if ($payType == 'offline' && sys_config('offline_postage') == 1) {
$payPostage = 0;
} else {
$payPostage = self::getOrderPriceGroup($cartInfo, $addr)['storePostage'];
}
if ($shipping_type === 1) {
if (!$test && !$addressId) return self::setErrorInfo('请选择收货地址!', true);
if (!$test && (!UserAddress::be(['uid' => $uid, 'id' => $addressId, 'is_del' => 0]) || !($addressInfo = UserAddress::find($addressId))))
return self::setErrorInfo('地址选择有误!', true);
} else {
if ((!$real_name || !$phone) && !$test) return self::setErrorInfo('请填写姓名和电话', true);
$addressInfo['real_name'] = $real_name;
$addressInfo['phone'] = $phone;
$addressInfo['province'] = '';
$addressInfo['city'] = '';
$addressInfo['district'] = '';
$addressInfo['detail'] = '';
}
$cartIds = [];
$totalNum = 0;
$gainIntegral = 0;
foreach ($cartInfo as $cart){
if (!$test && !self::checkProductStock($uid, $cart['product_id'], $cart['cart_num'], $cart['product_attr_unique'], $cart['combination_id'], $cart['seckill_id'], $cart['bargain_id'])) {
return false;
}
$cartIds[] = $cart['id'];
$totalNum += $cart['cart_num'];
if (!$seckill_id) $seckill_id = $cart['seckill_id'];
if (!$bargain_id) $bargain_id = $cart['bargain_id'];
if (!$combinationId) $combinationId = $cart['combination_id'];
$cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul($cart['cart_num'], $cart['productInfo']['give_integral'], 2) : 0;
$gainIntegral = bcadd($gainIntegral, $cartInfoGainIntegral, 2);
}
$deduction = $seckill_id || $bargain_id || $combinationId;
if ($deduction) {
$couponId = 0;
$useIntegral = false;
if (!$test) {
unset(self::$payType['offline']);
if (!array_key_exists($payType, self::$payType)) return self::setErrorInfo('营销产品不能使用线下支付!', true);
}
}
//使用优惠劵
$res1 = true;
if ($couponId) {
$couponInfo = StoreCouponUser::validAddressWhere()->where('id', $couponId)->where('uid', $uid)->find();
if (!$couponInfo) return self::setErrorInfo('选择的优惠劵无效!', true);
$coupons = StoreCouponUser::getUsableCouponList($uid, ['valid' => $cartInfo], $payPrice);
$flag = false;
foreach ($coupons as $coupon) {
if ($coupon['id'] == $couponId) {
$flag = true;
continue;
}
}
if (!$flag)
return self::setErrorInfo('不满足优惠劵的使用条件!', true);
$payPrice = (float)bcsub($payPrice, $couponInfo['coupon_price'], 2);
$res1 = StoreCouponUser::useCoupon($couponId);
$couponPrice = $couponInfo['coupon_price'];
} else {
$couponId = 0;
$couponPrice = 0;
}
if (!$res1) return self::setErrorInfo('使用优惠劵失败!', true);
//$shipping_type = 1 快递发货 $shipping_type = 2 门店自提
$store_self_mention = sys_config('store_self_mention') ?? 0;
if (!$store_self_mention) $shipping_type = 1;
if ($shipping_type === 1) {
//是否包邮
if ((isset($other['offlinePostage']) && $other['offlinePostage'] && $payType == 'offline')) $payPostage = 0;
$payPrice = (float)bcadd($payPrice, $payPostage, 2);
} else if ($shipping_type === 2) {
//门店自提没有邮费支付
$priceGroup['storePostage'] = 0;
$payPostage = 0;
if (!$storeId && !$test) {
return self::setErrorInfo('请选择门店', true);
}
}
//积分抵扣
$res2 = true;
$SurplusIntegral = 0;
$useIntegral = false;
if ($useIntegral && $userInfo['integral'] > 0) {
$deductionPrice = (float)bcmul($userInfo['integral'], $other['integralRatio'], 2);
if ($deductionPrice < $payPrice) {
$payPrice = bcsub($payPrice, $deductionPrice, 2);
$usedIntegral = $userInfo['integral'];
$SurplusIntegral = 0;
$res2 = false !== User::edit(['integral' => 0], $userInfo['uid'], 'uid');
} else {
$deductionPrice = $payPrice;
$usedIntegral = (float)bcdiv($payPrice, $other['integralRatio'], 2);
$SurplusIntegral = bcsub($userInfo['integral'], $usedIntegral, 2);
$res2 = false !== User::bcDec($userInfo['uid'], 'integral', $usedIntegral, 'uid');
$payPrice = 0;
}
$res2 = $res2 && false != UserBill::expend('积分抵扣', $uid, 'integral', 'deduction', $usedIntegral, $key, $userInfo['integral'], '购买商品使用' . floatval($usedIntegral) . '积分抵扣' . floatval($deductionPrice) . '元');
} else {
$deductionPrice = 0;
$usedIntegral = 0;
}
if (!$res2) return self::setErrorInfo('使用积分抵扣失败!', true);
if ($payPrice <= 0) $payPrice = 0;
if ($test) {
self::rollbackTrans();
return [
'total_price' => $priceGroup['totalPrice'],
'pay_price' => $payPrice,
'pay_postage' => $payPostage,
'coupon_price' => $couponPrice,
'deduction_price' => $deductionPrice,
'SurplusIntegral' => $SurplusIntegral,
];
}
$orderInfo = [
'uid' => $uid,
'order_id' => $test ? 0 : self::getNewOrderId(),
'real_name' => $addressInfo['real_name'],
'user_phone' => $addressInfo['phone'],
'user_address' => $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['detail'],
'cart_id' => $cartIds,
'total_num' => $totalNum,
'total_price' => $priceGroup['totalPrice'],
'total_postage' => $priceGroup['storePostage'],
'coupon_id' => $couponId,
'coupon_price' => $couponPrice,
'pay_price' => $payPrice,
'pay_postage' => $payPostage,
'deduction_price' => $deductionPrice,
'paid' => 0,
'pay_type' => $payType,
'use_integral' => $usedIntegral,
'gain_integral' => $gainIntegral,
'mark' => htmlspecialchars($mark),
'combination_id' => $combinationId,
'pink_id' => $pinkId,
'seckill_id' => $seckill_id,
'bargain_id' => $bargain_id,
'cost' => $priceGroup['costPrice'],
'is_channel' => $isChannel,
'add_time' => time(),
'unique' => $key,
'shipping_type' => $shipping_type,
];
if ($shipping_type === 2) {
$orderInfo['verify_code'] = self::getStoreCode();
$orderInfo['store_id'] = SystemStore::getStoreDispose($storeId, 'id');
if (!$orderInfo['store_id']) return self::setErrorInfo('暂无门店无法选择门店自提!', true);
}
$order = self::create($orderInfo);
if (!$order) return self::setErrorInfo('订单生成失败!', true);
$res5 = true;
foreach ($cartInfo as $cart) {
//减库存加销量
if ($combinationId) $res5 = $res5 && StoreCombination::decCombinationStock($cart['cart_num'], $combinationId, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
else if ($seckill_id) $res5 = $res5 && StoreSeckill::decSeckillStock($cart['cart_num'], $seckill_id, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
else if ($bargain_id) $res5 = $res5 && StoreBargain::decBargainStock($cart['cart_num'], $bargain_id, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
else $res5 = $res5 && StoreProduct::decProductStock($cart['cart_num'], $cart['productInfo']['id'], isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
}
//保存购物车商品信息
$res4 = false !== StoreOrderCartInfo::setCartInfo($order['id'], $cartInfo);
$res7 = $res8 = true;
if($cartInfo[0]['productInfo']['id'])
{
$user_info = User::getUserInfo($uid);
$insert_spell_data = [
'uid' => $uid,
'nickname' => $user_info['nickname'],
'oid' => $order['id'],
'goods_id' => $cartInfo[0]['productInfo']['id'],
'status' => 0,
'is_auto' => $is_auto,
'is_pay' => 0,
'edit_time' => time(),
'add_time' => time(),
];
$res7 = StoreOrderSpell::insert($insert_spell_data);
//如果系统没有记录,则新增一条
if( StoreOrderSpellUserLog::where('uid="'.$uid.'" AND goods_id="'.$cartInfo[0]['productInfo']['id'].'"')->count() == 0)
{
$insert_user_log = [
'goods_id' => $cartInfo[0]['productInfo']['id'],
'uid' => $uid,
];
$res8 = StoreOrderSpellUserLog::insert($insert_user_log);
}
}
//购物车状态修改
$res6 = false !== StoreCart::where('id', 'IN', $cartIds)->update(['is_pay' => 1]);
if (!$res4 || !$res5 || !$res6 || !$res7 || !$res8) return self::setErrorInfo('订单生成失败!', true);
//自动设置默认地址
UserRepository::storeProductOrderCreateEbApi($order, compact('cartInfo', 'addressId'));
self::clearCacheOrderInfo($uid, $key);
self::commitTrans();
StoreOrderStatus::status($order['id'], 'cache_key_create_order', '订单生成');
return $order;
} catch (\PDOException $e) {
self::rollbackTrans();
return self::setErrorInfo('生成订单时SQL执行错误错误原因:' . $e->getMessage());
} catch (\Exception $e) {
self::rollbackTrans();
return self::setErrorInfo('生成订单时系统错误错误原因:' . $e->getMessage());
}
}
/**
* 回退积分
* @param $order 订单信息
* @return bool
*/
public static function RegressionIntegral($order)
{
if ($order['paid'] || $order['status'] == -2 || $order['is_del']) return true;
if ($order['use_integral'] <= 0) return true;
if ((int)$order['status'] != -2 && (int)$order['refund_status'] != 2 && $order['back_integral'] >= $order['use_integral']) return true;
$res = User::bcInc($order['uid'], 'integral', $order['use_integral']);
if (!$res) return self::setErrorInfo('回退积分增加失败');
UserBill::income('积分回退', $order['uid'], 'integral', 'deduction', $order['use_integral'], $order['unique'], User::where('uid', $order['uid'])->value('integral'), '购买商品失败,回退积分' . floatval($order['use_integral']));
return false !== self::where('order_id', $order['order_id'])->update(['back_integral' => $order['use_integral']]);
}
/**
* 回退库存和销量
* @param $order 订单信息
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function RegressionStock($order)
{
if ($order['status'] == -2 || $order['is_del']) return true;
$combinationId = $order['combination_id'];
$seckill_id = $order['seckill_id'];
$bargain_id = $order['bargain_id'];
$res5 = true;
$cartInfo = StoreOrderCartInfo::where('cart_id', 'in', $order['cart_id'])->select();
foreach ($cartInfo as $cart) {
//增库存减销量
if ($combinationId) $res5 = $res5 && StoreCombination::incCombinationStock($cart['cart_info']['cart_num'], $combinationId, isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '');
else if ($seckill_id) $res5 = $res5 && StoreSeckill::incSeckillStock($cart['cart_info']['cart_num'], $seckill_id, isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '');
else if ($bargain_id) $res5 = $res5 && StoreBargain::incBargainStock($cart['cart_info']['cart_num'], $bargain_id, isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '');
else $res5 = $res5 && StoreProduct::incProductStock($cart['cart_info']['cart_num'], $cart['cart_info']['productInfo']['id'], isset($cart['cart_info']['productInfo']['attrInfo']) ? $cart['cart_info']['productInfo']['attrInfo']['unique'] : '');
}
return $res5;
}