176 lines
6.4 KiB
PHP
Executable File
176 lines
6.4 KiB
PHP
Executable File
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Enums\LottState;
|
||
use App\Enums\OrderType;
|
||
use App\Enums\PayState;
|
||
use App\Model\Customer\Customer;
|
||
use App\Model\Customer\CustomerRanking;
|
||
use App\Model\Order;
|
||
use App\Utils\Helps;
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class GenerateCustomerRanking extends Command
|
||
{
|
||
/**
|
||
* 这个就是命令名称
|
||
*/
|
||
protected $signature = 'gen:customer_ranking';
|
||
|
||
/**
|
||
* 命令的说明描述
|
||
* @var string
|
||
*/
|
||
protected $description = '生成用户的,一站成名,七日命中率,连红榜信息';
|
||
|
||
/**
|
||
* 创建命令的构造方法。
|
||
* @param string $words 传入的字符参数
|
||
* @return void
|
||
*/
|
||
public function __construct()
|
||
{
|
||
parent::__construct();
|
||
}
|
||
|
||
public function handle()
|
||
{
|
||
$cdate = date('Ymd');
|
||
Customer::chunkById(100, function ($customers) use ($cdate) {
|
||
foreach ($customers as $customer) {
|
||
$this->generateRankingData($customer, $cdate);
|
||
}
|
||
});
|
||
}
|
||
|
||
public function generateRankingData($customer, $cdate)
|
||
{
|
||
$orders = $this->last7DayOrders($customer->id);
|
||
|
||
$day7 = $this->dayxReport($orders);
|
||
|
||
if (@$day7['rank_fame'] || @$day7['rank_hit_rate'] || @$day7['rank_profit']) {
|
||
$day5 = $this->dayxReport($orders, 5);
|
||
$day3 = $this->dayxReport($orders, 3);
|
||
$day2 = $this->dayxReport($orders, 2);
|
||
|
||
$insertData = array_merge($day7, $day5, $day3, $day2);
|
||
|
||
$customerRanking = CustomerRanking::where('customer_id', $customer->id)
|
||
->where('cdate', $cdate)
|
||
->first();
|
||
if (!$customerRanking) {
|
||
$customerRanking = new CustomerRanking();
|
||
$customerRanking->cdate = $cdate;
|
||
$customerRanking->customer_id = $customer->id;
|
||
$customerRanking->shop_id = $customer->shop_id;
|
||
}
|
||
$insertData['rank_fame'] = $insertData['rank_fame']??0;
|
||
$insertData['rank_hit_rate'] = $insertData['rank_hit_rate']??0;
|
||
$insertData['rank_profit'] = $insertData['rank_profit']??0;
|
||
|
||
foreach ($insertData as $field => $val) {
|
||
$customerRanking->{$field} = $val;
|
||
}
|
||
$customerRanking->save();
|
||
|
||
$winNum = collect($orders)->whereIn('lottery_state', [LottState::WIN, LottState::SEND])->count();
|
||
$lossNum = collect($orders)->where('lottery_state', LottState::LOSS)->count();
|
||
Customer::where('id', $customer->id)
|
||
->update([
|
||
'win_alway_num' => $customerRanking->wined_max7,
|
||
'win_hit_rate' => $winNum > 0 ? ($lossNum/$winNum) * 1000 : 0,
|
||
]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection $orderRawData
|
||
* @param $dayx
|
||
* @return array
|
||
*/
|
||
public function dayxReport($orderRawData, $dayx = 7)
|
||
{
|
||
$orders = $orderRawData->where('created_date', '>=', date('Ymd', strtotime("-{$dayx} day")));
|
||
$results = $orders->where('wined', '<>', -1);
|
||
$lastOrder = $results->first();
|
||
$dateArray = $orders->pluck('created_date')->toArray();
|
||
$resultArray = $results->where('wined', '<>', -1)->pluck('wined')->toArray();
|
||
|
||
// 最近三单连红次数
|
||
$last3Array = $orders->where('lottery_state', '<>', LottState::WAIT)->shift(3);
|
||
$last3WinArray = $last3Array->pluck('wined')->toArray();
|
||
$last3Max = Helps::findMaxConsecutive($last3WinArray, 1);
|
||
|
||
|
||
$danWinCount = $orders->where('wined', 1)->count();
|
||
$danLossCount = $orders->where('wined', 0)->count();
|
||
$danCount = $orders->count();
|
||
|
||
$dateArray = array_values(array_unique($dateArray));
|
||
$dayMax = Helps::findMaxConsecutiveDays($dateArray);
|
||
$lossMax = Helps::findMaxConsecutive($resultArray, 0);
|
||
$winMax = Helps::findMaxConsecutive($resultArray, 1);
|
||
|
||
$baseInfo = [
|
||
'total_num' . $dayx => $orders->count(),
|
||
'wined_num' . $dayx => $danWinCount,
|
||
'wined_max' . $dayx => $winMax,
|
||
'loss_max' . $dayx => $lossMax,
|
||
'loss_num' . $dayx => $danLossCount,
|
||
'total_money' . $dayx => $results->sum('money'),
|
||
'total_prize' . $dayx => $results->sum('lottery_prize'),
|
||
'last_prize' => $lastOrder ? $lastOrder->lottery_prize : 0,
|
||
];
|
||
|
||
if ($dayx == 7) {
|
||
// 最近连赢次数
|
||
$baseInfo['wined_last7'] = 0;
|
||
foreach ($orders as $item) {
|
||
if ($item->wined == 1) {
|
||
$baseInfo['wined_last7']++;
|
||
}
|
||
}
|
||
// 一站成名: 最后一单是红的,并且7日内有连续3天都红
|
||
if ($lastOrder && $lastOrder->wined == 1 && $lossMax < 3 && $dayMax >= 3) {
|
||
$baseInfo['rank_fame'] = 1;
|
||
}
|
||
|
||
// 命中: 7日内发单>=4,并且至少红2单,并且7日内至少连续3日发单
|
||
if ($lossMax < 3 && $danCount >= 4 && $dayMax >= 3 ) {
|
||
$baseInfo['rank_hit_rate'] = 1;
|
||
}
|
||
|
||
// 盈利榜: 7日内至少连续3日发单,并且最近3单至少红2单
|
||
if ($dayMax >= 3 && $last3Max >= 2) {
|
||
$baseInfo['rank_profit'] = 1;
|
||
$baseInfo['profit_lv7'] = Helps::percentage($baseInfo['total_prize'.$dayx], $baseInfo['total_money'.$dayx]);
|
||
}
|
||
}
|
||
return $baseInfo;
|
||
}
|
||
|
||
/**
|
||
* @param $customerId
|
||
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
|
||
*/
|
||
public function last7DayOrders($customerId)
|
||
{
|
||
$orders = Order::select([
|
||
'id', 'pid', 'money', 'type', 'type_mode', 'created_date', 'customer_id', 'shop_id', 'lottery_state', 'lottery_prize',
|
||
DB::raw('CASE lottery_state WHEN 3 THEN -1 WHEN 2 THEN 0 ELSE 1 END AS wined')
|
||
])
|
||
->where('customer_id', $customerId)
|
||
->where('type', OrderType::FADAN)
|
||
->where('created_date', '>=', date('Ymd', strtotime('-7 day')))
|
||
->where('pay_state', PayState::SUCCESS)
|
||
->whereIn('lottery_state', [LottState::WAIT, LottState::WIN, LottState::SEND, LottState::LOSS])
|
||
->orderBy('id', 'desc')
|
||
->get();
|
||
return $orders;
|
||
}
|
||
|
||
}
|