jingcai-php/app/Console/Commands/GenerateCustomerRanking.php

169 lines
6.1 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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) {
// 一站成名: 最后一单是红的并且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;
}
}