| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- <?php
- declare(strict_types=1);
- namespace plugin\saiadmin\app\service;
- use plugin\saiadmin\app\model\water\{WaterModel,WaterAgent,WaterEnterprise,WaterOrder,WaterCommission};
- use plugin\saiadmin\app\service\agent\{AgentFilters,AgentHierarchyPolicy,AgentAccessPolicy};
- use plugin\saiadmin\app\service\agent\WaterCommissionPolicy;
- use plugin\saiadmin\exception\ApiException;
- /** Read facade. Water sales never reuse legacy device-rental income or profit percentages. */
- final class WaterAgentDashboard
- {
- private readonly \DateTimeImmutable $now;
- public function __construct(?\DateTimeImmutable $now=null) { $this->now=$now??new \DateTimeImmutable('now',new \DateTimeZone('Asia/Shanghai')); }
- private function rows(): array {
- $end=$this->now->format('Y-m-d H:i:s'); $start=$this->now->format('Y-m-01 00:00:00');
- $enterprises=WaterEnterprise::query()->selectRaw('agent_id, COUNT(*) AS enterprise_count')->groupBy('agent_id');
- $sales=WaterOrder::query()->alias('o')->join('sa_water_enterprise as e','e.id','=','o.enterprise_id')
- ->where('o.created_at','<=',$end)
- ->selectRaw('e.agent_id, SUM(o.amount_cents) AS sales_cents, SUM(CASE WHEN o.created_at >= ? THEN o.amount_cents ELSE 0 END) AS month_cents',[$start])->groupBy('e.agent_id');
- $rows=WaterAgent::query()->alias('a')
- ->leftJoin('sa_system_user as u',function ($join) { $join->on('u.id','=','a.user_id')->whereNull('u.delete_time'); })
- ->leftJoinSub($enterprises,'customers','customers.agent_id','=','a.id')
- ->leftJoinSub($sales,'sales','sales.agent_id','=','a.id')
- ->selectRaw('a.id,a.name,a.contact,a.phone,a.region,a.address,a.user_id,a.parent_id,a.status,a.created_at,a.updated_at,
- u.username,u.status AS operator_status,COALESCE(customers.enterprise_count,0) AS enterprise_count,
- COALESCE(sales.sales_cents,0) AS sales_cents,COALESCE(sales.month_cents,0) AS month_cents')
- ->orderByDesc('a.id')->get()->toArray();
- $levels=(new AgentHierarchyPolicy())->levels($rows); $access=new AgentAccessPolicy(); $granted=$access->grantedUserIds();
- $names=array_column($rows,'name','id');
- $pendingCommission=WaterCommission::query()->where('status','pending')
- ->selectRaw('agent_id,SUM(amount_cents) AS amount_cents')->groupBy('agent_id')
- ->get()->pluck('amount_cents','agent_id')->all();
- foreach ($rows as &$row) {
- foreach (['id','status','enterprise_count','sales_cents','month_cents'] as $key) $row[$key]=(int)$row[$key];
- $row['user_id']=$row['user_id']===null?null:(int)$row['user_id'];
- $row['parent_id']=$row['parent_id']===null?null:(int)$row['parent_id'];
- $row['level']=$levels[$row['id']];
- $row['parent_name']=$names[$row['parent_id']]??null;
- $row['authorization']=$access->state($row,$granted);
- $row['commission_cents']=(int)($pendingCommission[$row['id']]??0);
- }
- unset($row);
- return $rows;
- }
- public function dashboard(array $input): array {
- $filters=new AgentFilters($input);
- return WaterModel::transaction(function () use ($filters) {
- $all=$this->rows();
- $rows=array_values(array_filter($all,function ($row) use ($filters) {
- return ($filters->keyword==='' || mb_stripos($row['name'].' '.$row['phone'].' '.$row['contact'],$filters->keyword)!==false)
- && ($filters->level==='' || ($filters->level==='unset'?$row['level']===null:$row['level']===(int)$filters->level))
- && ($filters->authorization==='' || $row['authorization']===$filters->authorization);
- }));
- $sales=array_sum(array_column($all,'sales_cents'));
- $platform=(int)WaterOrder::query()->where('created_at','<=',$this->now->format('Y-m-d H:i:s'))->sum('amount_cents');
- $members=array_filter($all,fn($row)=>$row['parent_id']!==null && $row['parent_id']>0);
- $rank=array_values(array_filter($all,fn($row)=>$row['month_cents']>0));
- usort($rank,fn($a,$b)=>($b['month_cents']<=>$a['month_cents'])?:($a['id']<=>$b['id']));
- $start=$this->now->format('Y-m-01 00:00:00'); $end=$this->now->format('Y-m-d H:i:s');
- return ['list'=>['data'=>array_slice($rows,($filters->page-1)*$filters->limit,$filters->limit),'total'=>count($rows),
- 'current_page'=>$filters->page,'per_page'=>$filters->limit],
- 'summary'=>['total'=>count($all),'new_month'=>count(array_filter($all,fn($r)=>$r['created_at']>=$start && $r['created_at']<=$end)),
- 'sales_cents'=>$sales,'platform_share'=>$platform?round(100*$sales/$platform,1):null,'commission_cents'=>array_sum(array_column($all,'commission_cents')),
- 'members'=>count($members),'active_members'=>count(array_filter($members,fn($r)=>$r['status']===1 && $r['month_cents']>0))],
- 'ranking'=>array_slice($rank,0,4),
- 'options'=>array_map(fn($r)=>array_intersect_key($r,array_flip(['id','name','status','level'])),$all),
- 'commission'=>['configured'=>true,'message'=>WaterCommissionPolicy::message()],
- 'updated_at'=>$end];
- });
- }
- public function detail(int $id): array {
- return WaterModel::transaction(function () use ($id) {
- $all=$this->rows(); $map=array_column($all,null,'id');
- if (!isset($map[$id])) throw new ApiException('代理不存在');
- return ['agent'=>$map[$id],
- 'children'=>array_values(array_filter($all,fn($r)=>$r['parent_id']===$id)),
- 'enterprises'=>WaterEnterprise::query()->where('agent_id',$id)->orderByDesc('id')->limit(20)->get(['id','name','region','status'])->toArray()];
- });
- }
- }
|