diff --git a/app/Console/Commands/Dealer/ManageSubsidySettleCommand.php b/app/Console/Commands/Dealer/ManageSubsidySettleCommand.php index 2610d69f..bf8f0787 100644 --- a/app/Console/Commands/Dealer/ManageSubsidySettleCommand.php +++ b/app/Console/Commands/Dealer/ManageSubsidySettleCommand.php @@ -6,9 +6,9 @@ use App\Enums\DealerLvl; use App\Enums\DealerManageSubsidyStatus; use App\Models\Dealer; use App\Models\DealerManageSubsidy; +use App\Models\DealerManageSubsidyLog; use Illuminate\Console\Command; use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; class ManageSubsidySettleCommand extends Command @@ -18,8 +18,7 @@ class ManageSubsidySettleCommand extends Command * * @var string */ - protected $signature = 'dealer:manage-subsidy-settle - {--force : 是否强制操作运行}'; + protected $signature = 'dealer:manage-subsidy-settle'; /** * The console command description. @@ -42,67 +41,58 @@ class ManageSubsidySettleCommand extends Command | | 管理津贴结算时间为每月的5号和20号。 | - | 5号结算上月20号0点到当月4号23点59分59秒的管理津贴 - | 20号结算当月5号0点到19号23点59分59秒的管理津贴 + | 5号结算上月20号0点0分0秒到当月4号23点59分59秒的管理津贴 + | 20号结算当月5号0点0分0秒到19号23点59分59秒的管理津贴 | */ $tz = now(); if ($tz->day >= 20) { + // 结算当月5号-19号的管理津贴 $startAt = $tz->copy()->setDay(5)->startOfDay(); $endAt = $tz->copy()->setDay(19)->endOfDay(); } elseif ($tz->day >= 5) { + // 结算上月20号-到当月4号的管理津贴 $startAt = $tz->copy()->subMonthNoOverflow()->set('day', 20)->startOfDay(); $endAt = $tz->copy()->set('day', 4)->endOfDay(); } else { + // 结算上月5号-到19号的管理津贴 $startAt = $tz->copy()->subMonthNoOverflow()->setDay(5)->startOfDay(); - $endAt = $startAt->copy()->subMonthNoOverflow()->setDay(19)->endOfDay(); + $endAt = $tz->copy()->subMonthNoOverflow()->setDay(19)->endOfDay(); } $head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】'; - $cacheKey = $this->cacheKey($startAt, $endAt); + $this->info("{$head}------------[开始]管理津贴结算------------".PHP_EOL); - // 如果不是强制执行,则需检查是否已结算过 - if (! $this->option('force') && Cache::has($cacheKey)) { - return $this->warn("{$head}管理津贴已结算"); - } + $this->info("{$head}管理津贴初始化..."); + $this->initializeManageSubsidies($startAt, $endAt, 500); + $this->info("{$head}管理津贴初始化完成".PHP_EOL); - $this->info("{$head}------------[开始]管理津贴结算------------"); - - if ($this->option('force')) { - $this->info("{$head}正在删除旧数据..."); - DealerManageSubsidy::where('start_at', $startAt)->where('end_at', $endAt)->delete(); - $this->info("{$head}数据删除成功"); - } - - $this->info("{$head}数据写入中..."); - $this->settle($startAt, $endAt, 500); - $this->info("{$head}写入成功, 总耗时: ".$this->formatDuration($tz->diffInMilliseconds(now(), false))); + $this->info("{$head}管理津贴结算..."); + $this->settleManageSubsidies($startAt, $endAt); + $this->info("{$head}管理津贴结算完成".PHP_EOL); + $this->info("{$head}Done! 总耗时: ".$this->formatDuration($tz->diffInMilliseconds(now(), false))); $this->info("{$head}------------[结束]管理津贴结算------------".PHP_EOL); - Cache::put($cacheKey, 1, $tz->addDays(17)); - return 0; } /** - * 管理津贴结算结算 + * 初始化管理津贴 * * @param \Illuminate\Support\Carbon $startAt * @param \Illuminate\Support\Carbon $endAt * @param int $count * @return void */ - protected function settle(Carbon $startAt, Carbon $endAt, $count = 200): void + protected function initializeManageSubsidies(Carbon $startAt, Carbon $endAt, $count = 200): void { $feeRate = app_settings('dealer.fee_rate'); - $lastId = Cache::get( - $cacheKey = $this->cacheKey($startAt, $endAt).':last_id' - ); + $lastId = $this->getLastDealerId($startAt, $endAt); do { $dealers = Dealer::where('lvl', '>=', DealerLvl::Secondary) @@ -115,67 +105,89 @@ class ManageSubsidySettleCommand extends Command break; } - $earnings = []; + $manageSubsidies = []; $tz = now()->toDateTimeString(); foreach ($dealers as $dealer) { - [$totalAmount, $remark] = $this->calculateTotalAmount($dealer, $startAt, $endAt); - - // 如果 补贴总金额 > 0,则添加管理者补贴记录 - if (bccomp($totalAmount, '0', 2) === 1) { - // 计算手续费 - $fee = bcmul($totalAmount, bcdiv($feeRate, '100', 10), 2); - - $earnings[] = [ - 'user_id' => $dealer->user_id, - 'total_amount' => $totalAmount, - 'real_amount' => bcsub($totalAmount, $fee, 2), - 'fee' => $fee, - 'fee_rate' => $feeRate, - 'start_at' => $startAt, - 'end_at' => $endAt, - 'lvl' => $dealer->lvl, - 'is_manager' => $dealer->is_manager, - 'status' => DealerManageSubsidyStatus::Pending, - 'remark' => $remark, - 'created_at' => $tz, - 'updated_at' => $tz, - ]; - } + $manageSubsidies[] = [ + 'user_id' => $dealer->user_id, + 'total_amount' => 0, + 'real_amount' => 0, + 'fee' => 0, + 'fee_rate' => $feeRate, + 'start_at' => $startAt, + 'end_at' => $endAt, + 'lvl' => $dealer->lvl, + 'is_manager' => $dealer->is_manager, + 'status' => DealerManageSubsidyStatus::Pending, + 'is_settle' => false, + 'created_at' => $tz, + 'updated_at' => $tz, + ]; $lastId = $dealer->id; } - DealerManageSubsidy::insert($earnings); + DealerManageSubsidy::insert($manageSubsidies); - Cache::put($cacheKey, $lastId, $endAt); - - unset($dealers, $earnings); + unset($dealers, $manageSubsidies); } while ($dealersCount == $count); + } - Cache::forget($cacheKey); + /** + * 结算管理津贴 + * + * @param \Illuminate\Support\Carbon $startAt + * @param \Illuminate\Support\Carbon $endAt + * @return void + */ + protected function settleManageSubsidies(Carbon $startAt, Carbon $endAt) + { + DealerManageSubsidy::where('start_at', $startAt)->where('end_at', $endAt)->where('is_settle', false)->chunkById(500, function ($subsidies) { + foreach ($subsidies as $subsidy) { + $this->settleManageSubsidy($subsidy); + } + }); + } + + /** + * 结算单挑管理津贴 + * + * @param \App\Models\DealerManageSubsidy + * @return void + */ + protected function settleManageSubsidy(DealerManageSubsidy $subsidy) + { + [$totalAmount, $remark] = $this->calculateTotalAmount($subsidy); + + $fee = bcmul($totalAmount, bcdiv($subsidy->fee_rate, '100', 5), 2); + + $subsidy->forceFill([ + 'total_amount' => $totalAmount, + 'real_amount' => bcsub($totalAmount, $fee, 2), + 'fee' => $fee, + 'remark' => $remark, + 'is_settle' => true, + ])->save(); } /** * 计算补贴总金额 * - * @param \App\Models\Dealer - * @param \Illuminate\Support\Carbon $startAt - * @param \Illuminate\Support\Carbon $endAt - * @return array + * @param \App\Models\DealerManageSubsidy + * @return void */ - protected function calculateTotalAmount(Dealer $dealer, Carbon $startAt, Carbon $endAt): array + protected function calculateTotalAmount(DealerManageSubsidy $subsidy): array { - $subsidyLogs = $dealer->manageSubsidyLogs() - ->with(['product']) - ->select([ - 'product_id', - DB::raw('sum(sales_volume) as sales_volume'), - DB::raw('sum(total_amount) as total_amount'), - ]) - ->whereBetween('order_completed_at', [$startAt, $endAt]) - ->groupBy('product_id') - ->get(); + $subsidyLogs = DealerManageSubsidyLog::select([ + 'product_id', + DB::raw('sum(sales_volume) as sales_volume'), + DB::raw('sum(total_amount) as total_amount'), + ])->where( + 'user_id', $subsidy->user_id + )->whereBetween( + 'order_completed_at', [$subsidy->start_at, $subsidy->end_at] + )->groupBy('product_id')->get(); // 补贴总金额 $totalAmount = 0; @@ -196,15 +208,20 @@ class ManageSubsidySettleCommand extends Command } /** - * 生成缓存的 key + * 获取最后 * * @param \Illuminate\Support\Carbon $startAt * @param \Illuminate\Support\Carbon $endAt - * @return void + * @return int|null */ - protected function cacheKey(Carbon $startAt, Carbon $endAt) + protected function getLastDealerId(Carbon $startAt, Carbon $endAt): ?int { - return $startAt->format('Ymd').'_'.$endAt->format('Ymd').'_dealer_manage_subsidy'; + $lastManageSubsidy = DealerManageSubsidy::where('start_at', $startAt) + ->where('end_at', $endAt) + ->latest('id') + ->first(); + + return $lastManageSubsidy?->dealer?->id; } /** diff --git a/app/Models/DealerManageSubsidy.php b/app/Models/DealerManageSubsidy.php index af1344ab..dc99b874 100644 --- a/app/Models/DealerManageSubsidy.php +++ b/app/Models/DealerManageSubsidy.php @@ -11,6 +11,7 @@ class DealerManageSubsidy extends Model protected $attributes = [ 'lvl' => DealerLvl::None, 'is_manager' => false, + 'is_settle' => false, ]; protected $casts = [ @@ -19,6 +20,7 @@ class DealerManageSubsidy extends Model 'start_at' => 'datetime', 'end_at' => 'datetime', 'status' => DealerManageSubsidyStatus::class, + 'is_settle' => 'bool', ]; protected $fillable = [ @@ -33,5 +35,14 @@ class DealerManageSubsidy extends Model 'end_at', 'status', 'remark', + 'is_settle', ]; + + /** + * 此管理津贴所属的经销商 + */ + public function dealer() + { + return $this->belongsTo(Dealer::class, 'user_id', 'user_id'); + } } diff --git a/database/migrations/2022_01_17_135120_add_is_settle_to_dealer_manage_subsidies_table.php b/database/migrations/2022_01_17_135120_add_is_settle_to_dealer_manage_subsidies_table.php new file mode 100644 index 00000000..f6b92b41 --- /dev/null +++ b/database/migrations/2022_01_17_135120_add_is_settle_to_dealer_manage_subsidies_table.php @@ -0,0 +1,32 @@ +boolean('is_settle')->default(0)->comment('是否结算'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('dealer_manage_subsidies', function (Blueprint $table) { + $table->dropColumn('is_settle'); + }); + } +}