feat: 修改了交易统计逻辑,添加了交易统计的接口

This commit is contained in:
mkm 2024-06-20 11:08:06 +08:00
parent 2aa8322f99
commit 557170ce74
11 changed files with 376 additions and 312 deletions

View File

@ -14,7 +14,9 @@
namespace app\admin\controller;
use app\admin\logic\statistic\ProductStatisticLogic;
use app\admin\logic\statistic\TradeStatisticLogic;
use app\admin\logic\statistic\UserStatisticLogic;
use app\admin\logic\WorkbenchLogic;
use DateInterval;
use DateTime;
@ -300,28 +302,10 @@ class WorkbenchController extends BaseAdminController
*/
public function get_product_ranking()
{
$data = [
[
"product_id" => 1661,
"visit" => "1331",
"user" => 119,
"cart" => "26",
"orders" => "22",
"pay" => "11",
"price" => "690.02",
"cost" => "0.00",
"profit" => "1.00",
"collect" => "4",
"changes" => "0.06",
"repeats" => "0.28",
"store_name" => "瞌睡兔 美式复古圆领卫衣外套女春秋款小个子宽松百搭休闲上衣",
"image" => "https://multi-store.crmeb.net/uploads/attach/2024/02/19/2f3f938d720fc4212216ab855808bf85.jpg",
"product_price" => "100.00",
"stock" => 16777213,
"is_show" => 1
],
];
return $this->data($data);
$date=$this->request->get('date','');
$where['create_time'] = $this->getDay($date);
$data=(new ProductStatisticLogic())->get_product_ranking($where);
return $this->success('',$data);
}
//-------------------------------用户统计---------------------------------------//
@ -331,68 +315,9 @@ class WorkbenchController extends BaseAdminController
*/
public function get_user_basic()
{
$data = [
"people" => [
"num" => 1086,
"last_num" => 20904,
"percent" => "-94.80"
],
"browse" => [
"num" => 11296,
"last_num" => 363632,
"percent" => "-96.89"
],
"newUser" => [
"num" => 391,
"last_num" => 21790,
"percent" => "-98.20"
],
"payPeople" => [
"num" => 84,
"last_num" => 1314,
"percent" => "-93.60"
],
"payPercent" => [
"num" => "7.73",
"last_num" => "6.28",
"percent" => "23.08"
],
"payUser" => [
"num" => 27,
"last_num" => 431,
"percent" => "-93.73"
],
"rechargePeople" => [
"num" => 13,
"last_num" => 121,
"percent" => "-89.25"
],
"payPrice" => [
"num" => 2042.04,
"last_num" => 10352.37,
"percent" => "-80.27"
],
"cumulativeUser" => [
"num" => 22852,
"last_num" => 21790,
"percent" => "4.87"
],
"cumulativePayUser" => [
"num" => 552,
"last_num" => 521,
"percent" => "5.95"
],
"cumulativeRechargePeople" => [
"num" => 134,
"last_num" => 121,
"percent" => "10.74"
],
"cumulativePayPeople" => [
"num" => 1380,
"last_num" => 1314,
"percent" => "5.02"
]
];
$date=$this->request->get('date','');
$where['create_time'] = $this->getDay($date);
$data=(new UserStatisticLogic())->getBasic($where);
return $this->data($data);
}
@ -401,217 +326,10 @@ class WorkbenchController extends BaseAdminController
*/
public function get_user_trend()
{
$data = [
"xAxis" => [
"2024-05-06",
"2024-05-07",
"2024-05-08",
"2024-05-09",
"2024-05-10",
"2024-05-11",
"2024-05-12",
"2024-05-13",
"2024-05-14",
"2024-05-15",
"2024-05-16",
"2024-05-17",
"2024-05-18",
"2024-05-19",
"2024-05-20",
"2024-05-21",
"2024-05-22",
"2024-05-23",
"2024-05-24",
"2024-05-25",
"2024-05-26",
"2024-05-27",
"2024-05-28",
"2024-05-29",
"2024-05-30",
"2024-05-31",
"2024-06-01",
"2024-06-02",
"2024-06-03",
"2024-06-04"
],
"series" => [
[
"name" => "新增用户数",
"value" => [
13,
15,
11,
20,
9,
8,
1,
6,
15,
20,
9,
13,
5,
2,
17,
19,
8,
12,
12,
22,
9,
32,
17,
16,
14,
17,
10,
5,
20,
7
]
],
[
"name" => "访客数",
"value" => [
44,
69,
59,
82,
58,
37,
27,
44,
43,
57,
54,
49,
24,
17,
42,
68,
55,
72,
52,
130,
45,
213,
108,
97,
84,
78,
54,
45,
94,
52
]
],
[
"name" => "成交用户数",
"value" => [
3,
4,
5,
5,
3,
3,
1,
3,
4,
7,
9,
5,
1,
1,
4,
4,
7,
6,
7,
8,
2,
14,
5,
5,
8,
3,
1,
4,
8,
4
]
],
[
"name" => "充值用户",
"value" => [
0,
0,
0,
1,
2,
0,
0,
0,
0,
2,
1,
1,
0,
0,
0,
1,
0,
0,
0,
1,
1,
2,
0,
0,
0,
1,
0,
0,
1,
1
]
],
[
"name" => "新增付费用户数",
"value" => [
0,
3,
2,
1,
0,
0,
0,
0,
1,
4,
4,
1,
1,
1,
0,
0,
0,
3,
3,
1,
0,
3,
2,
0,
1,
3,
1,
2,
3,
0
]
]
]
];
$date=$this->request->get('date','');
$where['create_time'] = $this->getDay($date);
$data=(new UserStatisticLogic())->getTrend($where);
return $this->data($data);
}
//-------------------------------交易统计---------------------------------------//
@ -644,4 +362,23 @@ class WorkbenchController extends BaseAdminController
$data=(new TradeStatisticLogic())->getBottomTrade(['data'=>'2024/05/21-2024/06/19']);
return $this->data($data);
}
/**
* 格式化时间
* @param $time
* @return string
*/
public function getDay($time)
{
if (strstr($time, '-') !== false) {
[$startTime, $endTime] = explode('-', $time);
if (!$startTime && !$endTime) {
return date("Y/m/d", strtotime("-30 days", time())) . '-' . date("Y/m/d", time());
} else {
return $startTime . '-' . $endTime;
}
} else {
return date("Y/m/d", strtotime("-30 days", time())) . '-' . date("Y/m/d", time());
}
}
}

View File

@ -45,7 +45,7 @@ class SystemStoreLists extends BaseAdminDataLists implements ListsSearchInterfac
{
return SystemStore::where($this->searchWhere)
->field(['id', 'name', 'phone', 'detailed_address', 'image', 'is_show','day_start','day_end'
,'bank','bank_code','bank_address','realname'
,'bank','bank_code','bank_address','realname,paid_deposit,security_deposit'
])
->limit($this->limitOffset, $this->limitLength)
->order(['id' => 'desc'])

View File

@ -0,0 +1,46 @@
<?php
namespace app\admin\logic\statistic;
use app\common\logic\BaseLogic;
use app\common\model\store_product_log\StoreProductLog;
/**
* Class 商品统计
* @package app\services\statistic
*/
class ProductStatisticLogic extends BaseLogic
{
public function get_product_ranking($where)
{
$list = StoreProductLog::where($where)->with('storeName')
->field([
'product_id',
'SUM(visit_num) as visit',
'COUNT(distinct(uid)) as user',
'SUM(cart_num) as cart',
'SUM(order_num) as orders',
'SUM(pay_num) as pay',
'SUM(pay_price * pay_num) as price',
'SUM(cost_price) as cost',
'ROUND((SUM(pay_price)-SUM(cost_price))/SUM(pay_price),2) as profit',
'SUM(collect_num) as collect',
'ROUND((COUNT(distinct(pay_uid))-1)/COUNT(distinct(uid)),2) as changes',
'COUNT(distinct(pay_uid))-1 as repeats'
])->group('product_id')->order('pay' . ' desc')->limit(20)->select()->toArray();
foreach ($list as $key => &$item) {
if (!$item['store_name'] || !$item['image']) {
unset($list[$key]);
}
if ($item['profit'] == null) $item['profit'] = 0;
if ($item['changes'] == null) $item['changes'] = 0;
if ($item['repeats'] == null) {
$item['repeats'] = 0;
} else {
$item['repeats'] = bcdiv(count(StoreProductLog::where($where)->where('type', 'pay')->where('product_id', $item['product_id'])->field('count(pay_uid) as p')->group('pay_uid')->having('p>1')->select()), $item['repeats'], 2);
}
}
return array_merge($list);
}
}

View File

@ -8,7 +8,7 @@ use app\common\model\user_recharge\UserRecharge;
use tidy;
/**
* Class 交易底部数据
* Class 交易数据
* @package app\services\statistic
*/
class TradeStatisticLogic extends BaseLogic
@ -596,14 +596,14 @@ class TradeStatisticLogic extends BaseLogic
$whereOrderMoner['paid'] = 1;
$timeKey = $this->TimeConvert($where['create_time'], $isNum);
$where['timeKey'] = $timeKey;
switch ($selectType) {
case "sum":
$totalMoney = $storeOrder->where($whereOrderMoner)->when(isset($whereOrderMoner['create_time']), function ($query) use ($whereOrderMoner) {
$query->whereBetweenTime('create_time', strtotime($whereOrderMoner['create_time']['start_time']), strtotime($whereOrderMoner['create_time']['end_time']));
$totalMoney = $storeOrder->where($whereOrderMoner)->when(isset($where['timeKey']), function ($query) use ($where) {
$query->whereBetweenTime('create_time', strtotime($where['timeKey']['start_time']), strtotime($where['timeKey']['end_time']));
})->sum('pay_price');
break;
case "group":
$where['timeKey'] = $timeKey;
$totalMoney = $storeOrder->where($whereOrderMoner)->when(isset($where['timeKey']), function ($query) use ($where, $group) {
$query->whereBetweenTime('create_time', $where['timeKey']['start_time'], $where['timeKey']['end_time']);
if ($where['timeKey']['days'] == 1) {

View File

@ -0,0 +1,172 @@
<?php
namespace app\admin\logic\statistic;
use app\common\logic\BaseLogic;
use app\common\model\store_order\StoreOrder;
use app\common\model\user\User;
use app\common\model\user\UserVisit;
use app\common\model\user_recharge\UserRecharge;
use Exception;
/**
* Class 用户统计
* @package app\services\statistic
*/
class UserStatisticLogic extends BaseLogic
{
/**
* 基本概况
* @param $where
* @return mixed
*/
public function getBasic($where)
{
$time = explode('-', $where['create_time']);
$time = [strtotime($time[0]), strtotime($time[1])];
if (count($time) != 2) throw new Exception('参数错误');
$userVisit = new UserVisit();
/** @var UserServices $user */
$user = new User();
$order = new StoreOrder();
$user_recharge = new UserRecharge();
// /** @var UserRechargeServices $recharge */
// $recharge = app()->make(UserRechargeServices::class);
// /** @var OtherOrderServices $otherOrder */
// $otherOrder = app()->make(OtherOrderServices::class);
$now['people'] = $userVisit->where('create_time', 'between', $time)->group('uid')->count(); //访客数
$now['browse'] = $userVisit->where('create_time', 'between', $time)->sum('id'); //访问量
$now['newUser'] = $user->where('create_time', 'between', $time)->count(); //新增用户数
$now['payPeople'] = $order->where('create_time', 'between', $time)->group('uid')->count(); //成交用户数
$now['payPercent'] = bcmul((string)($now['people'] > 0 ? bcdiv($now['payPeople'], $now['people'], 4) : 0), '100', 2); //访问-付款转化率
$now['payUser'] = $user->where('create_time', 'between', $time)->where('user_ship', 1)->count(); //激活付费会员数
$now['rechargePeople'] = $user_recharge->where('create_time', 'between', $time)->where('paid', 1)->group('uid')->count(); //充值用户数
$totalPayPrice = $order->where('create_time', 'between', $time)->where('paid', 1)->sum('pay_price');
$now['payPrice'] = floatval($now['payPeople'] > 0 ? bcdiv($totalPayPrice, $now['payPeople'], 2) : 0); //客单价
$now['cumulativeUser'] = $user->count(); //累计用户数
$now['cumulativePayUser'] = 0; //count($otherOrder->getPayUserCount(strtotime($time[1]), $where['channel_type']));//到截至日期有付费会员状态的会员数
$now['cumulativeRechargePeople'] = $user_recharge->where('paid', 1)->group('uid')->count(); //累计充值用户数
$now['cumulativePayPeople'] = $order->where('paid', 1)->group('uid')->count(); //累计成交用户数
$dayNum = ($time[1] - $time[0]) / 86400 + 1;
$time = [
strtotime("-$dayNum days", $time[0]),
strtotime("-1 days", $time[0])
];
// $where['time'] = implode('-', $lastTime);
// $toEndtime = implode('-', [0, $lastTime[1]]);
$last['people'] = $userVisit->where('create_time', 'between', $time)->group('uid')->count(); //访客数
$last['browse'] = $userVisit->where('create_time', 'between', $time)->sum('id'); //访问量
$last['newUser'] = $user->where('create_time', 'between', $time)->count(); //新增用户数
$last['payPeople'] = $order->where('create_time', 'between', $time)->group('uid')->count(); //成交用户数
$last['payPercent'] = bcmul((string)($last['people'] > 0 ? bcdiv($last['payPeople'], $last['people'], 4) : 0), '100', 2); //访问-付款转化率
$last['payUser'] = $user->where('create_time', 'between', $time)->where('user_ship', 1)->count(); //激活付费会员数
$last['rechargePeople'] = $user_recharge->where('create_time', 'between', $time)->where('paid', 1)->group('uid')->count(); //充值用户数
$totalPayPrice = $order->where('create_time', 'between', $time)->where('paid', 1)->sum('pay_price');
$last['payPrice'] = floatval($last['payPeople'] > 0 ? bcdiv($totalPayPrice, $last['payPeople'], 2) : 0); //客单价
$last['cumulativeUser'] = $user->count(); //累计用户数
$last['cumulativePayUser'] = 0; //count($otherOrder->getPayUserCount(strtotime($lastTime[1]) + 86400, $where['channel_type']));//到截至日期有付费会员状态的会员数
$last['cumulativeRechargePeople'] = $user_recharge->where('paid', 1)->group('uid')->count(); //累计充值用户数
$last['cumulativePayPeople'] = $order->where('paid', 1)->group('uid')->count(); //累计成交用户数
//组合数据,计算环比
$data = [];
foreach ($now as $key => $item) {
$data[$key]['num'] = $item;
$data[$key]['last_num'] = $last[$key];
$num = $last[$key] > 0 ? $last[$key] : 1;
$data[$key]['percent'] = bcmul((string)bcdiv((string)($item - $last[$key]), (string)$num, 4), 100, 2);
}
return $data;
}
/**
* 用户趋势
* @param $where
* @param $excel
* @return mixed
*/
public function getTrend($where, $excel = false)
{
$time = explode('-', $where['create_time']);
$time = [strtotime($time[0]), strtotime($time[1])];
$channelType = ''; //$where['channel_type'];
if (count($time) != 2) throw new Exception('参数错误');
$dayCount = ($time[1] - $time[0]) / 86400 + 1;
$data = [];
if ($dayCount == 1) {
$data = $this->trend($time, $channelType, 0, $excel);
} elseif ($dayCount > 1 && $dayCount <= 31) {
$data = $this->trend($time, $channelType, 1, $excel);
} elseif ($dayCount > 31 && $dayCount <= 92) {
$data = $this->trend($time, $channelType, 3, $excel);
} elseif ($dayCount > 92) {
$data = $this->trend($time, $channelType, 30, $excel);
}
return $data;
}
/**
* 用户趋势
* @param $time
* @param $channelType
* @param $num
* @param $excel
* @return array
*/
public function trend($time, $channelType, $num, $excel)
{
$user = new User();
$userVisit = new UserVisit();
$order = new StoreOrder();
$recharge = new UserRecharge();
$newPeople = $visitPeople = $paidPeople = $rechargePeople = $vipPeople = [];
$newPeople['name'] = '新增用户数';
$visitPeople['name'] = '访客数';
$paidPeople['name'] = '成交用户数';
$rechargePeople['name'] = '充值用户';
$vipPeople['name'] = '新增付费用户数';
if ($num == 0) {
$xAxis = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
$timeType = '%H';
} elseif ($num != 0) {
$dt_start = strtotime($time[0]);
$dt_end = strtotime($time[1]);
while ($dt_start <= $dt_end) {
if ($num == 30) {
$xAxis[] = date('Y-m', $dt_start);
$dt_start = strtotime("+1 month", $dt_start);
$timeType = '%Y-%m';
} else {
$xAxis[] = date('Y-m-d', $dt_start);
$dt_start = strtotime("+$num day", $dt_start);
$timeType = '%Y-%m-%d';
}
}
}
$visitPeople = array_column($userVisit->getTrendData($time, $channelType, $timeType, 'count(distinct(uid))'), 'num', 'days');
$newPeople = array_column($user->getTrendData($time, $channelType, $timeType), 'num', 'days');
$paidPeople = array_column($order->getTrendData($time, $channelType, $timeType, 'count(distinct(uid))'), 'num', 'days');
$rechargePeople = array_column($recharge->getTrendData(['paid'=>1],$time, $channelType, $timeType, 'count(distinct(uid))'), 'num', 'days');
$vipPeople = array_column($recharge->getTrendData(['paid'=>1,'price'=>1000],$time, $channelType, $timeType, 'count(distinct(uid))'), 'num', 'days');
$data = $series = [];
foreach ($xAxis as $item) {
$data['新增用户数'][] = isset($newPeople[$item]) ? intval($newPeople[$item]) : 0;
$data['访客数'][] = isset($visitPeople[$item]) ? intval($visitPeople[$item]) : 0;
$data['成交用户数'][] = isset($paidPeople[$item]) ? intval($paidPeople[$item]) : 0;
$data['充值用户'][] = isset($rechargePeople[$item]) ? intval($rechargePeople[$item]) : 0;
$data['新增付费用户数'][] = isset($vipPeople[$item]) ? intval($vipPeople[$item]) : 0;
}
foreach ($data as $key => $item) {
$series[] = ['name' => $key, 'value' => $item];
}
return compact('xAxis', 'series');
}
}

View File

@ -52,6 +52,7 @@ class SystemStoreLogic extends BaseLogic
'street' => $params['street_code'],
'is_store' => $params['is_store'] ?? 0,
'is_send' => $params['is_send'] ?? 0,
'security_deposit' => $params['security_deposit'] ?? 0,
]);
$taff = [
'store_id' => $store['id'],
@ -111,6 +112,8 @@ class SystemStoreLogic extends BaseLogic
'bank_address' => $params['bank_address']??'',
'realname' => $params['realname']??'',
'default_delivery' => $params['default_delivery'] ?? 2,
'security_deposit' => $params['security_deposit'] ?? 0,
]);
$res=SystemStoreStaff::where('store_id', $params['id'])->where('is_admin', 1)->where('account', $params['phone'])->find();
if($params['password']!=''&&$res){

View File

@ -25,19 +25,19 @@ class StoreOrder extends BaseModel
public function store()
{
return $this->hasOne(SystemStore::class, 'id','store_id')
->bind(['store_name'=>'name', 'store_phone'=>'phone','store_detailed_address'=>'detailed_address','store_simple_address'=>'address']);
return $this->hasOne(SystemStore::class, 'id', 'store_id')
->bind(['store_name' => 'name', 'store_phone' => 'phone', 'store_detailed_address' => 'detailed_address', 'store_simple_address' => 'address']);
}
public function getPayTypeNameTextAttr($value, $data)
{
$status = PayEnum::getPaySceneDesc($value)??'';
$status = PayEnum::getPaySceneDesc($value) ?? '';
return $status;
}
public function getStatusNameTextAttr($value, $data)
{
$status = OrderEnum::getOrderType($data['status'])??'';
$status = OrderEnum::getOrderType($data['status']) ?? '';
return $status;
}
@ -55,5 +55,25 @@ class StoreOrder extends BaseModel
{
return $this->hasOne(SystemStoreStaff::class, 'id', 'staff_id')->bind(['staff_name']);
}
/**
* 用户趋势数据
* @param $time
* @param $type
* @param $timeType
* @return mixed
*/
public function getTrendData($time, $type, $timeType, $str)
{
return $this->when($type != '', function ($query) use ($type) {
$query->where('channel_type', $type);
})->where('paid', 1)->where('paid', '>=', 0)->where(function ($query) use ($time) {
if ($time[0] == $time[1]) {
$query->whereDay('create_time', $time[0]);
} else {
$time[1] = $time[1] + 86400;
$query->whereTime('create_time', 'between', $time);
}
})->field("FROM_UNIXTIME(create_time,'$timeType') as days,$str as num")
->group('days')->select()->toArray();
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace app\common\model\store_product_log;
use app\common\model\BaseModel;
use think\model\concern\SoftDelete;
/**
* 商品统计模型
* Class StoreProductLog
* @package app\common\model\store_product_log
*/
class StoreProductLog extends BaseModel
{
use SoftDelete;
protected $name = 'store_product_log';
protected $deleteTime = 'delete_time';
}

View File

@ -23,9 +23,9 @@ class User extends BaseModel
public function userShip()
{
return $this->hasOne(UserShip::class,'id','user_ship')
// return $this->hasOne(UserShip::class,'user_ship','id')
->bind(['vip_name'=>'title','discount','limit']);
return $this->hasOne(UserShip::class, 'id', 'user_ship')
// return $this->hasOne(UserShip::class,'user_ship','id')
->bind(['vip_name' => 'title', 'discount', 'limit']);
}
/**
@ -113,7 +113,7 @@ class User extends BaseModel
*/
public function getAvatarAttr($value)
{
if($value){
if ($value) {
return trim($value) ? FileService::getFileUrl($value) : '';
}
}
@ -168,4 +168,25 @@ class User extends BaseModel
// }
return $sn;
}
}
/**
* 获取用户统计数据
* @param $time
* @param $type
* @param $timeType
* @return mixed
*/
public function getTrendData($time, $type, $timeType)
{
return $this->when($type != '', function ($query) use ($type) {
$query->where('user_type', $type);
})->where(function ($query) use ($time) {
if ($time[0] == $time[1]) {
$query->whereDay('create_time', $time[0]);
} else {
$time[1] = $time[1] + 86400;
$query->whereTime('create_time', 'between', $time);
}
})->field("FROM_UNIXTIME(create_time,'$timeType') as days,count(id) as num")->group('days')->select()->toArray();
}
}

View File

@ -19,4 +19,25 @@ class UserVisit extends BaseModel
protected $deleteTime = 'delete_time';
/**
* 用户趋势数据
* @param $time
* @param $type
* @param $timeType
* @param $str
* @return mixed
*/
public function getTrendData($time, $type, $timeType, $str)
{
return $this->when($type != '', function ($query) use ($type) {
$query->where('channel_type', $type);
})->where(function ($query) use ($time) {
if ($time[0] == $time[1]) {
$query->whereDay('create_time', $time[0]);
} else {
$time[1] = $time[1] + 86400;
$query->whereTime('create_time', 'between', $time);
}
})->field("FROM_UNIXTIME(create_time,'$timeType') as days,$str as num")->group('days')->select()->toArray();
}
}

View File

@ -18,5 +18,26 @@ class UserRecharge extends BaseModel
protected $name = 'user_recharge';
protected $deleteTime = 'delete_time';
}
/**
* 获取充值统计曲线
* @param $time
* @param $type
* @param $timeType
* @param string $str
* @return mixed
*/
public function getTrendData($where,$time, $type, $timeType, $str = 'count(id)')
{
return $this->when($type != '', function ($query) use ($type) {
$query->where('channel_type', $type);
})->where($where)->where(function ($query) use ($time) {
if ($time[0] == $time[1]) {
$query->whereDay('create_time', $time[0]);
} else {
$time[1] = $time[1] + 86400;
$query->whereTime('create_time', 'between', $time);
}
})->field("FROM_UNIXTIME(create_time,'$timeType') as days, " . $str . "as num")
->group('days')->select()->toArray();
}
}