优化 收益

This commit is contained in:
iVampireSP.com 2022-11-19 12:37:18 +08:00
parent e94c86eb53
commit 042468ba23
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
11 changed files with 157 additions and 210 deletions

View File

@ -2,7 +2,6 @@
namespace App\Console\Commands;
use App\Http\Controllers\Modules\ModuleController;
use App\Models\Module;
use Illuminate\Console\Command;
@ -39,37 +38,33 @@ public function __construct()
*/
public function handle()
{
$moduleController = new ModuleController();
$rate = config('drops.module_rate');
$this->warn('开始计算集成模块收益。');
$this->warn('当前时间: ' . now());
$this->warn('比例: 1:' . $rate . ' (1 元 = ' . $rate . ' Drops)');
Module::chunk(100, function ($modules) use ($rate, $moduleController) {
Module::chunk(100, function ($modules) {
foreach ($modules as $module) {
$report = $moduleController->calcModule($module);
$this->warn('模块: ' . $module->name);
$years = $module->calculate();
foreach ($years as $year => $months) {
// 排序 months 从小到大
ksort($months);
$income = $report['transactions']['this_month']['drops'] / $rate;
$total = 0;
$total_should = 0;
if ($income < 0) {
$income = 0;
foreach ($months as $month => $m) {
$total += $m['balance'];
$total_should += $m['should_balance'];
$this->info("{$module->name} {$year}{$month}月 实收: {$total}元 应得: {$total_should}");
}
}
// 取 2 位
$income = round($income, 2);
$text = $module->name . " 收益 {$income}";
$this->info($text);
}
});
$this->warn('计算模块收益完成。');
$this->warn('完成时间: ' . now());
$this->warn('比例: 1:' . $rate . ' (1 元 = ' . $rate . ' Drops)');
return 1;
}

View File

@ -2,6 +2,7 @@
namespace App\Console;
use App\Jobs\AutoCloseWorkOrder;
use App\Jobs\CheckAndChargeBalance;
use App\Jobs\CheckHostIfExistsOnModule;
use App\Jobs\ClearTasks;
@ -9,6 +10,7 @@
use App\Jobs\HostCost;
use App\Jobs\Module\FetchModule;
use App\Jobs\Module\PushWorkOrder;
use App\Jobs\SendModuleEarnings;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@ -23,22 +25,35 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// 清理过期的 Token
$schedule->command('sanctum:prune-expired --hours=24')->daily();
// dispatch HostCost job
// 扣费
$schedule->job(new HostCost())->everyFiveMinutes();
// $schedule->job(new UserSave())->everyTenMinutes();
$schedule->job(new FetchModule())->withoutOverlapping()->everyMinute();
// $schedule->job(new Remote\PushHost())->everyMinute()->onOneServer();
$schedule->job(new PushWorkOrder())->everyMinute()->onOneServer();
// 获取模块暴露的信息(服务器等)
$schedule->job(new FetchModule())->withoutOverlapping()->everyMinute();
// 推送工单
$schedule->job(new PushWorkOrder())->everyMinute()->onOneServer();
// 自动关闭工单
$schedule->job(new AutoCloseWorkOrder())->everyMinute()->onOneServer();
// 清理任务
$schedule->job(new ClearTasks())->weekly();
// 删除暂停或部署时间超过 3 天以上的主机
$schedule->job(new DeleteHost())->hourly();
// 检查主机是否存在于模块
$schedule->job(new CheckHostIfExistsOnModule())->everyThirtyMinutes()->withoutOverlapping()->onOneServer();
// 检查未充值的订单,并充值
$schedule->job(new CheckAndChargeBalance())->everyFiveMinutes()->onOneServer()->withoutOverlapping();
// 发送模块收益
$schedule->job(new SendModuleEarnings())->dailyAt('20:00');
}
/**

View File

@ -1,61 +0,0 @@
<?php
namespace App\Jobs;
use App\Models\Module;
use App\Models\Transaction;
use Illuminate\Support\Facades\Cache;
class CalcModule extends Job
{
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// begin of this month
$beginOfMonth = now()->startOfMonth();
// end of this month
$endOfMonth = now()->endOfMonth();
Module::chunk(100, function ($modules) use ($beginOfMonth, $endOfMonth) {
foreach ($modules as $module) {
$this_month = Transaction::where('module_id', $module->id)->where('type', 'payout')->whereBetween('created_at', [$beginOfMonth, $endOfMonth]);
// this month transactions
$this_month = [
'balances' => $this_month->sum('outcome'),
'drops' => $this_month->sum('outcome_drops')
];
Cache::put('this_month_balance_and_drops_' . $module->id, $this_month, 60 * 24 * 30);
// last month transactions
$last_moth = Transaction::where('module_id', $module->id)->where('type', 'payout')->whereBetween('created_at', [$beginOfMonth, $endOfMonth]);
$last_moth = [
'balances' => $last_moth->sum('outcome'),
'drops' => $last_moth->sum('outcome_drops')
];
Cache::put('last_month_balance_and_drops_' . $module->id, $last_moth, 60 * 24 * 30);
}
});
return 0;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Jobs;
use App\Models\Module;
use App\Notifications\ModuleEarnings;
use Illuminate\Support\Facades\Cache;
class SendModuleEarnings extends Job
{
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
Module::chunk(100, function ($modules) {
foreach ($modules as $module) {
(new ModuleEarnings($module))
->toGroup($module->calculate());
}
});
}
}

View File

@ -1,56 +0,0 @@
<?php
namespace App\Jobs;
use App\Models\Module;
use App\Notifications\ModuleEarnings;
use Illuminate\Support\Facades\Cache;
class SendThisMonthModuleEarnings extends Job
{
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
$default = [
'balance' => 0,
'drops' => 0,
];
$rate = config('drops.module_rate');
Module::chunk(
100,
function ($modules) use ($default, $rate) {
foreach ($modules as $module) {
$data = [
'transactions' => [
'this_month' => Cache::get('this_month_balance_and_drops_' . $module->id, $default),
'last_month' => Cache::get('last_month_balance_and_drops_' . $module->id, $default),
],
'rate' => $rate,
];
(new ModuleEarnings($module))
->toGroup($data);
}
}
);
}
}

View File

@ -11,6 +11,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsTo as BelongsToAlias;
use Illuminate\Database\Eloquent\Relations\HasMany as HasManyAlias;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
// use Illuminate\Database\Eloquent\SoftDeletes;
@ -157,6 +158,54 @@ public function cost($price = null, $auto = true): bool
$transaction->reduceDrops($this->user_id, $this->id, $this->module_id, $auto, $real_price);
/** 统计收益开始 */
$current_month = now()->month;
$current_year = now()->year;
$cache_key = 'module_earning_' . $this->module_id;
$rate = (int)config('drops.rate');
$commission = (float)config('drops.commission');
// 换成 余额
$balance = round($real_price / $rate, 2);
$should_balance = round($balance * $commission, 2);
// 应得的余额
$should_balance = $balance - $should_balance;
$earnings = Cache::get($cache_key, []);
if (!isset($earnings[$current_year])) {
$earnings[$current_year] = [];
}
if (isset($earnings[$current_year][$current_month])) {
$earnings[$current_year][$current_month]['balance'] += $balance;
$earnings[$current_year][$current_month]['should_balance'] += $should_balance;
$earnings[$current_year][$current_month]['drops'] += $real_price;
} else {
$earnings[$current_year][$current_month] = [
'balance' => $balance,
// 应得(交了手续费)
'should_balance' => $should_balance,
'drops' => $real_price
];
}
// 删除 前 3 年的数据
if (count($earnings) > 3) {
$earnings = array_slice($earnings, -3, 3, true);
}
// 保存 1 年
Cache::put($cache_key, $earnings, 24 * 60 * 60 * 365);
/** 统计收益结束 */
broadcast(new UserEvent($this->user_id, 'balances.drops.reduced', $this->user));
// 检测用户余额是否足够

View File

@ -172,17 +172,8 @@ public function check($module_id = null)
#[ArrayShape(['transactions' => "array"])]
public function calculate(): array
{
$cache_key = 'module_earning_' . $this->id;
$default = [
'balance' => 0,
'drops' => 0,
];
return [
'transactions' => [
'this_month' => Cache::get('this_month_balance_and_drops_' . $this->id, $default),
'last_month' => Cache::get('last_month_balance_and_drops_' . $this->id, $default),
]
];
return Cache::get($cache_key, []);
}
}

View File

@ -162,13 +162,11 @@ public function reduceDrops($user_id, $host_id, $module_id, $auto = 1, $amount =
Cache::forever($cache_key, $current_drops);
// if ($auto) {
// $description = '平台按时间自动扣费。';
// } else {
// $description = '集成模块发起的扣费。';
// }
if (!$auto) {
$description = '集成模块发起的扣费。';
$this->addPayoutDrops($user_id, $amount, $description, $host_id, $module_id);
}
// $this->addPayoutDrops($user_id, $amount, $description, $host_id, $module_id);
}
public function reduceAmount($user_id, $amount = 0, $description = '扣除费用请求。')

View File

@ -4,6 +4,7 @@
use App\Models\Module;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
@ -29,31 +30,47 @@ public function __construct(Module $module)
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
* @return MailMessage
*/
public function toGroup($notifiable)
{
if (!isset($notifiable['transactions'])) {
return;
}
$module = $this->module;
$view = 'notifications.module.earnings';
// make wecom_key visible
$wecom_key = $module->wecom_key ?? config('settings.wecom.robot_hook.billing');
$text = "# {$module->name} 收益";
foreach ($notifiable as $year => $months) {
// 排序 months 从小到大
ksort($months);
$total = 0;
$total_should = 0;
foreach ($months as $month => $m) {
$total += $m['balance'];
$total_should += $m['should_balance'];
$text .= <<<EOF
==========
{$year} {$month}
实收: {$total}
应得: {$total_should}
EOF;
}
}
$resp = Http::post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' . $wecom_key, [
'msgtype' => 'markdown',
'markdown' => [
'content' => view($view, [
'module' => $module,
'data' => $notifiable,
])->render(),
'content' => $text,
],
]);
if ($resp->failed()) {
Log::error('发送模块盈利到企业微信时失败', [
'module' => $module->id,

View File

@ -2,6 +2,6 @@
return [
'rate' => 1000,
'decimal' => 100000,
'module_rate' => 825,
// 提成
'commission' => 0.1,
];

View File

@ -1,40 +0,0 @@
## 收益汇报
# {{ $module->name }}
==================================
## 本月
#### 现金 {{ round($data['transactions']['this_month']['balances'], 2) }} 元
#### Drops {{ round($data['transactions']['this_month']['drops'], 4) }}
#### 合计 {{ round($data['transactions']['this_month']['balances'] + $data['transactions']['this_month']['drops'] / $data['rate'], 2) }} 元
==================================
## 上个月
#### 现金 {{ round($data['transactions']['last_month']['balances'], 2) }} 元
#### Drops {{ round($data['transactions']['last_month']['drops'], 4) }}
#### 合计 {{ round($data['transactions']['last_month']['balances'] + $data['transactions']['last_month']['drops'] / $data['rate'], 2) }} 元
{{--
$module = $this->http->get('modules')->json()['data'];
$total = $module['transactions']['this_month']['balances'];
$drops = $module['transactions']['this_month']['drops'] / $module['rate'];
if ($drops < 0) { $drops=0; } $total +=$drops; $total=round($total, 2); $module=[ 'balances'=>
$module['transactions']['this_month']['balances'],
'drops' => $module['transactions']['this_month']['drops'],
'total' => $total,
];
<h4>收益</h4>
<div>
<h3>
本月收益
</h3>
<p>
直接扣费金额: {{ $module['balances'] }}
</p>
<p>
Drops: {{ $module['drops'] }}
</p>
<p>本月总计收入 CNY: {{ $module['total'] }} </p>
</div> --}}