diff --git a/app/common/services/income/IncomeService.php b/app/common/services/income/IncomeService.php index cd8dcb5f..0cfc6301 100644 --- a/app/common/services/income/IncomeService.php +++ b/app/common/services/income/IncomeService.php @@ -207,6 +207,7 @@ class IncomeService const QUICKEN_INCOME_REWARD = 190;//加速收益分红 const REWARD_POOL_DIVIDEND = 191;//奖金池分红 const STORE_MANAGER = 200;// 经销商店长-店补 + const CULTURAL_SPACE_CONTRIBUTION_BONUS = 201;// 文创空间 - 贡献值分红 /** * @param $data 会员id:member_id,分红类型:dividend_code,分红表id:dividend_table_id,金额:amount,订单号:order_sn,详情:detail @@ -677,6 +678,7 @@ class IncomeService self::QUICKEN_INCOME_REWARD => defined('QUICKEN_INCOME_DIY_NAME') ? QUICKEN_INCOME_DIY_NAME : "加速收益分红", self::REWARD_POOL_DIVIDEND => defined('REWARD_POOL_DIVIDEND_DIY_NAME') ? REWARD_POOL_DIVIDEND_DIY_NAME : "奖金池分红", self::STORE_MANAGER => '店补', + self::CULTURAL_SPACE_CONTRIBUTION_BONUS => '贡献值分红', ]; if (empty($income_config_desc[$code])) { if ($func = app('ShopAsset')->getData('income')[$code]) { @@ -877,6 +879,7 @@ class IncomeService self::QUICKEN_INCOME_REWARD => 'Yunshop\QuickenIncome\models\EquityDetailModel', self::REWARD_POOL_DIVIDEND => 'Yunshop\RewardPoolDividend\common\models\DividendUpgradeRecord', self::STORE_MANAGER => 'Yunshop\TeamDividend\Common\models\StoreManagerRecordModel', + self::CULTURAL_SPACE_CONTRIBUTION_BONUS => 'Yunshop\CulturalSpace\models\ContributionBonusLog' ]; if (empty($income_config_class[$code])) { if ($func = app('ShopAsset')->getData('income')[$code]) { diff --git a/plugins/cultural-space/src/PluginApplication.php b/plugins/cultural-space/src/PluginApplication.php index 24dedd40..a715c300 100644 --- a/plugins/cultural-space/src/PluginApplication.php +++ b/plugins/cultural-space/src/PluginApplication.php @@ -4,6 +4,7 @@ namespace Yunshop\CulturalSpace; use Yunshop\CulturalSpace\listener\OrderPaidListener; +use Yunshop\CulturalSpace\models\ContributionBonusLog; class PluginApplication extends \app\common\services\PluginApplication{ @@ -146,6 +147,17 @@ class PluginApplication extends \app\common\services\PluginApplication{ ); } + public function getIncomeItems(){ + return [ + 'contributionBonus' => [ + 'title' => '贡献值分红', + 'type' => 'contributionBonus', + 'type_name' => '贡献值分红', + 'class' => 'Yunshop\CulturalSpace\models\ContributionBonusLog', + ] + ]; + } + public function boot(){ $events = app('events'); @@ -154,12 +166,24 @@ class PluginApplication extends \app\common\services\PluginApplication{ - - - - - - } + public function cronConfig(){ + \Event::listen('cron.collectJobs', function () { + // 每天0点30 执行一次贡献值分红处理 + \Cron::add('cultural-space-contribution-bonus', '30 0 * * *', function () { + \Log::debug('--- 文创空间 - 贡献值分红 - 开始 ----'); + (new ContributionBonusLog())->bonusInit(); + return; + }); + // 每天1点30 执行一次贡献值分红结算 + \Cron::add('cultural-space-contribution-bonus-settlement', '30 1 * * *', function () { + \Log::debug('--- 文创空间 - 贡献值分红 - 结算开始 ----'); + (new ContributionBonusLog())->contributionBonusSettlement(); + return; + }); + }); + } + + } \ No newline at end of file diff --git a/plugins/cultural-space/src/admin/IndexController.php b/plugins/cultural-space/src/admin/IndexController.php index c1f565ea..658ffc53 100644 --- a/plugins/cultural-space/src/admin/IndexController.php +++ b/plugins/cultural-space/src/admin/IndexController.php @@ -3,6 +3,7 @@ namespace Yunshop\CulturalSpace\admin; use app\common\components\BaseController; use app\common\facades\Setting; +use Yunshop\CulturalSpace\models\ContributionBonusLog; class IndexController extends BaseController{ @@ -42,10 +43,8 @@ class IndexController extends BaseController{ public function test(){ // (new CulturalSpace())->buyGoodsGiveContribution(19,76);// 订单支付成功奖励贡献值 - - - - + // (new ContributionBonusLog())->bonusInit(); + // (new ContributionBonusLog())->contributionBonusSettlement(); } diff --git a/plugins/cultural-space/src/models/ContributionBonus.php b/plugins/cultural-space/src/models/ContributionBonus.php new file mode 100644 index 00000000..a011bc99 --- /dev/null +++ b/plugins/cultural-space/src/models/ContributionBonus.php @@ -0,0 +1,26 @@ + 'datetime:Y-m-d H:i:s', + ]; + protected $fillable = ['uniacid','uid','order_total_money','contribution_bonus_ratio','total_money','start_time','end_time','created_at']; + + + + + +} diff --git a/plugins/cultural-space/src/models/ContributionBonusLog.php b/plugins/cultural-space/src/models/ContributionBonusLog.php new file mode 100644 index 00000000..984e2960 --- /dev/null +++ b/plugins/cultural-space/src/models/ContributionBonusLog.php @@ -0,0 +1,311 @@ + 'datetime:Y-m-d H:i:s', + ]; + protected $fillable = ['uniacid','uid','total_money','money','total_contribution','hold_contribution','proportion','created_at']; + + // 贡献值分红相关内容 + private $orderTotalMoney = 0;// 周期订单总金额 + private $bonusTotalMoney = 0;// 分红总销售额(周期订单总金额的N%) + + + /** + * Common: 贡献值分红 - 分红处理开始 + * Author: wu-hui + * Time: 2023/11/03 15:09 + */ + public function bonusInit(){ + set_time_limit(0); + DB::beginTransaction(); + try{ + [$startTime,$endTime] = getTimeStamp('yesterday'); + // 循环平台 进行处理 + $uniAccount = UniAccount::getEnable() ?: []; + foreach ($uniAccount as $u) { + Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid; + $set = Setting::get('plugin.cultural_space_set'); + // 判断:是否符合执行条件 + $isRun = (boolean)$this->isRun($set,$startTime,$endTime); + // 判断:允许下一步 + if ($isRun) $this->bonusHandle($set,$startTime,$endTime); + } + + \Log::debug('--- 文创空间 - 贡献值分红 - 结束 end----'); + DB::commit(); + }catch(\Exception $e){ + \Log::debug('--- 文创空间 - 贡献值分红 - 错误:'.$e->getMessage()); + DB::rollBack(); + } + } + /** + * Common: 贡献值分红 - 判断是否允许继续执行 + * Author: wu-hui + * Time: 2023/11/03 13:43 + * @param $set + * @param $startTime + * @param $endTime + * @return bool + */ + private function isRun($set,$startTime,$endTime){ + $time = time(); + // 判断:时间上是否允许继续执行(上一个周期结束时间存在 & 当前时间小于下一个周期开始时间 禁止继续执行) + $upCycleEndTime = ContributionBonus::uniacid()->max('end_time'); + $lastRunTime = strtotime(date("Y-m-d H:i:s",$upCycleEndTime)." +1 day");// 下一个周期结束时间 + if($upCycleEndTime > 0 && $time < $lastRunTime) { + \Log::debug("执行时间错误(上一个周期结束时间{$upCycleEndTime},下一个周期结束时间{$lastRunTime})",\YunShop::app()->uniacid); + return false; + } + // 判断:设置是否允许执行 未开启贡献值 || 分红总额比例为0或未设置 + if((int)$set['is_give_contribution'] != 1 || (float)$set['contribution_bonus_ratio'] <= 0) { + \Log::debug("未开启贡献值或者分红总额比例为0或未设置",\YunShop::app()->uniacid); + return false; + } + // 判断:是否存在分红总金额 + $this->orderTotalMoney = (float)Order::uniacid() + ->where('pay_time','>=',$startTime) + ->where('pay_time','<',$endTime) + ->where('price','>',0) + ->whereIn('status',[Order::WAIT_SEND,Order::WAIT_RECEIVE,Order::COMPLETE]) + ->sum('price'); + $this->bonusTotalMoney = (float)sprintf("%.2f",$this->orderTotalMoney * (float)$set['contribution_bonus_ratio'] / 100); + if($this->bonusTotalMoney <= 0) { + \Log::debug("分红总金额为0",\YunShop::app()->uniacid); + return false; + } + + return true; + } + /** + * Common: 贡献值分红 - 处理每个站点所有用户的分红 + * Author: wu-hui + * Time: 2023/11/03 15:09 + * @param $set + * @param $startTime + * @param $endTime + * @return false|void + */ + private function bonusHandle($set,$startTime,$endTime){ + // 获取贡献值信息(截止昨天24时) + $userList = ContributionLog::getAllList($endTime); + $totalContribution = (float)array_sum($userList); + if($totalContribution <= 0){ + \Log::debug("不存在分红用户或截至当前周期结束时间总共的贡献值为0",\YunShop::app()->uniacid); + return false; + } + // 记录周期分红信息 + $culturalSpaceContributionBonusId = ContributionBonus::insertGetId([ + 'uniacid' => \YunShop::app()->uniacid, + 'order_total_money' => $this->orderTotalMoney, + 'contribution_bonus_ratio' => (float)$set['contribution_bonus_ratio'], + 'total_money' => $this->bonusTotalMoney, + 'start_time' => $startTime, + 'end_time' => $endTime, + 'created_at' => time(), + ]); + // 循环处理所有用户 + $logInsertData = [];// 明细记录 + $time = time(); + $uniacid = \YunShop::app()->uniacid; + foreach($userList as $userId => $contributionValue){ + // 添加贡献值分红信息记录 这里必须进行100的偏移计算 + $radio = (float)sprintf("%.2f",$contributionValue / $totalContribution * 100);// 佣金比例 + $money = (float)sprintf("%.2f",$this->bonusTotalMoney * $radio / 100);// 实际获得佣金 + if($money > 0){ + $logInsertData[] = [ + 'uniacid' => $uniacid, + 'uid' => $userId, + 'total_money' => $this->bonusTotalMoney, + 'money' => $money, + 'total_contribution' => $totalContribution, + 'hold_contribution' => $contributionValue, + 'proportion' => $radio, + 'cultural_space_contribution_bonus_id' => $culturalSpaceContributionBonusId, + 'created_at' => $time, + ]; + } + } + + self::insert($logInsertData); + } + /** + * Common: 贡献值分红 - 结算 + * Author: wu-hui + * Time: 2023/11/03 15:24 + */ + public function contributionBonusSettlement(){ + set_time_limit(0); + DB::beginTransaction(); + try{ + // 循环平台 进行处理 + $uniAccount = UniAccount::getEnable() ?: []; + foreach ($uniAccount as $u) { + Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid; + // 获取未结算列表 + $list = self::uniacid() + ->select(['id','uid','money']) + ->where('is_settlement',0) + ->get() + ->toArray(); + if($list){ + // 循环处理数据 + $incomeData = []; + foreach($list as $item){ + $incomeData[] = [ + 'uniacid' => \YunShop::app()->uniacid, + 'member_id' => $item['uid'], + 'amount' => $item['money'], + 'detail' => '', + 'dividend_table_id' => $item['id'], + 'dividend_code' => IncomeService::CULTURAL_SPACE_CONTRIBUTION_BONUS, + 'order_sn' => '', + ]; + } + IncomeService::insertIncome($incomeData); + // 修改为已经结算 + $ids = array_column($list,'id'); + self::whereIn('id',$ids)->update([ + 'is_settlement' => 1 + ]); + } + } + DB::commit(); + }catch(\Exception $e){ + \Log::debug('--- 文创空间 - 贡献值分红结算 - 错误:'.$e->getMessage()); + DB::rollBack(); + } + } + + + + + + + + + + + /** + * Common: 店长信息统计 - 初始化 + * Author: wu-hui + * Time: 2023/09/18 14:46 + */ + public function infoStatistics(){ + set_time_limit(0); + try{ + // 循环平台 进行处理 + $uniAccount = UniAccount::getEnable() ?: []; + foreach ($uniAccount as $u) { + Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid; + $set = Setting::get('plugin.team_dividend'); + $isRun = (boolean)$this->isRun($set); + // 判断:允许下一步 开启店长 店补比例大于0 + if ($isRun && (int)$set['store_manager_switch'] == 1 && (float)$set['store_manager_proportion'] > 0) { + \Log::debug('--- 经销商 - 店长统计 - 满足条件,开始处理:'.$u->uniacid); + $this->infoStatisticsHandle($set); + } else { + \Log::debug('--- 经销商 - 店长统计 - 不满足条件:'.$u->uniacid); + } + } + }catch(\Exception $e){ + \Log::debug('--- 经销商 - 店长统计 - 错误:'.$e->getMessage()); + } + } + /** + * Common: 店长信息统计 - 开始处理 + * Author: wu-hui + * Time: 2023/09/18 14:03 + * @param $set + */ + public function infoStatisticsHandle($set){ + // 获取所有店长 + $storeManagerList = self::uniacid() + ->select(['id','uid']) + ->where('status',1) + ->orderBy('id','DESC') + ->get(); + if(!$storeManagerList){ + \Log::debug('--- 经销商 - 店长统计 - 没有店长信息'); + return; + } + // 订单查询条件 + $storeManagerCycle = $set['store_manager_cycle'] ?? 'last_month'; + [$startTime,$endTime] = getTimeStamp($storeManagerCycle); + $where = [ + ['yz_order.pay_time','>=',$startTime], + ['yz_order.pay_time','<',$endTime], + ['yz_order_goods.payment_amount','>',0],// 实际支付金额必须大于0 + ]; + // 循环处理店长 + $storeIds = array_column($storeManagerList->toArray(),'uid'); + $insertData = []; + $time = time(); + foreach($storeManagerList as $storeInfo){ + // 获取全部有效下级 + $validChild = $this->getValidChild($storeInfo->uid,$storeIds); + $validChild[] = $storeInfo->uid;// 包括本人 + // 获取团队全部订单,这里以订单商品的实际支付价格算;统计已支付-待发货,已支付-待收货,已完成订单 + $totalMoney = (float)OrderGoods::uniacid() + ->join('yz_order', 'yz_order_goods.order_id', '=','yz_order.id') + ->where($where) + ->whereIn('yz_order.status',[Order::WAIT_SEND,Order::WAIT_RECEIVE,Order::COMPLETE]) + ->whereIn('yz_order.uid',$validChild) + ->sum('yz_order_goods.payment_amount'); + $insertData[] = [ + 'uniacid' => \YunShop::app()->uniacid, + 'uid' => $storeInfo->uid, + 'total_money' => $totalMoney, + 'money' => sprintf("%.2f",$totalMoney * (float)$set['store_manager_proportion'] / 100), + 'proportion' => (float)$set['store_manager_proportion'], + 'start_time' => $startTime, + 'end_time' => $endTime, + 'created_at' => $time, + ]; + } + // 添加记录 + StoreManagerRecordModel::insert($insertData); + + return; + } + /** + * Common: 店长信息统计 - 获取店长全部有效下级(去除店长及其团队的全部下级) + * Author: wu-hui + * Time: 2023/09/18 13:34 + * @param $uid + * @param $storeIds + * @return array + */ + public function getValidChild($uid,$storeIds){ + $allChild = MemberChild::uniacid()->where('member_id',$uid)->pluck('child_id')->toArray(); + $diff = array_values(array_intersect($allChild,$storeIds));// 获取交集 判断下级中是否存在店长 + if(count($diff) > 0){ + // 下级中存在店长 进行处理,剔除所有店长及其团队成员 + $subAllChild = MemberChild::uniacid()->whereIn('member_id',$diff)->pluck('child_id')->toArray(); + $delIds = array_values(array_merge($diff,$subAllChild)); + $allChild = array_diff($allChild,$delIds); + } + + return $allChild; + } + + + + + + +} diff --git a/plugins/cultural-space/src/models/ContributionLog.php b/plugins/cultural-space/src/models/ContributionLog.php index abea4d9d..1ecb7cbd 100644 --- a/plugins/cultural-space/src/models/ContributionLog.php +++ b/plugins/cultural-space/src/models/ContributionLog.php @@ -4,13 +4,14 @@ namespace Yunshop\CulturalSpace\models; use app\common\models\BaseModel; use app\common\models\Member; +use Illuminate\Support\Facades\DB; class ContributionLog extends BaseModel{ public $table = 'yz_cultural_space_contribution_log'; public $timestamps = false; public $casts = [ - 'created_at' => 'datetime:Y-m-d h:i:s' + 'created_at' => 'datetime:Y-m-d H:i:s' ]; protected $fillable = [ 'uniacid', @@ -56,7 +57,29 @@ class ContributionLog extends BaseModel{ return $list ? $list->toArray() : []; } + /** + * Common: 根据截至时间 获取全部用户持有的贡献值 + * Author: wu-hui + * Time: 2023/11/03 14:13 + * @param $endTime + * @return array|false|null + */ + public static function getAllList($endTime){ + $idList = self::uniacid() + ->select([DB::raw('max(id) as max_id')]) + ->where('created_at','<=',$endTime) + ->groupBy('uid') + ->get() + ->toArray(); + $ids = array_column($idList,'max_id'); + $list = self::uniacid() + ->select(['uid','change_after']) + ->whereIn('id',$ids) + ->get() + ->toArray(); + return array_column($list,'change_after','uid'); + } diff --git a/plugins/cultural-space/views/index/set.blade.php b/plugins/cultural-space/views/index/set.blade.php index 4b3db2a1..986829be 100644 --- a/plugins/cultural-space/views/index/set.blade.php +++ b/plugins/cultural-space/views/index/set.blade.php @@ -35,14 +35,18 @@
订单实际支付的N%奖励给用户及直推上级,作为贡献值。0或者空则无贡献值奖励
- - + +
周期销售额的N%用作分红总金额,根据每个人当前贡献值比例进行分红;0或者空则无贡献值奖励
+ + + + {{--保存按钮--}} 保存 @@ -59,6 +63,7 @@ return{ set: JSON.parse('{!! json_encode($set) !!}') || { is_give_contribution: 0, + is_open_contribution_bonus: 0, }, } }, diff --git a/plugins/weight-value/src/models/WeightValueLog.php b/plugins/weight-value/src/models/WeightValueLog.php index b91ef5d4..016b75d5 100644 --- a/plugins/weight-value/src/models/WeightValueLog.php +++ b/plugins/weight-value/src/models/WeightValueLog.php @@ -10,7 +10,7 @@ class WeightValueLog extends BaseModel{ public $timestamps = false; public $table = 'yz_weight_value_log'; public $casts = [ - 'created_at' => 'datetime:Y-m-d h:i:s' + 'created_at' => 'datetime:Y-m-d H:i:s' ]; protected $fillable = [ 'uniacid',