瀏覽代碼

Merge branch 'stable' into liuzj-1000967-dev

liuzejian 1 年之前
父節點
當前提交
cd693c32e7

+ 1 - 1
modules/Channel/Http/Controllers/AdvertiserController.php

@@ -138,7 +138,7 @@ class AdvertiserController extends CatchController
             'miniProgramIds' => 'required|array|min:1',
             'miniProgramIds.*' => 'required|integer',
             'status' => 'required|in:1,2',
-            'remark' => 'string|max:140',
+            'remark' => 'nullable|string|max:140',
         ]);
         $uid = $request->input('id');
         $user = DB::table('users')

+ 74 - 23
modules/Channel/Http/Controllers/PayTemplateController.php

@@ -3,23 +3,24 @@
 namespace Modules\Channel\Http\Controllers;
 
 use Carbon\Carbon;
-use Illuminate\Http\Request;
 use Catch\Base\CatchController;
-use Modules\Common\Errors\Errors;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Modules\Channel\Exceptions\ChannelBusinessException;
 use Modules\Channel\Models\PayProduct;
 use Modules\Channel\Models\PayTemplate;
 use Modules\Channel\Models\PayTemplateItem;
-use Modules\Channel\Exceptions\ChannelBusinessException;
 use Modules\Channel\Services\User\UserService;
+use Modules\Common\Errors\Errors;
 
 class PayTemplateController extends CatchController
 {
+    use ValidatesRequests;
     public function __construct(protected readonly PayTemplate $payTemplate,protected readonly PayTemplateItem $payTemplateItem,protected readonly PayProduct $payProduct)
     {
 
     }
-
-
     private $sequence_map = [
         '','位置一','位置二','位置三','位置四','位置五','位置六','位置七','位置八'
     ];
@@ -36,16 +37,60 @@ class PayTemplateController extends CatchController
         if(UserService::userHasRole($uid,'administrator')){
             $uid = 0;
         }
+        if($uid) {
+            $this->initPayTemplate($uid);
+        }
         $name = $request->get('name');
-        $where = [[
-            'uid','=',$uid
-        ]];
+        // 1-首充模板,2-非首充模板
+        $type = $request->input('type');
+        $where = [['uid','=',$uid,], ['type', '=', $type,]];
         if($name){
             $where[] = ['name','like','%'.$name.'%'];
         }
-        return $this->payTemplate->orderBy('id','desc')->where($where)->paginate(20);
+        $result = $this->payTemplate->orderBy('id','desc')->where($where)->paginate($request->input('limit', 20));
+        foreach ($result as $item) {
+            $item->status_str = $item->status ? '默认模板': '非默认模板';
+            $item->type_str = 1 == $item->type ? '首充模板' : '非首充模板';
+        }
+
+        return $result;
     }
 
+    /**
+     * 如果优化是没有设置充值模板,那么就是用官方模板进行初始化
+     * @param $uid
+     */
+    private function initPayTemplate($uid) {
+        if(!$this->payTemplate->where('uid', $uid)->count()) {
+            $systemPayTemplates = $this->payTemplate->where('uid', 0)->get();
+            $now = date('Y-m-d H:i:s');
+            foreach ($systemPayTemplates as $systemPayTemplate) {
+                $payTemplate = $this->payTemplate->create([
+                    'uid' => $uid,
+                    'name' => $systemPayTemplate->name,
+                    'status' => $systemPayTemplate->status,
+                    'type' => $systemPayTemplate->type,
+                ]);
+                $payTemplateItems = $this->payTemplateItem->where([
+                    'pay_template_id' => $systemPayTemplate->id, 'status' => 1,
+                ])->get();
+                $payTemplateItemDatas = [];
+
+                foreach ($payTemplateItems as $item) {
+                    $payTemplateItemDatas[] = [
+                        'pay_template_id' => $payTemplate->id,
+                        'pay_product_id' => $item->pay_product_id,
+                        'is_default' => $item->is_default,
+                        'status' => $item->status,
+                        'sequence' => $item->sequence,
+                        'created_at' => $now,
+                        'updated_at' => $now,
+                    ];
+                }
+                $this->payTemplateItem->insert($payTemplateItemDatas);
+            }
+        }
+    }
 
     /**
      * 添加模板
@@ -55,21 +100,24 @@ class PayTemplateController extends CatchController
      */
     public function store(Request $request)
     {
+        $this->validate($request, [
+            'name' => 'required',
+            'options' => 'required',
+            'status' => 'required|in:0,1',
+            'type' => 'required|in:1,2'
+        ]);
         $uid = $this->getLoginUser()->id;
         $name = $request->post('name');
+        // 0-非默认模板,1-默认模板
         $status = $request->post('status');
         $options = $request->post('options');
-        if(empty($name) || empty($options)){
-            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
-        }
+        // 1-首充模板,2-非首充模板
+        $type = $request->input('type');
+
         if(UserService::userHasRole($uid,'administrator')){
             $uid = 0;
         }
 
-        $exists = $this->payTemplate->where('uid',$uid)->where('name',$name)->count();
-        if($exists){
-            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_EXISTS_ERROR);
-        }
         $option_list = json_decode($options,1);
         $data = [];
         $default_optioin = 0;
@@ -102,11 +150,14 @@ class PayTemplateController extends CatchController
 
         $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
 
-        if($status == 1){
-            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
+        if($status == 1 && 0 == $uid){
+            $this->payTemplate->where([
+                'uid' => $uid, 'type' => $type
+            ])->update(['status'=>0]);
         }
 
-        $pay_template_info = $this->payTemplate->create(['name'=>$name,'uid'=>$uid,'status'=>$status]);
+        $pay_template_info = $this->payTemplate->create(['name'=>$name,'uid'=>$uid,
+            'type' => $type, 'status' => $status]);
 
         foreach($option_list as $option){
             $type = $option['type'];
@@ -133,8 +184,7 @@ class PayTemplateController extends CatchController
      */
     public function show($id)
     {
-        //$uid = $this->getLoginUser()->id;
-        $uid= 1;
+        $uid = $this->getLoginUser()->id;
         if(UserService::userHasRole($uid,'administrator')){
             $uid = 0;
         }
@@ -185,6 +235,8 @@ class PayTemplateController extends CatchController
         $name = $request->post('name');
         $status = $request->post('status',-1);
         $options = $request->post('options');
+        // 1-首充模板,2-非首充模板
+        $type = $request->input('type');
         $uid = $this->getLoginUser()->id;
         if(UserService::userHasRole($uid,'administrator')){
             $uid = 0;
@@ -204,7 +256,7 @@ class PayTemplateController extends CatchController
         }
 
         if($status == 1){
-            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
+            $this->payTemplate->where('uid',$uid)->where('type', $type)->update(['status'=>0]);
             $this->payTemplate->where('id',$id)->update(['status'=>1]);
         }
         if($template_info_update){
@@ -381,7 +433,6 @@ class PayTemplateController extends CatchController
     public function optionTypeList(){
         return [
             ['name'=>'普通充值','value'=>'COIN'],
-            ['name'=>'首充','value'=>'FIRST_COIN'],
             ['name'=>'包月','value'=>'MONTH'],
             ['name'=>'包季','value'=>'QUARTER'],
             ['name'=>'包年','value'=>'YEAR']

+ 1 - 1
modules/Channel/Models/PayTemplate.php

@@ -8,7 +8,7 @@ class PayTemplate extends BaseModel
     protected $table = 'pay_templates';
 
     protected $fillable = [
-        'id', 'name', 'uid','status', 'created_at', 'updated_at',
+        'id', 'name', 'uid','status', 'created_at', 'updated_at','type'
     ];
 
 }

+ 1 - 0
modules/Common/Errors/Errors.php

@@ -33,4 +33,5 @@ class Errors
     public const REQUEST_HTTP_STATUS_ERROR = [500401, '请求上游接口返回http状态码有误'];
     public const REQUEST_CODE_STATUS_ERROR = [500402, '请求上游接口返回code状态码有误'];
     public const SYNC_WECHAT_NOT_OK = [500302, '剧集没有成功同步到微信'];
+    public const  MINIPROGRAM_OWNER_ACCOUNT_ROLE_ERROR= [5000501, '所分配的账号不是投放公司账号'];
 }

+ 116 - 69
modules/Manage/Http/Controllers/MiniprogramController.php

@@ -22,7 +22,8 @@ class MiniprogramController extends CatchController
 {
 
     use UserTrait;
-    public function __construct(protected readonly Miniprogram $miniprogram,protected readonly UserHasMiniprograms $userHasMiniprograms)
+
+    public function __construct(protected readonly Miniprogram $miniprogram, protected readonly UserHasMiniprograms $userHasMiniprograms)
     {
 
     }
@@ -45,34 +46,34 @@ class MiniprogramController extends CatchController
         $type = $request->get('type');
         $page_size = $request->input('limit', 15);
         $where = [];
-        if($name){
-            $where[] = ['name','like','%'.$name.'%'];
+        if ($name) {
+            $where[] = ['name', 'like', '%' . $name . '%'];
         }
-        if($play_name){
-            $where[] = ['play_name','like','%'.$play_name.'%'];
+        if ($play_name) {
+            $where[] = ['play_name', 'like', '%' . $play_name . '%'];
         }
-        if($company){
-            $where[] = ['company','like','%'.$company.'%'];
+        if ($company) {
+            $where[] = ['company', 'like', '%' . $company . '%'];
         }
 
-        if($type){
-            $where[] = ['type','=',$type];
+        if ($type) {
+            $where[] = ['type', '=', $type];
         }
-        if(UserService::userHasRole($uid,'administrator')){
-            $result = $this->miniprogram->where($where)->orderBy('id','desc')->paginate($page_size);
-        }else{
-            $result = $this->userHasMiniprograms->join('miniprogram','miniprogram.id','=','user_has_miniprograms.miniprogram_id')
-            ->where('user_has_miniprograms.is_enabled',1)
-            ->where('uid',$uid)
-            ->where($where)
-            ->select('miniprogram.*')
-            ->paginate($page_size);
+        if (UserService::userHasRole($uid, 'administrator')) {
+            $result = $this->miniprogram->where($where)->orderBy('id', 'desc')->paginate($page_size);
+        } else {
+            $result = $this->userHasMiniprograms->join('miniprogram', 'miniprogram.id', '=', 'user_has_miniprograms.miniprogram_id')
+                ->where('user_has_miniprograms.is_enabled', 1)
+                ->where('uid', $uid)
+                ->where($where)
+                ->select('miniprogram.*')
+                ->paginate($page_size);
         }
 
-        foreach($result as $item){
+        foreach ($result as $item) {
             $item->type_name = MiniprogramType::from($item->type)->name();
-            $item->status_name = $item->status == 1 ?'启用':'禁用';
-            $item->pay_merchant_name = getProp($item->pay_merchant_info,'name','-');
+            $item->status_name = $item->status == 1 ? '启用' : '禁用';
+            $item->pay_merchant_name = getProp($item->pay_merchant_info, 'name', '-');
             unset($item->pay_merchant_info);
         }
         return $result;
@@ -87,14 +88,14 @@ class MiniprogramController extends CatchController
     public function store(MiniprogramRequest $request)
     {
         $validate_result = $request->validated();
-        $validate_result['remark'] = $request->post('remark','') ?? '';
-        $validate_result['pay_merchant_id'] = $request->post('pay_merchant_id',0);
-        if (getProp($validate_result,'pay_merchant_id',0)){
-            $info = DB::table('pay_merchants')->where('id',$validate_result['pay_merchant_id'])->first();
-            if (empty($info)){
+        $validate_result['remark'] = $request->post('remark', '') ?? '';
+        $validate_result['pay_merchant_id'] = $request->post('pay_merchant_id', 0);
+        if (getProp($validate_result, 'pay_merchant_id', 0)) {
+            $info = DB::table('pay_merchants')->where('id', $validate_result['pay_merchant_id'])->first();
+            if (empty($info)) {
                 throw  new  FailedException("支付方式不存在");
             }
-            if ($info->miniprogram_type != $validate_result['type']){
+            if ($info->miniprogram_type != $validate_result['type']) {
                 throw  new  FailedException("小程序类型和支付的小程序类型不匹配");
             }
             $validate_result['pay_merchant_info'] = [
@@ -106,7 +107,7 @@ class MiniprogramController extends CatchController
                 'pay_appid' => $info->pay_appid,
             ];
 
-        }else{
+        } else {
             $validate_result['pay_merchant_id'] = 0;
             $validate_result['pay_merchant_info'] = [];
         }
@@ -136,15 +137,15 @@ class MiniprogramController extends CatchController
     public function update($id, MiniprogramUpdateRequest $request)
     {
         $validate_result = $request->validated();
-        if($request->post('remark','')){
-            $validate_result['remark'] = $request->post('remark','');
+        if ($request->post('remark', '')) {
+            $validate_result['remark'] = $request->post('remark', '');
         }
-        if (getProp($validate_result,'pay_merchant_id',0)){
-            $info = DB::table('pay_merchants')->where('id',$validate_result['pay_merchant_id'])->first();
-            if (empty($info)){
+        if (getProp($validate_result, 'pay_merchant_id', 0)) {
+            $info = DB::table('pay_merchants')->where('id', $validate_result['pay_merchant_id'])->first();
+            if (empty($info)) {
                 throw  new  FailedException("支付方式不存在");
             }
-            if ($info->miniprogram_type != $validate_result['type']){
+            if ($info->miniprogram_type != $validate_result['type']) {
                 throw  new  FailedException("小程序类型和支付的小程序类型不匹配");
             }
             $validate_result['pay_merchant_info'] = [
@@ -156,11 +157,11 @@ class MiniprogramController extends CatchController
                 'pay_appid' => $info->pay_appid,
             ];
 
-        }else{
+        } else {
             $validate_result['pay_merchant_id'] = 0;
             $validate_result['pay_merchant_info'] = [];
         }
-        $this->miniprogram->where('id',$id)->update($validate_result);
+        $this->miniprogram->where('id', $id)->update($validate_result);
         return [];
     }
 
@@ -170,9 +171,10 @@ class MiniprogramController extends CatchController
      *
      * @return array [ ['name'=>'微信小程序','id'=>1],[],[] ]
      */
-    public function typeList(){
-        $type_list =  MiniprogramType::cases();
-        $data = array_map( fn($item)=>['name'=>$item->name(),'value'=>$item->value()],$type_list );
+    public function typeList()
+    {
+        $type_list = MiniprogramType::cases();
+        $data = array_map(fn($item) => ['name' => $item->name(), 'value' => $item->value()], $type_list);
         return $data;
     }
 
@@ -182,66 +184,110 @@ class MiniprogramController extends CatchController
      *
      * @return void
      */
-    public function companyList(){
+    public function companyList()
+    {
         return $this->miniprogram->select(DB::raw('distinct company'))->get()->pluck('company');
     }
 
 
-
     /**
      * 绑定小程序和投放公司的关系 或者投放公司把小程序分配给优化师
      * @param [type] $miniprogram_id
-     * @param Request $request  uid=2,3,4,5 actison=on|off on:分配,off取消分配
+     * @param Request $request uid=2,3,4,5 actison=on|off on:分配,off取消分配
      * @return array
      *
      */
-    public function allocationStore($miniprogram_id,Request $request)
+    public function allocationStore($miniprogram_id, Request $request)
     {
         $uid = $this->getLoginUser()->id;
-        if(!UserService::userHasRoles($uid,[self::COMPANY_ROLE,self::ADMINISTRATOR_ROLE])){
+        if (!UserService::userHasRoles($uid, [self::COMPANY_ROLE, self::ADMINISTRATOR_ROLE])) {
             ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
         }
         $uids = $request->post('uids');
         $action = $request->post('action');
-        if(empty($miniprogram_id) || empty($uids) || empty($action) || !in_array($action,['on','off'])){
+        if (empty($miniprogram_id) || empty($uids) || empty($action) || !in_array($action, ['on', 'off'])) {
             ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
         }
 
-        $miniprogram_info =  $this->miniprogram->find($miniprogram_id);
-        if(!$miniprogram_info || $miniprogram_info->status == 0){
+        $miniprogram_info = $this->miniprogram->find($miniprogram_id);
+        if (!$miniprogram_info || $miniprogram_info->status == 0) {
             ChannelBusinessException::throwError(Errors::MINIPROGRAM_STATUS_ERROR);
         }
+        $userContext = $this->getUserContext(null);
+        if ($userContext['loginUserRoles']->contains(self::COMPANY_ROLE)) {
+            // 公司给投手分配小程序
+            return $this->allocationStoreCompany($miniprogram_id, $uids, $action);
+        } else {
+            $companyId = explode(',', $uids)[0] ?: 0;
+            if (empty($companyId)) {
+                ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
+            }
+            if (!UserService::userHasRoles($companyId, [self::COMPANY_ROLE])) {
+                ChannelBusinessException::throwError(Errors::MINIPROGRAM_OWNER_ACCOUNT_ROLE_ERROR);
+            }
+
+            // 小程序原拥有公司账号id
+            $ownerCompanyId = DB::table('user_has_miniprograms as up')
+                ->leftJoin('user_has_roles as ur', 'ur.user_id', '=', 'up.uid')
+                ->leftJoin('roles as r', 'r.id', '=', 'ur.role_id')
+                ->where('up.is_enabled', 1)
+                ->where('up.miniprogram_id', $miniprogram_id)
+                ->where('r.identify', 'company')->orderBy('up.id', 'desc')
+                ->value('up.uid');
+            if ($companyId == $ownerCompanyId) {
+                // 相同则不修改
+                return true;
+            }
+            if ($ownerCompanyId > 0) {
+                //  若小程序已经分配给其他公司
+                $this->userHasMiniprograms::where('miniprogram_id', $miniprogram_id)->update(['is_enabled' => 0]);
+            }
+            $result = $this->userHasMiniprograms->where('uid', $companyId)->where('miniprogram_id', $miniprogram_id)->first();
+            if ($result) {
+                if ($result->is_enabled == 0) {
+                    $result->is_enabled = 1;
+                    $result->save();
+                }
+                return true;
+            }
+            $this->userHasMiniprograms->create([
+                'uid' => $companyId, 'miniprogram_id' => $miniprogram_id, 'is_enabled' => 1
+            ]);
+            return true;
+        }
+
+    }
 
-        return collect(explode(',',$uids))->filter(function (int $value, int $key) use($miniprogram_id,$action){
-            $user_access = UserService::userHasRoles($value,[self::COMPANY_ROLE,self::OPTIMIZER_ROLE]);
+    protected function allocationStoreCompany($miniprogram_id, $uids, $action)
+    {
+        return collect(explode(',', $uids))->filter(function (int $value, int $key) use ($miniprogram_id, $action) {
+            $user_access = UserService::userHasRoles($value, [self::COMPANY_ROLE, self::OPTIMIZER_ROLE]);
             //只能分配给投手公司或者优化师
-            if($user_access){
-                $result = $this->userHasMiniprograms->where('uid',$value)->where('miniprogram_id',$miniprogram_id)->first();
-                if($action == 'off'){
-                    if($result){
+            if ($user_access) {
+                $result = $this->userHasMiniprograms->where('uid', $value)->where('miniprogram_id', $miniprogram_id)->first();
+                if ($action == 'off') {
+                    if ($result) {
                         $result->is_enabled = 0;
                         $result->save();
                     }
                     return true;
                 }
-                if($result){
-                    if($result->is_enabled == 0){
+                if ($result) {
+                    if ($result->is_enabled == 0) {
                         $result->is_enabled = 1;
                         $result->save();
                     }
                     return true;
                 }
                 $this->userHasMiniprograms->create([
-                    'uid'=>$value,'miniprogram_id'=>$miniprogram_id,'is_enabled'=>1
+                    'uid' => $value, 'miniprogram_id' => $miniprogram_id, 'is_enabled' => 1
                 ]);
                 return true;
             }
             return false;
         });
-
     }
 
-
     /**
      * 获取投手公司和小程序的绑定关系,用于前端数据回显
      * @param [type] $miniprogram_id
@@ -256,30 +302,31 @@ class MiniprogramController extends CatchController
      *      ]
      *
      */
-    public function getAllocationInfo($miniprogram_id){
+    public function getAllocationInfo($miniprogram_id)
+    {
         $uid = $this->getLoginUser()->id;
-        if(UserService::userHasRole($uid,self::ADMINISTRATOR_ROLE)){
-            $all_company_account = UserService::listByRole(self::COMPANY_ROLE,['users.username','users.id']);
-        }else{
-            $all_company_account = UserService::getOptimizers($uid,['users.username','users.id']);
+        if (UserService::userHasRole($uid, self::ADMINISTRATOR_ROLE)) {
+            $all_company_account = UserService::listByRole(self::COMPANY_ROLE, ['users.username', 'users.id']);
+        } else {
+            $all_company_account = UserService::getOptimizers($uid, ['users.username', 'users.id']);
         }
 
-        $result = $all_company_account->map(function ($item,$key) use($miniprogram_id) {
-            $info = $this->userHasMiniprograms->where('uid',$item->id)->where('miniprogram_id',$miniprogram_id)->where('is_enabled',1)->count();
-            if($info){
+        $result = $all_company_account->map(function ($item, $key) use ($miniprogram_id) {
+            $info = $this->userHasMiniprograms->where('uid', $item->id)->where('miniprogram_id', $miniprogram_id)->where('is_enabled', 1)->count();
+            if ($info) {
                 $item->user_has_miniprogram = 1;
                 $item->user_has_miniprogram_flag = 'on';
-            }else{
+            } else {
                 $item->user_has_miniprogram = 0;
                 $item->user_has_miniprogram_flag = 'off';
             }
             return $item;
         });
         $group = $result->groupBy('user_has_miniprogram_flag')->toArray();
-        if(!isset($group['on'])){
+        if (!isset($group['on'])) {
             $group['on'] = [];
         }
-        if(!isset($group['off'])){
+        if (!isset($group['off'])) {
             $group['off'] = [];
         }
         $group['all'] = $result->toArray();

+ 1 - 1
modules/Operation/Service/ChannelServic.php

@@ -30,7 +30,7 @@ class ChannelServic extends BaseService
             foreach ($list as  $value){
                 $value->type_txt = $type[$value->type]['name'] ?? "-";
                 $value->miniprogram_type_text = $minParamType[$value->miniprogram_type]['name'] ?? "-";
-                $value->duanjus = collect($value->duanjus)->sortBy('sort');
+                $value->duanjus = collect($value->duanjus)->sortBy('sort')->toArray();
             }
         }
         return $list;

+ 46 - 0
modules/Statistic/Http/Controllers/UserStatisticsController.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ *
+ * @file:UserStatisticsController.php
+ * @Date: 2023/6/20
+ * @Time: 09:29
+ */
+
+
+namespace Modules\Statistic\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Catch\Exceptions\FailedException;
+use Illuminate\Http\Request;
+
+use Modules\Statistic\Services\UserStatisticsService;
+use Modules\User\Http\Controllers\UserTrait;
+
+class UserStatisticsController extends CatchController
+{
+
+    use  UserTrait;
+    /**
+     *  获取当日数据
+     * name: todayData
+     * date 2023/06/20 09:45
+     */
+    public function todayData(Request $request)
+    {
+        $miniProgramId = $request->input('miniprogram_id',0);
+        if ($miniProgramId < 1){
+            throw new FailedException("参数错误,小程序id必传");
+        }
+        $userContext = $this->getUserContext(null);
+        $type = 1;
+        if( $userContext['loginUserRoles']->contains('company')){
+            $type = 2;
+        }else if ($userContext['loginUserRoles']->contains('optimizer')){
+            $type = 3;
+        }
+        $uid = $this->getLoginUserId();
+        return UserStatisticsService::getTodayData($uid,$miniProgramId,$type);
+    }
+
+
+}

+ 126 - 0
modules/Statistic/Services/UserStatisticsService.php

@@ -0,0 +1,126 @@
+<?php
+/**
+ *
+ * @file:UserStatisticsService.php
+ * @Date: 2023/6/20
+ * @Time: 09:31
+ */
+
+
+namespace Modules\Statistic\Services;
+
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+use Modules\Common\Services\BaseService;
+use Modules\User\Http\Controllers\UserTrait;
+
+class UserStatisticsService extends BaseService
+{
+
+    // 日期:小程序id
+    protected const PROMOTION_STATISTIC_RECORD_REDIS_KEY = 'statistic:miniprogram:users_recode:%s:%s';
+    protected const NEW_USER_NUM = 'new_user_num_%s'; // 当日新增用户数
+    protected const NEW_USER_RECHARGE_NUM = "new_user_recharge_num_%s"; // 当日新增户充值人数
+    protected const NEW_USER_RECHARGE_TOTAL = "new_user_recharge_total_%s"; // 当日新增户充值金额
+
+    /**
+     *
+     * name: getTodayData
+     * @param int $accountId 账号id
+     * @param int $miniProgramId 小程序id
+     * @param int $type 账号类型 1 其他 2 投放公司 3 优化师
+     * date 2023/06/20 10:20
+     */
+    public static function getTodayData($accountId, $miniProgramId, $type = 1)
+    {
+        $date = date("Y-m-d");
+        // $date = '2023-05-31';
+        $key = sprintf(self::PROMOTION_STATISTIC_RECORD_REDIS_KEY, $date, $miniProgramId);
+        $new_user_recharge_total = self::getValue($key, sprintf(self::NEW_USER_RECHARGE_TOTAL, $accountId)); // 当日新增用户充值总额
+        $new_user_recharge_num = self::getValue($key, sprintf(self::NEW_USER_RECHARGE_NUM, $accountId)); // 当日新增用户充值人数
+        $new_user_num = self::getValue($key, sprintf(self::NEW_USER_NUM, $accountId)); // 当日新增用户人数
+        [$recharge_coin_num, $recharge_vip_num] = self::getRechargeUserNum($accountId, $miniProgramId, $type);
+        $data = [
+            'key' => $key,
+            'account_id' =>  $accountId,
+            'date' => $date,
+            'new_user_recharge_total' => $new_user_recharge_total ?: 0,
+            'new_user_recharge_num' => $new_user_recharge_num ?: 0,
+            'new_user_num' => $new_user_num ?: 0,
+            'recharge_coin_num' => $recharge_coin_num ?: 0,
+            'recharge_vip_num' => $recharge_vip_num ?: 0,
+        ];
+  
+        if ($new_user_num > 0 && $new_user_recharge_num > 0) {
+            $data['recharge_rate'] = sprintf('%.2f%', ($new_user_recharge_num / $new_user_num) * 100);
+        } else {
+            $data['recharge_rate'] = 0;
+            $data['recharge_mean'] = 0;
+        }
+        if ($new_user_recharge_total > 0 || $new_user_recharge_num > 0) {
+            $data['recharge_mean'] = sprintf('%.2f', ($new_user_recharge_total / $new_user_recharge_num));
+        } else {
+            $data['recharge_mean'] = 0;
+        }
+
+        return $data;
+    }
+
+    // 获取redis值
+    protected static function getValue($key, $field)
+    {
+        return Redis::hget($key, $field);
+    }
+
+    // 保存redis的值
+    protected static function setValue($key, $field, $value)
+    {
+        Redis::hset($key, $field, $value);
+    }
+
+    /**
+     *  充值人数查询
+     * name: getRechargeUserNum
+     * @param $accountId 账号id
+     * @param  $miniProgramId 小程序id
+     * @param mixed $type 账号类型 2 投放公司 3 优化师
+     * date 2023/06/20 10:18
+     */
+    private static function getRechargeUserNum($accountId, $miniProgramId, mixed $type): array
+    {
+        $start = date("Y-m-d") . " 00:00:00";
+        $end = date("Y-m-d") . " 23:59:59";
+        // $start = "2023-05-31 00:00:00";
+        // $end = "2023-05-31 23:59:59";
+        if ($type == 2) {
+            // 投放公司
+            $recharge_coin_num = DB::table('orders')->where('status', "<>", 'UNPAID')
+                ->where('miniprogram_id', $miniProgramId)
+                ->where('puser_id', $accountId)->whereBetween("created_at", [$start, $end])
+                ->whereBetween('ranse_created_at', [$start, $end])
+                ->where('order_type', 'COIN')->groupBy('uid', 'ranse_created_at')->count();
+            $recharge_vip_num = DB::table('orders')->where('status', "<>", 'UNPAID')
+                ->where('miniprogram_id', $miniProgramId)
+                ->where('puser_id', $accountId)->whereBetween("created_at",[ $start, $end])
+                ->whereBetween('ranse_created_at', [$start, $end])
+                ->where('order_type', '<>', 'COIN')->groupBy('uid', 'ranse_created_at')->count();
+        } elseif ($type == 3) {
+            // 优化师
+            $recharge_coin_num = DB::table('orders')->where('status', "<>", 'UNPAID')
+                ->where('miniprogram_id', $miniProgramId)
+                ->where('user_id', $accountId)->whereBetween("created_at", [$start, $end])
+                ->whereBetween('ranse_created_at', [$start, $end])
+                ->where('order_type', 'COIN')->groupBy('uid', 'ranse_created_at')->count();
+            $recharge_vip_num = DB::table('orders')->where('status', "<>", 'UNPAID')
+                ->where('miniprogram_id', $miniProgramId)
+                ->where('user_id', $accountId)->whereBetween("created_at",[$start, $end])
+                ->whereBetween('ranse_created_at',[ $start, $end])
+                ->where('order_type', '<>', 'COIN')->groupBy('uid', 'ranse_created_at')->count();
+        } else {
+            // 其他暂不统计
+            $recharge_coin_num = 0;
+            $recharge_vip_num = 0;
+        }
+        return [$recharge_coin_num, $recharge_vip_num];
+    }
+}

+ 5 - 0
modules/Statistic/routes/route.php

@@ -1,7 +1,12 @@
 <?php
 
 use Illuminate\Support\Facades\Route;
+use Modules\Statistic\Http\Controllers\UserStatisticsController;
 
 Route::prefix('statistic')->group(function(){
     //next
+    // 用户统计
+    Route::prefix('users')->group(function (){
+        Route::any('today',[UserStatisticsController::class,'todayData']);
+    });
 });

+ 21 - 6
modules/Tuiguang/Http/Controllers/PromotionController.php

@@ -14,7 +14,6 @@ class PromotionController extends CatchController
 {
     use UserTrait;
     use ValidatesRequests;
-
     public function list(Request $request) {
         $callbackTypeMap = [
             '0' => '无',
@@ -33,7 +32,6 @@ class PromotionController extends CatchController
         $miniprogramId = $request->input('miniprogram_id');
         $result = DB::table('promotions')
             ->leftJoin('videos', 'videos.id', '=', 'promotions.video_id')
-            ->leftJoin('miniprogram', 'miniprogram.id', '=', 'promotions.miniprogram_id')
             ->where(['promotions.is_enabled' => 1, 'promotions.uid' => $this->getLoginUserId()])
             ->when($miniprogramId, function ($query, $miniprogramId) {
                 return $query->where('promotions.miniprogram_id', $miniprogramId);
@@ -55,8 +53,15 @@ class PromotionController extends CatchController
             })->orderBy('created_at', 'desc')
             ->select('promotions.id', 'promotions.name', 'promotions.created_at',
                 'videos.name as video_name', 'promotions.series_sequence', 'promotions.callback_type',
-                'promotions.callback_config_id', 'promotions.video_id', 'promotions.remark', 'promotions.status', 'miniprogram.name as miniprogram_name')
+                'promotions.callback_config_id', 'promotions.video_id', 'promotions.remark', 'promotions.status',
+                'promotions.first_charge_template_id', 'promotions.not_first_charge_template_id')
             ->paginate($request->input('limit', 15));
+        $chargeTemplateIds = $result->pluck('first_charge_template_id')->merge($result->pluck('not_first_charge_template_id'))->unique();
+
+        $payTemplates = DB::table('pay_templates')->whereIn('id', $chargeTemplateIds)
+            ->select('id', 'name')
+            ->get()->keyBy('id')->toArray();
+
         foreach ($result as $item) {
             $item->status_str = $item->status ? '启用':'禁用';
             $item->series_sequence_name = '第'. $item->series_sequence . '集';
@@ -66,8 +71,10 @@ class PromotionController extends CatchController
                 '/track?dycallback=1&connection_id='.$item->id.
                 '&link_source=' .( $linkSourceMap[$item->callback_type] ?? '') .
                 '&adid=__AID__&cid=__CID__&imei=__IMEI__&oaid=__OAID__&mac=__MAC__&os=__OS__&ip=__IP__&androidid=__ANDROIDID__&ua=__UA__&timestamp=__TS__&callback_url=__CALLBACK_URL__&projectid=__PROJECT_ID__&promotionid=__PROMOTION_ID__&advertiser_id=__ADVERTISER_ID__&campaign_id=__CAMPAIGN_ID__';
-        }
+            $item->first_charge_template_str = $payTemplates[$item->first_charge_template_id]->name ?? '';
+            $item->not_first_charge_template_str = $payTemplates[$item->not_first_charge_template_id]->name ?? '';
 
+        }
         return $result;
 
     }
@@ -84,12 +91,16 @@ class PromotionController extends CatchController
 
     public function updateSeriesSequence(Request $request) {
         $this->validate($request, ['id' => 'required',
-            'series_sequence' => 'required', 'remark' => 'nullable|string|max:140']);
+            'series_sequence' => 'required', 'remark' => 'nullable|string|max:140',
+            'first_charge_template_id' => 'required',
+            'not_first_charge_template_id' => 'required',]);
 
         DB::table('promotions')
             ->where(['id' => $request->input('id'), 'uid' => $this->getLoginUserId(), 'is_enabled' => 1])
             ->update(['series_sequence' => $request->input('series_sequence'),
-                'remark' => $request->input('remark', ''),
+                'remark' => $request->input('remark') ?? '',
+                'first_charge_template_id' => $request->input('first_charge_template_id'),
+                'not_first_charge_template_id' => $request->input('not_first_charge_template_id'),
                 'updated_at' => date('Y-m-d H:i:s')]);
 
         return 'ok';
@@ -101,6 +112,8 @@ class PromotionController extends CatchController
             'series_sequence' => 'required',
             'name' => 'required',
             'miniprogram_id' => 'required',
+            'first_charge_template_id' => 'required',
+            'not_first_charge_template_id' => 'required',
         ]);
         $now = date('Y-m-d H:i:s');
         DB::table('promotions')
@@ -110,6 +123,8 @@ class PromotionController extends CatchController
                 'name' => $request->input('name'),
                 'video_id' => $request->input('video_id'),
                 'series_sequence' =>  $request->input('series_sequence'),
+                'first_charge_template_id' =>  $request->input('first_charge_template_id'),
+                'not_first_charge_template_id' =>  $request->input('not_first_charge_template_id'),
                 'created_at' => $now,
                 'updated_at' => $now,
             ]);

+ 5 - 2
tests/Tuiguang/Http/Controllers/PromotionControllerTest.php

@@ -40,8 +40,11 @@ class PromotionControllerTest extends UsedTestCase
         $res = $this->withHeaders([
             'Authorization' => 'Bearer '. $this->token,
         ])->json('post','http://localhost/api/tuiguang/promotion/updateSeriesSequence', [
-            'id' => 2,
-            'series_sequence' => 5
+            'id' => 136,
+            'series_sequence' => 5,
+            'remark' => '',
+            'first_charge_template_id' => 1,
+            'not_first_charge_template_id' => 2
         ]);
 
         $res->dump();