Selaa lähdekoodia

Merge branch 'wzq-tj-xyh' into stable

# Conflicts:
#	app/Console/Kernel.php
#	modules/Statistic/routes/route.php
zqwang 1 vuosi sitten
vanhempi
commit
e8b3e7b2e5

+ 44 - 0
app/Console/Commands/Statistic/CompanyDayUserStatistic.php

@@ -0,0 +1,44 @@
+<?php
+/**
+ * 优化师新增用户统计
+ * @file:PromotionDayUserStatistic.php
+ * @Date: 2023/6/25
+ * @Time: 16:38
+ */
+
+
+namespace App\Console\Commands\Statistic;
+
+use Illuminate\Console\Command;
+use Modules\Common\Services\Statistic\CompanyDayUser;
+use Modules\Common\Services\Statistic\OptimizerDayUser;
+
+class CompanyDayUserStatistic extends Command
+{
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'Statistic:CompanyDayUser {--date= : 统计日期}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '投放公司当日新增用户日统计';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle(): void
+    {
+
+        $date = $this->option('date') ?? date('Y-m-d', strtotime('yesterday'));
+        $this->info('统计开始--统计日期:'.$date);
+        CompanyDayUser::companyDayUserStatistic($date);
+        $this->info('统计结束');
+    }
+}

+ 43 - 0
app/Console/Commands/Statistic/OptimizerDayUserStatistic.php

@@ -0,0 +1,43 @@
+<?php
+/**
+ * 优化师新增用户统计
+ * @file:PromotionDayUserStatistic.php
+ * @Date: 2023/6/25
+ * @Time: 16:38
+ */
+
+
+namespace App\Console\Commands\Statistic;
+
+use Illuminate\Console\Command;
+use Modules\Common\Services\Statistic\OptimizerDayUser;
+
+class OptimizerDayUserStatistic extends Command
+{
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'Statistic:OptimizerDayUser {--date= : 统计日期}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '优化师当日新增用户日统计';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle(): void
+    {
+
+        $date = $this->option('date') ?? date('Y-m-d', strtotime('yesterday'));
+        $this->info('统计开始--统计日期:'.$date);
+        OptimizerDayUser::optimizerDayUserStatistic($date);
+        $this->info('统计结束');
+    }
+}

+ 2 - 0
app/Console/Kernel.php

@@ -30,6 +30,8 @@ class Kernel extends ConsoleKernel
         $schedule->command('Statistic:CompanyMonthCharge')->monthlyOn(1, '04:00');
         $schedule->command('Statistic:PromotionDayCharge')->dailyAt('01:00');
         $schedule->command('Statistic:OptimizerMonthCharge')->monthlyOn(1,'03:00');
+        // 新增用户统计
+        $schedule->command('Statistic:OptimizerDayUser')->dailyAt('05:00');
     }
 
     /**

+ 1 - 1
config/database.php

@@ -56,7 +56,7 @@ return [
             'collation' => 'utf8mb4_unicode_ci',
             'prefix' => env('DB_PREFIX', ''),
             'prefix_indexes' => true,
-            'strict' => true,
+            // 'strict' => true,
             'engine' => 'InnoDB',
             'options' => extension_loaded('pdo_mysql') ? array_filter([
                 PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),

+ 16 - 0
modules/Common/Models/TjCompanyDayNewUser.php

@@ -0,0 +1,16 @@
+<?php
+/**
+ *
+ * @file:OptimizerDayUser.php
+ * @Date: 2023/6/26
+ * @Time: 11:04
+ */
+
+
+namespace Modules\Common\Models;
+
+class TjCompanyDayNewUser extends BaseModel
+{
+    protected $table = "tj_company_day_new_users";
+    protected $fillable = ["id","date","new_user_total","user_id","miniprogram_id","new_user_recharge_coin_num","miniprogram_name","miniprogram_play_name","miniprogram_type","new_user_num","new_user_recharge_num","new_user_recharge_vip_num","new_user_recharge_total","recharge_user_total","recharge_amount_total","updated_at","created_at"];
+}

+ 16 - 0
modules/Common/Models/TjOptimizerDayNewUser.php

@@ -0,0 +1,16 @@
+<?php
+/**
+ *
+ * @file:OptimizerDayUser.php
+ * @Date: 2023/6/26
+ * @Time: 11:04
+ */
+
+
+namespace Modules\Common\Models;
+
+class TjOptimizerDayNewUser extends BaseModel
+{
+    protected $table = "tj_optimizer_day_new_users";
+    protected $fillable = ["id","new_user_total","date","user_id","puser_id","new_user_recharge_coin_num","miniprogram_id","miniprogram_name","miniprogram_play_name","miniprogram_type","new_user_num","new_user_recharge_num","new_user_recharge_vip_num","new_user_recharge_total","recharge_user_total","recharge_amount_total","updated_at","created_at"];
+}

+ 161 - 0
modules/Common/Services/Statistic/CompanyDayUser.php

@@ -0,0 +1,161 @@
+<?php
+/**
+ *
+ * @file:PromotionDayUser.php
+ * @Date: 2023/6/25
+ * @Time: 16:58
+ */
+
+
+namespace Modules\Common\Services\Statistic;
+
+use Illuminate\Support\Facades\DB;
+use Modules\Common\Models\TjCompanyDayNewUser;
+use Modules\Common\Models\TjOptimizerDayNewUser;
+use Modules\Common\Services\BaseService;
+
+class CompanyDayUser extends BaseService
+{
+    protected static $miniPrograms; // 小程序
+    protected static $newUserStatisc; // 新增用户
+    protected static $orderStatisc; // 充值统计
+    protected static $orderVipStatisc; // 充值会员统计
+    protected static $orderCoinStatisc; // 充值会员统计
+
+    /**
+     * 优化师用户统计
+     * name:companyDayUserStatistic
+     * @param $date
+     * date 2023/06/25 17:01
+     */
+    public static function companyDayUserStatistic($date)
+    {
+
+        self::getMiniProgram(); // 获取小程序
+        self::getStatisticOrders($date); // 进行订单统计
+        self::getStatisticNewUser($date);
+
+        //  从优化师维度出发统计
+        DB::table('users', 'u')
+            ->leftJoin('user_has_roles as  ur', 'ur.user_id', '=', 'u.id')
+            ->leftJoin('roles as r', 'r.id', '=', 'ur.role_id')
+            ->where('r.identify', 'company')
+            ->select("u.id as  user_id")->orderBy('u.id')
+            ->chunk(10, function ($items) use ($date) {
+                foreach ($items as $v) {
+                    self::getcompanyDayData($v->user_id, $date);
+                }
+            });
+    }
+
+    /**
+     *  优化师统计
+     * name: getcompanyDayData
+     * @param $accountId 账号id
+     * @param  $date 日期
+     * @return array|int[]
+     * date 2023/06/26 17:24
+     */
+    private static function getcompanyDayData($accountId, $date)
+    {
+
+        $userHasMin = DB::table('user_has_miniprograms')->where('uid', $accountId)->get();
+        $userHasMin = $userHasMin->pluck('miniprogram_id')->unique()->toArray();
+        if ($userHasMin) {
+            foreach ($userHasMin as $value) {
+                $userData = self::$newUserStatisc->where('user_id', $accountId)->where('miniprogram_id', $value)->first();
+                $order = self::$orderStatisc->where('user_id', $accountId)->where('miniprogram_id', $value)->first();
+                $vip = self::$orderVipStatisc->where('user_id', $accountId)->where('miniprogram_id', $value)->first();
+                $coin = self::$orderCoinStatisc->where('user_id', $accountId)->where('miniprogram_id', $value)->first();
+                $min = self::$miniPrograms->where('id', $value)->first();
+                $data = [
+                    'user_id' => $accountId,
+                    'miniprogram_id' => $value,
+                    'date' => $date,
+                    'new_user_num' => getProp($userData, 'new_user_num', 0),
+                    'new_user_recharge_num' => getProp($order, 'new_user_recharge_num', 0),
+                    'new_user_recharge_total' => getProp($order, 'new_user_recharge_total', 0),
+                    'new_user_recharge_vip_num' => getProp($vip, 'new_user_recharge_vip_num', 0),
+                    'new_user_recharge_coin_num' => getProp($coin, 'new_user_recharge_coin_num', 0),
+                    'miniprogram_name' => getProp($min, 'name', ''),
+                    'miniprogram_play_name' => getProp($min, 'play_name', ''),
+                    'miniprogram_type' => getProp($min, 'type', ''),
+                ];
+                $last = TjCompanyDayNewUser::where('user_id', $accountId)->where('miniprogram_id',$value)->where('date', "<", $date)->orderBy('date', "desc")->first();
+                if (!is_empty($last)) {
+                    $data['recharge_user_total'] = $last->recharge_user_total + $data['new_user_recharge_num'];
+                    $data['recharge_amount_total'] = $last->recharge_amount_total + $data['new_user_recharge_total'];
+                } else {
+                    $data['recharge_user_total'] = $data['new_user_recharge_num'];
+                    $data['recharge_amount_total'] = $data['new_user_recharge_total'];
+                }
+                TjCompanyDayNewUser::updateOrCreate(['user_id' => $data['user_id'], 'date' => $data['date'],'miniprogram_id' => $data['miniprogram_id']], $data);
+            }
+        }
+    }
+
+    /**
+     *   获取系统所有小程序
+     * name: getMiniProgram
+     * date 2023/06/26 17:21
+     */
+    private static function getMiniProgram()
+    {
+        self::$miniPrograms = DB::table('miniprogram')->get();
+    }
+
+    /**
+     *  统计当日订单
+     * name: getStatisticOrders
+     * @param $date
+     * date 2023/06/26 17:21
+     */
+    private static function getStatisticOrders($date)
+    {
+        $start = $date . " 00:00:00";
+        $end = $date . " 23:59:59";
+        self::$orderStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->select(
+                'puser_id as user_id',
+                "miniprogram_id",
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as  new_user_recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as new_user_recharge_num")  // 当日新增用户充值人数
+            )->groupBy('puser_id', 'miniprogram_id')->get();
+        self::$orderVipStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])->whereNotIn("order_type",  ["COIN", "FIRST_COIN"])
+            ->select(
+                'puser_id as user_id',
+                "miniprogram_id",
+                DB::raw("COUNT(DISTINCT ranse_end_at,uid) as new_user_recharge_vip_num") // 会员充值人数
+            )->groupBy('puser_id', 'miniprogram_id')->get();
+        self::$orderCoinStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])->whereIn("order_type",  ["COIN", "FIRST_COIN"])
+            ->select(
+                'puser_id as user_id',
+                "miniprogram_id",
+                DB::raw("COUNT(DISTINCT ranse_end_at,uid) as new_user_recharge_coin_num") // 会员充值人数
+            )->groupBy('puser_id', 'miniprogram_id')->get();
+    }
+
+    /**
+     *  当日新用户统计
+     * name: getStatisticNewUser
+     * @param $date
+     * date 2023/06/26 17:21
+     */
+    private static function getStatisticNewUser($date)
+    {
+        self::$newUserStatisc = DB::table('user_ranse_record_all')->where('date', "=", $date)
+            ->select(
+                 'puser_id as user_id', 'miniprogram_id', 'miniprogram_type', 'date',
+                DB::raw('count(user_id) as new_user_num')
+            )->orderBy('puser_id')
+            ->groupBy('puser_id', 'miniprogram_id')->get();
+    }
+
+
+}

+ 172 - 0
modules/Common/Services/Statistic/OptimizerDayUser.php

@@ -0,0 +1,172 @@
+<?php
+/**
+ *
+ * @file:PromotionDayUser.php
+ * @Date: 2023/6/25
+ * @Time: 16:58
+ */
+
+
+namespace Modules\Common\Services\Statistic;
+
+use Illuminate\Support\Facades\DB;
+use Modules\Common\Models\TjOptimizerDayNewUser;
+use Modules\Common\Services\BaseService;
+
+class OptimizerDayUser extends BaseService
+{
+    protected static $miniPrograms; // 小程序
+    protected static $newUserStatisc; // 优化师
+    protected static $orderStatisc; // 充值统计
+    protected static $orderVipStatisc; // 充值会员统计
+    protected static $orderCoinStatisc; // 充值会员统计
+
+    /**
+     * 优化师用户统计
+     * name:optimizerDayUserStatistic
+     * @param $date
+     * date 2023/06/25 17:01
+     */
+    public static function optimizerDayUserStatistic($date)
+    {
+
+        self::getMiniProgram(); // 获取小程序
+        self::getStatisticOrders($date); // 进行订单统计
+        self::getStatisticNewUser($date);
+
+        //  从优化师维度出发统计
+        DB::table('users', 'u')
+            ->leftJoin('user_has_roles as  ur', 'ur.user_id', '=', 'u.id')
+            ->leftJoin('roles as r', 'r.id', '=', 'ur.role_id')
+            ->where('r.identify', 'optimizer')
+            ->select("u.id as  user_id", 'u.pid as  puser_id')->orderBy('u.id')
+            ->chunk(10, function ($items) use ($date) {
+                foreach ($items as $v) {
+                    self::getOptimizerDayData($v, $date);
+                }
+            });
+    }
+
+    /**
+     *  优化师统计
+     * name: getOptimizerDayData
+     * @param  $date 日期
+     * @param $data 账号
+     *  $data = [
+     *          'user_id' => 10, // 优化师id
+     *          'puser_id' => 2, // 公司账号id
+     *        ]
+     *
+     * @return array|int[]
+     * date 2023/06/26 17:24
+     */
+    private static function getOptimizerDayData($data, $date)
+    {
+        $userId = getProp($data, 'user_id');
+        $puserId = getProp($data, 'puser_id');
+        $userHasMin = DB::table('user_has_miniprograms')->where('uid', $userId)->get();
+        $userHasMin = $userHasMin->pluck('miniprogram_id')->unique()->toArray();
+        if ($userHasMin) {
+            foreach ($userHasMin as $value) {
+                $userData = self::$newUserStatisc->where('user_id', $userId)->where('miniprogram_id', $value)->first();
+                $order = self::$orderStatisc->where('user_id', $userId)->where('miniprogram_id', $value)->first();
+                $vip = self::$orderVipStatisc->where('user_id', $userId)->where('miniprogram_id', $value)->first();
+                $coin = self::$orderCoinStatisc->where('user_id', $userId)->where('miniprogram_id', $value)->first();
+                $min = self::$miniPrograms->where('id', $value)->first();
+                $data = [
+                    "user_id" => $userId,
+                    'puser_id' => $puserId,
+                    'miniprogram_id' => $value,
+                    'date' => $date,
+                    'new_user_num' => getProp($userData, 'new_user_num', 0),
+                    'new_user_recharge_num' => getProp($order, 'new_user_recharge_num', 0),
+                    'new_user_recharge_total' => getProp($order, 'new_user_recharge_total', 0),
+                    'new_user_recharge_vip_num' => getProp($vip, 'new_user_recharge_vip_num', 0),
+                    'new_user_recharge_coin_num' => getProp($coin, 'new_user_recharge_coin_num', 0),
+                    'miniprogram_name' => getProp($min, 'name', ''),
+                    'miniprogram_play_name' => getProp($min, 'play_name', ''),
+                    'miniprogram_type' => getProp($min, 'type', ''),
+                ];
+                $last = TjOptimizerDayNewUser::where('user_id', $userId)->where('miniprogram_id',$value)->where('puser_id', $puserId)->where('date', "<", $date)->orderBy('date', "desc")->first();
+                if (!is_empty($last)) {
+                    $data['recharge_user_total'] = $last->recharge_user_total + $data['new_user_recharge_num'];
+                    $data['recharge_amount_total'] = $last->recharge_amount_total + $data['new_user_recharge_total'];
+                    $data['new_user_total'] = $last->new_user_total + $data['new_user_num'];
+                } else {
+                    $data['recharge_user_total'] = $data['new_user_recharge_num'];
+                    $data['new_user_total'] = $data['new_user_num'];
+                    $data['recharge_amount_total'] =  $data['new_user_recharge_total'];
+                }
+                TjOptimizerDayNewUser::updateOrCreate(['user_id' => $data['user_id'], 'puser_id' => $data['puser_id'], 'date' => $data['date'],'miniprogram_id' => $data['miniprogram_id']], $data);
+            }
+        }
+    }
+
+    /**
+     *   获取系统所有小程序
+     * name: getMiniProgram
+     * date 2023/06/26 17:21
+     */
+    private static function getMiniProgram()
+    {
+        self::$miniPrograms = DB::table('miniprogram')->get();
+    }
+
+    /**
+     *  统计当日订单
+     * name: getStatisticOrders
+     * @param $date
+     * date 2023/06/26 17:21
+     */
+    private static function getStatisticOrders($date)
+    {
+        $start = $date . " 00:00:00";
+        $end = $date . " 23:59:59";
+        self::$orderStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->select(
+                "user_id",
+                'puser_id',
+                "miniprogram_id",
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as  new_user_recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as new_user_recharge_num")  // 当日新增用户充值人数
+            )->groupBy('user_id', 'miniprogram_id')->get();
+        self::$orderVipStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])->whereNotIn("order_type", ["COIN", "FIRST_COIN"])
+            ->select(
+                "user_id",
+                'puser_id',
+                "miniprogram_id",
+                DB::raw("COUNT(DISTINCT ranse_end_at,uid) as new_user_recharge_vip_num") // 会员充值人数
+            )->groupBy('user_id', 'miniprogram_id')->get();
+        self::$orderCoinStatisc = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])->whereIn("order_type", ["COIN", "FIRST_COIN"])
+            ->select(
+                "user_id",
+                'puser_id',
+                "miniprogram_id",
+                DB::raw("COUNT(DISTINCT ranse_end_at,uid) as new_user_recharge_coin_num") // 普通充值人数
+            )->groupBy('user_id', 'miniprogram_id')->get();
+    }
+
+    /**
+     *  当日新用户统计
+     * name: getStatisticNewUser
+     * @param $date
+     * date 2023/06/26 17:21
+     */
+    private static function getStatisticNewUser($date)
+    {
+        self::$newUserStatisc = DB::table('user_ranse_record_all')->where('date', "=", $date)
+            ->select(
+                "user_id", 'puser_id', 'miniprogram_id', 'miniprogram_type', 'date',
+                DB::raw('count(user_id) as new_user_num')
+            )->orderBy('user_id')
+            ->groupBy('user_id', 'miniprogram_id')->get();
+    }
+
+
+}

+ 35 - 0
modules/Statistic/Http/Controllers/HomeStatisticsController.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ *
+ * @file:HomeStatisticsController.php
+ * @Date: 2023/6/28
+ * @Time: 09:23
+ */
+
+
+namespace Modules\Statistic\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Http\Request;
+use Modules\Statistic\Services\UserStatisticsService;
+use Modules\User\Http\Controllers\UserTrait;
+
+class HomeStatisticsController  extends CatchController
+{
+    use UserTrait;
+    public  function  statistics(Request $request)
+    {
+        $userContext = $this->getUserContext(null);
+        $type = 1;
+        if( $userContext['loginUserRoles']->contains('company')){
+            $type = 2;
+        }else if ($userContext['loginUserRoles']->contains('optimizer')){
+            $type = 3;
+        }
+        $uid = $this->getLoginUserId();
+        $miniProgramId = $request->input('miniprogram_id',0);
+
+        return UserStatisticsService::getTodayHomeData($uid,$type,$miniProgramId);
+    }
+
+}

+ 73 - 4
modules/Statistic/Http/Controllers/UserStatisticsController.php

@@ -13,6 +13,7 @@ use Catch\Base\CatchController;
 use Catch\Exceptions\FailedException;
 use Illuminate\Http\Request;
 
+use Modules\Common\Services\Statistic\OptimizerDayUser;
 use Modules\Statistic\Services\UserStatisticsService;
 use Modules\User\Http\Controllers\UserTrait;
 
@@ -27,10 +28,27 @@ class UserStatisticsController extends CatchController
      */
     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;
         }
+        $miniProgramId = $request->input('miniprogram_id',0);
+        $uid = $this->getLoginUserId();
+        return UserStatisticsService::getTodayData($uid,$type,$miniProgramId);
+    }
+
+    /**
+     *  历史统计
+     * name: stats
+     * @param Request $request
+     * date 2023/06/25 14:24
+     */
+    public function stats(Request $request)
+    {
+        $miniProgramId = $request->input('miniprogram_id',0);
         $userContext = $this->getUserContext(null);
         $type = 1;
         if( $userContext['loginUserRoles']->contains('company')){
@@ -39,7 +57,58 @@ class UserStatisticsController extends CatchController
             $type = 3;
         }
         $uid = $this->getLoginUserId();
-        return UserStatisticsService::getTodayData($uid,$miniProgramId,$type);
+        return UserStatisticsService::historyStats($uid,$type,$miniProgramId);
+    }
+
+    /**
+     *   列表查询
+     * name: list
+     * @param Request $request
+     * date 2023/06/25 14:24
+     */
+    public function list(Request $request){
+        $param = $request->all();
+        $param = $this->getlistParams($param);
+       return UserStatisticsService::list($param);
+    }
+
+    public function listStatistics(Request $request){
+        $param = $request->all();
+        $param = $this->getlistParams($param);
+        return UserStatisticsService::listStatistics($param);
+    }
+
+    private function getlistParams($param)
+    {
+        $userContext = $this->getUserContext(null);
+        if (getProp($param, 'puser_id')) {
+            $param['puser_id'] = $param['puser_id'];
+        }
+        if (getProp($param, 'user_id')) {
+            $param['user_id'] = $param['user_id'];
+        }
+        // 公司账户处理
+        if ($userContext['loginUserRoles']->contains('company')) {
+            $param['puser_id'] = $userContext['operateUser']->id;
+        }
+
+        // 投手处理
+        if ($userContext['loginUserRoles']->contains('optimizer')) {
+            $param['user_id'] = $userContext['operateUser']->id;
+            $param['puser_id'] = $userContext['operateUser']->pid;
+        }
+        if (!getProp($param,'end_at')){
+            $param['end_at'] = date('Y-m-d');
+        }else{
+            $param['end_at'] = date('Y-m-d',strtotime($param['end_at']));
+        }
+        if (!getProp($param,'start_at')){
+            // 默认最近7天
+            $param['start_at'] = date('Y-m-d',strtotime($param['end_at'])-86400*7);
+        }else{
+            $param['start_at'] = date('Y-m-d',strtotime($param['start_at']));
+        }
+        return $param;
     }
 
 

+ 328 - 55
modules/Statistic/Services/UserStatisticsService.php

@@ -11,54 +11,97 @@ namespace Modules\Statistic\Services;
 
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Redis;
+use Modules\Common\Models\TjOptimizerDayNewUser;
 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';
+    // key 日期:
+    protected const PROMOTION_STATISTIC_RECORD_REDIS_KEY = 'statistic:miniprogram:users_recode:%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"; // 当日新增户充值金额
+    protected const RANSE_NEW_USER_COUNT = "promotion:newUserCount:%s"; // 推广链接新用户统计
 
     /**
      *
      * name: getTodayData
      * @param int $accountId 账号id
-     * @param int $miniProgramId 小程序id
      * @param int $type 账号类型 1 其他 2 投放公司 3 优化师
+     * @param int $minId 小程序id
      * date 2023/06/20 10:20
+     * @return array
      */
-    public static function getTodayData($accountId, $miniProgramId, $type = 1)
+    public static function getTodayData($accountId, $type = 1, $minId = 0)
     {
         $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);
+        $start = $date . " 00:00:00";
+        $end = $date . " 23:59:59";
+
+        $where = [];
+        if ($minId > 0) {
+            $where['miniprogram_id'] = $minId;
+        }
+
+        if ($type == 2) {
+            $where['puser_id'] = $accountId;
+        } else if ($type == 3) {
+            $where['user_id'] = $accountId;
+        }
+        $new_user_num = DB::table('user_ranse_record_all')->where($where)->where('date', $date)->count(); // 新增用户人数
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first();
+        $new_user_recharge_total = $info->recharge_total ?: 0; // 新增用户充值总额
+        $new_user_recharge_num = $info->recharge_num ?: 0; // 新增用户充值人数
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->whereIn('order_type', ["COIN", "FIRST_COIN"])
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first(); // 普通充值金额
+        $recharge_coin_total = $info->recharge_total ?: 0; // 新增用户普通充值总额
+        $recharge_coin_num = $info->recharge_num ?: 0; // 新增用户普通充值总额
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first(); // 会员充值金额
+        $recharge_vip_total = $info->recharge_total ?: 0; // 新增用户会员充值总额
+        $recharge_vip_num = $info->recharge_num ?: 0; // 新增用户会员充值总额
+
         $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_total' => $recharge_coin_total ?: 0,
             'recharge_coin_num' => $recharge_coin_num ?: 0,
+            'recharge_vip_total' => $recharge_vip_total ?: 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);
+            $data['recharge_rate'] = sprintf("%.2f%s", ($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));
+            $data['recharge_mean'] = sprintf('%.2f%s', ($new_user_recharge_total / $new_user_recharge_num), "%");
         } else {
             $data['recharge_mean'] = 0;
         }
@@ -66,61 +109,291 @@ class UserStatisticsService extends BaseService
         return $data;
     }
 
-    // 获取redis值
+    /**
+     * 获取redis值
+     * name: getValue
+     * @param $key
+     * @param $field
+     * @return mixed
+     * date 2023/06/25 15:57
+     */
     protected static function getValue($key, $field)
     {
         return Redis::hget($key, $field);
     }
 
-    // 保存redis的值
+    /**
+     *
+     * name: getTodayData
+     * @param int $accountId 账号id
+     * @param int $type 账号类型 1 其他 2 投放公司 3 优化师
+     * @param int $minId 小程序id
+     * date 2023/06/20 10:20
+     * @return array
+     */
+    public static function getTodayHomeData(mixed $accountId, int $type, $minId = 0)
+    {
+        $date = date("Y-m-d");
+        $start = $date . " 00:00:00";
+        $end = $date . " 23:59:59";
+
+        $where = [];
+        if ($minId > 0) {
+            $where['miniprogram_id'] = $minId;
+        }
+        if ($type == 2) {
+            $where['puser_id'] = $accountId;
+        } else if ($type == 3) {
+            $where['user_id'] = $accountId;
+        }
+        $new_user_num = DB::table('user_ranse_record_all')->where($where)->where('date', $date)->count(); // 新增用户人数
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first();
+        $new_user_recharge_total = $info->recharge_total ?: 0; // 新增用户充值总额
+        $new_user_recharge_num = $info->recharge_num ?: 0; // 新增用户充值人数
+        if ($type == 2) {
+            $where = ['puser_id' => $accountId];
+        } else {
+            $where = ['user_id' => $accountId];
+        }
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->whereIn('order_type', ["COIN", "FIRST_COIN"])->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first(); // 普通充值金额
+        $new_user_recharge_coin_total = $info->recharge_total ?: 0; // 新增用户普通充值总额
+        $new_user_recharge_coin_num = $info->recharge_num ?: 0; // 新增用户普通充值总额
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereBetween('ranse_created_at', [$start, $end])
+            ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num")  // 当日新增用户充值人数
+            )->first(); // 会员充值金额
+        $new_user_recharge_vip_total = $info->recharge_total ?: 0; // 新增用户会员充值总额
+        $new_user_recharge_vip_num = $info->recharge_num ?: 0; // 新增用户会员充值总额
+        $info = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->where($where)
+            ->select(
+                DB::raw("sum(if(status = 'unpaid', 0, price)) as  recharge_total"), // 单日新增用户充值金额
+                DB::raw("count(DISTINCT ranse_created_at,uid) as  recharge_num")  // 当日新增用户充值人数
+            )->first();
+        $recharge_total = $info->recharge_total ?: 0; // 充值人数
+        $recharge_num = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->whereBetween("created_at", [$start, $end])
+            ->where($where)->count();
+        $recharge_coin_total = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 普通充值金额
+        $recharge_vip_total = DB::table('orders')->where('status', "<>", 'UNPAID')
+            ->where($where)
+            ->whereBetween("created_at", [$start, $end])
+            ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 会员充值金额
+
+        $data = [
+            'new_user_num' => $new_user_num, // 新增用户数
+            'new_user_recharge_num' => $new_user_recharge_num, // 新增用户充值人数
+            'new_user_recharge_coin_num' => $new_user_recharge_coin_num, // 新增用户普通充值人数
+            'new_user_recharge_vip_num' => $new_user_recharge_vip_num, // 新增用户vip充值人数
+            'new_user_recharge_total' => $new_user_recharge_total, // 新增用户充值金额
+            'new_user_recharge_vip_total' => $new_user_recharge_vip_total, // 新增用户普通充值金额
+            'new_user_recharge_coin_total' => $new_user_recharge_coin_total, // 新增用户vip充值金额
+            'recharge_total' => $recharge_total, // 充值金额
+            'recharge_coin_totall' => $recharge_coin_total, // 普通充值金额
+            'recharge_vip_total' => $recharge_vip_total, // VIP 充值金额
+            'recharge_num' => $recharge_num, // 充值笔数
+
+        ];
+
+        // 新增用户充值率
+        $data['new_user_recharge_rate'] = $data['new_user_num'] > 0 && $data['new_user_recharge_num'] > 0 ? sprintf("%.2f%s", $data['new_user_recharge_num'] / $data['new_user_num'], "%") : 0;
+        // 新增用户人均充值
+        $data['new_user_mean'] = $data['new_user_num'] > 0 && $data['new_user_recharge_total'] > 0 ? sprintf("%.2f", $data['new_user_recharge_total'] / $data['new_user_num']) : 0;
+        $data['recharge_mean'] = $data['recharge_total'] > 0 && $data['recharge_num'] > 0 ? sprintf("%.2f", $data['recharge_total'] / $data['recharge_num'], "%") : 0; // 新增用户人均充值
+        return $data;
+
+    }
+
+
+    /**
+     * 保存redis的值
+     * name: setValue
+     * @param $key
+     * @param $field
+     * @param $value
+     * date 2023/06/25 15:57
+     */
     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
+     *
+     * name: getTodayData
+     * @param int $accountId 账号id
+     * @param mixed $type 账号类型 1 其他 2 投放公司 3 优化师
+     * @param mixed $miniProgramId 小程序id
+     */
+    public static function historyStats(int $accountId, $type, $miniProgramId)
+    {
+        $month = self::getStaticsData($accountId, date('Y-m-01'), date('Y-m-d', strtotime('yesterday')), $type, $miniProgramId);
+        $lastMonth = self::getStaticsData($accountId, date('Y-m-01', strtotime(date('Y-m-01')) - 10), date('Y-m-d', strtotime(date('Y-m-01')) - 10), $type, $miniProgramId);
+        $history = self::getHistoryData($accountId, $type, $miniProgramId);
+        return ['month' => $month, 'lastMonth' => $lastMonth, 'history' => $history];
+    }
+
+    /**
+     *   历史汇总
+     * name: getMonthData
+     * @param int $accountId 账号
+     * @param mixed $type 角色类型 账号类型 1 其他 2 投放公司 3 优化师
+     * @param mixed $minId 小程序id
+     * date 2023/06/27 11:19
+     */
+    protected static function getHistoryData($accountId, $type, $minId = 0)
+    {
+        $date = date('Y-m-d', strtotime('yesterday'));
+        $sql = TjOptimizerDayNewUser::where('date', $date);
+        if ($type == 2) {
+            $sql->where('puser_id', $accountId);
+        } elseif ($type == 3) {
+            $sql->where('user_id', $accountId);
+        }
+        if ($minId > 0) {
+            $sql->where('miniprogram_id', $minId);
+        }
+        $info = $sql->select(
+            DB::raw("sum(recharge_amount_total) as recharge_amount_total"), // 总充金额
+            DB::raw("sum(new_user_total) as new_user_total"), // 总充金额
+            DB::raw("sum(recharge_user_total) as recharge_user_total"), // 累计充值人数
+        )->first();
+
+        return [
+            'recharge_amount_total' => $info->recharge_amount_total ?: 0,
+            'new_user_total' => $info->new_user_total ?: 0,
+            'recharge_user_total' => $info->recharge_user_total ?: 0,
+        ];
+    }
+
+    /**
+     *    日期范围的统计
+     * name: getMonthData
+     * @param int $accountId 账号
+     * @param mixed $type 角色类型 账号类型 1 其他 2 投放公司 3 优化师
+     * @param mixed $minId 小程序id
+     * date 2023/06/27 11:19
      */
-    private static function getRechargeUserNum($accountId, $miniProgramId, mixed $type): array
+    private static function getStaticsData($accountId, $start, $end, $type, $minId = 0)
     {
-        $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";
+        $sql = TjOptimizerDayNewUser::where('date', '>=', $start)->where("date", "<=", $end);
         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();
+            $sql->where('puser_id', $accountId);
         } 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();
+            $sql->where('user_id', $accountId);
+        }
+        if ($minId > 0) {
+            $sql->where('miniprogram_id', $minId);
+        }
+        return self::handleStaticData($sql);
+
+    }
+
+    /**
+     *   统计数据处理
+     * name: handelStaticData
+     * @param $sql
+     * @return array
+     * date 2023/06/27 14:51
+     */
+    protected static function handleStaticData($sql): array
+    {
+        $info = $sql->select(
+            DB::raw("sum(new_user_recharge_total) as new_user_recharge_total"), // 充值人数
+            DB::raw("sum(new_user_num) as new_user_num"), // 新增用户人数
+            DB::raw("sum(new_user_recharge_num) as new_user_recharge_num"), // 充值人数
+            DB::raw("sum(new_user_recharge_vip_num) as new_user_recharge_vip_num"), // VIP充值人数
+            DB::raw("sum(new_user_recharge_coin_num) as new_user_recharge_coin_num") // 普通充值人数
+        )->first();
+        return [
+            'new_user_recharge_total' => $info->new_user_recharge_total ?: 0,
+            'new_user_num' => $info->new_user_num ?: 0,
+            'new_user_recharge_num' => $info->new_user_recharge_num ?: 0,
+            'new_user_recharge_vip_num' => $info->new_user_recharge_vip_num ?: 0,
+            'new_user_recharge_coin_num' => $info->new_user_recharge_coin_num ?: 0,
+        ];
+    }
+
+
+    /**
+     * 统计列表
+     */
+    public static function list($param)
+    {
+        $sql = self::getQuerySql($param)->select("tj_optimizer_day_new_users.*", 'users.username')->orderBy('date', 'desc')->orderBy('id', 'desc');
+        $isAll = getProp($param, 'is_all');
+        if ($isAll) {
+            $list = $sql->get();
         } else {
-            // 其他暂不统计
-            $recharge_coin_num = 0;
-            $recharge_vip_num = 0;
+            $list = $sql->paginate(getProp($param, 'limit', 15));
+        }
+        if ($list->isEmpty()) {
+            return $list;
+        }
+        $companyIds = $list->pluck('puser_id')->unique()->toArray();
+
+        $companys = DB::table('users')->whereIn('id', $companyIds)->get();
+
+        foreach ($list as $value) {
+            // 充值率
+            $value->recharge_rate = $value->new_user_recharge_num > 0 && $value->new_user_num > 0 ? sprintf("%.2f%s", $value->new_user_recharge_num / $value->new_user_num, "%") : 0;
+            // 人均充值
+            $value->recharge_mean = $value->new_user_recharge_num > 0 && $value->new_user_recharge_total > 0 ? sprintf("%.2f%s", $value->new_user_recharge_total / $value->new_user_recharge_num, "%") : 0;
+            $value->company_name = $companys->where('id', $value->puser_id)->value('username');
+        }
+        return $list;
+    }
+
+    // 列表数据统计
+    public static function listStatistics($param): array
+    {
+        $sql = self::getQuerySql($param);
+        return self::handleStaticData($sql);
+    }
+
+    private static function getQuerySql(array $param)
+    {
+        $sql = TjOptimizerDayNewUser::query()->leftJoin('users', 'users.id', "=", 'tj_optimizer_day_new_users.user_id');
+        if (getProp($param, 'start_at')) {
+            $sql->where('tj_optimizer_day_new_users.date', ">=", $param['start_at']);
+        }
+        if (getProp($param, 'end_at')) {
+            $sql->where('tj_optimizer_day_new_users.date', "<=", $param['end_at']);
         }
-        return [$recharge_coin_num, $recharge_vip_num];
+        if (getProp($param, 'user_id')) {
+            $sql->where('tj_optimizer_day_new_users.user_id', $param['user_id']);
+        }
+        if (getProp($param, 'puser_id')) {
+            $sql->where('tj_optimizer_day_new_users.puser_id', $param['puser_id']);
+        }
+        if (getProp($param, 'miniprogram_id')) {
+            $sql->where('tj_optimizer_day_new_users.miniprogram_id', $param['miniprogram_id']);
+        }
+        return $sql;
     }
+
+
 }

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

@@ -2,6 +2,7 @@
 
 use Illuminate\Support\Facades\Route;
 use Modules\Statistic\Http\Controllers\ChargeTJController;
+use Modules\Statistic\Http\Controllers\HomeStatisticsController;
 use Modules\Statistic\Http\Controllers\UserStatisticsController;
 use Modules\Statistic\Http\Controllers\VideoStatController;
 
@@ -9,7 +10,14 @@ Route::prefix('statistic')->group(function(){
     //next
     // 用户统计
     Route::prefix('users')->group(function (){
+        // 今天数据统计
         Route::any('today',[UserStatisticsController::class,'todayData']);
+        // 历史充值统计
+        Route::any('stats',[UserStatisticsController::class,'stats']);
+        // 投手日充值列表
+        Route::any('list',[UserStatisticsController::class,'list']);
+        // 投手日充值列表汇总
+        Route::any('list_statistics',[UserStatisticsController::class,'listStatistics']);
     });
 
     // 短剧统计
@@ -26,4 +34,8 @@ Route::prefix('statistic')->group(function(){
         Route::get('lastMonthCharge', [ChargeTJController::class, 'lastMonthCharge']);
         Route::get('totalCharge', [ChargeTJController::class, 'totalCharge']);
     });
+
+    // 首页统计
+    Route::any("home",[HomeStatisticsController::class,"statistics"]);
+
 });