load(); \support\App::loadAllConfig(['route']); date_default_timezone_set('Asia/Shanghai'); use plugin\saiadmin\app\model\water\{WaterModel,WaterAgent,WaterEnterprise,WaterOperator,WaterLedger,WaterAccount,WaterOrder,WaterDelivery,WaterSku,WaterPackage,WaterDevice}; use plugin\saiadmin\app\service\{WaterBusiness,WaterAgentDashboard}; const RANKING_BATCH = 'TEST-WATER-AGENT-RANKING-20260916'; const RANKING_TAG = '【业绩测试0916】'; function ensure(bool $ok,string $message): void { if (!$ok) throw new RuntimeException($message); } function existingRows(): array { $snapshot=[]; foreach ([WaterAgent::class,WaterEnterprise::class,WaterAccount::class,WaterOrder::class,WaterDelivery::class, WaterSku::class,WaterPackage::class,WaterDevice::class,WaterLedger::class] as $model) { $snapshot[$model]=$model::query()->orderBy('id')->get()->toArray(); } return $snapshot; } function rankingSummary(array $ranking): array { return array_map(fn($row)=>['agent_id'=>$row['id'],'agent'=>$row['name'],'month_yuan'=>$row['month_cents']/100],$ranking); } $samples=[ ['customer'=>'星澜科技','agent_id'=>1,'cents'=>120000,'buckets'=>60], ['customer'=>'青禾创意','agent_id'=>1,'cents'=>80000,'buckets'=>40], ['customer'=>'云帆商贸','agent_id'=>6,'cents'=>90000,'buckets'=>45], ['customer'=>'沐光设计','agent_id'=>6,'cents'=>60000,'buckets'=>30], ['customer'=>'森屿办公','agent_id'=>7,'cents'=>60000,'buckets'=>30], ]; $result=['applied'=>false,'batch'=>RANKING_BATCH,'planned_orders'=>5,'planned_yuan'=>4100,'planned_entitlement'=>205, 'ranking_before'=>rankingSummary((new WaterAgentDashboard())->dashboard([])['ranking'])]; if (in_array('--apply',$argv,true)) { $result+=WaterModel::transaction(function () use ($samples): array { ensure((bool)WaterOperator::query()->where('id',1)->lockForUpdate()->first(),'缺少操作账号'); if (WaterLedger::query()->where(['kind'=>'demo_seed','reference'=>RANKING_BATCH])->exists()) return ['replayed'=>true]; ensure(date('Y-m-d')==='2026-09-16','此固定批次首次只能在2026-09-16执行,避免误写其他月份'); ensure(!WaterSku::query()->where('name','like',RANKING_TAG.'%')->exists(),'已有同名测试规格,禁止覆盖'); ensure(!WaterPackage::query()->where('name','like',RANKING_TAG.'%')->exists(),'已有同名测试套餐,禁止覆盖'); ensure(!WaterOrder::query()->where('reference','like',RANKING_BATCH.'%')->exists(),'已有批次订单但缺少完成标记,请核对'); $before=existingRows(); $dashboard=new WaterAgentDashboard(); $beforeSales=[]; foreach ([1,6,7] as $id) { $agent=$dashboard->detail($id)['agent']; ensure($agent['status']===1,'测试关联代理已停用'); $beforeSales[$id]=$agent['month_cents']; } $service=new WaterBusiness(); $sku=$service->save('sku',['name'=>RANKING_TAG.'18.9L模拟水','liters'=>18.9,'safety_stock'=>0,'status'=>1],1)['id']; $orders=[]; $expected=[]; foreach ($samples as $index=>$sample) { $customers=WaterEnterprise::query()->where('name','【代理测试0916】'.$sample['customer'])->lockForUpdate()->get(); ensure($customers->count()===1,'测试客户缺失或重名:'.$sample['customer']); $customer=$customers->first(); ensure((int)$customer->agent_id===$sample['agent_id'] && (int)$customer->status===1,'测试客户归属或状态已变化,禁止覆盖'); $packageValues=['name'=>RANKING_TAG.'模拟套餐'.($index+1),'sku_id'=>$sku,'buckets'=>$sample['buckets'], 'price_cents'=>$sample['cents'],'status'=>1]; $package=$service->save('package',$packageValues,1)['id']; $reference=RANKING_BATCH.'-'.($index+1); $order=$service->purchase(['enterprise_id'=>(int)$customer->id,'package_id'=>$package,'reference'=>$reference],1); WaterLedger::query()->where(['kind'=>'purchase','reference'=>$reference])->update([ 'note'=>'【测试数据】代理业绩排行模拟订单及权益,未发生真实收款,请勿实际配送', ]); $saved=WaterOrder::query()->findOrFail($order['id']); ensure((int)$saved->amount_cents===$sample['cents'] && (int)$saved->buckets===$sample['buckets'],'订单数据不一致'); $account=WaterAccount::query()->where(['enterprise_id'=>$customer->id,'sku_id'=>$sku])->firstOrFail(); ensure((int)$account->entitlement===$sample['buckets'] && (int)$account->frozen===0,'测试权益不一致'); $expected[$sample['agent_id']]=($expected[$sample['agent_id']]??0)+$sample['cents']; $orders[]=['id'=>$order['id'],'customer'=>$customer->name,'agent_id'=>$sample['agent_id'], 'amount_yuan'=>$sample['cents']/100,'buckets'=>$sample['buckets']]; // Keep the historical order and entitlement; prevent accidental further purchases of this demo package. $service->save('package',['id'=>$package]+array_replace($packageValues,['status'=>2]),1); } $service->save('sku',['id'=>$sku,'name'=>RANKING_TAG.'18.9L模拟水','liters'=>18.9,'safety_stock'=>0,'status'=>2],1); foreach ($expected as $agentId=>$cents) { ensure((new WaterAgentDashboard())->detail($agentId)['agent']['month_cents']-$beforeSales[$agentId]===$cents,'代理本月业绩增量不一致'); } foreach ($before as $model=>$rows) { $after=$model::query()->whereIn('id',array_column($rows,'id'))->orderBy('id')->get()->toArray(); ensure($rows===$after,'已有业务记录发生变化:'.$model); } ensure(WaterDelivery::query()->count()===count($before[WaterDelivery::class]),'不得创建配送任务'); WaterLedger::query()->create(['kind'=>'demo_seed','reference'=>RANKING_BATCH,'created_by'=>1,'enterprise_id'=>0, 'sku_id'=>$sku,'quantity'=>205,'amount_cents'=>410000,'note'=>'代理排行模拟数据;5单4100元,无真实收款;规格及套餐已停用', 'created_at'=>date('Y-m-d H:i:s')]); return ['replayed'=>false,'sku_id'=>$sku,'orders'=>$orders,'checks'=>'sales, entitlements, prior rows and no delivery verified']; }); $result['applied']=true; } $expectedRanking=(new WaterAgentDashboard())->dashboard([])['ranking']; $result['ranking_after']=rankingSummary($expectedRanking); if (in_array('--http',$argv,true)) { $token=\Tinywan\Jwt\JwtToken::generateToken(['id'=>1,'username'=>'admin','plat'=>'saiadmin','type'=>'web', 'client'=>RANKING_BATCH,'access_exp'=>120,'refresh_exp'=>120])['access_token']; $ch=curl_init('http://127.0.0.1:8787/core/water/agents/dashboard'); curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>15,CURLOPT_HTTPHEADER=>['Authorization: Bearer '.$token]]); $raw=curl_exec($ch); $status=curl_getinfo($ch,CURLINFO_HTTP_CODE); curl_close($ch); unset($token); $body=json_decode((string)$raw,true); ensure($status===200 && ($body['code']??0)===200,'HTTP业绩排行查询失败'); ensure(rankingSummary($body['data']['ranking'])===rankingSummary($expectedRanking),'HTTP排行与业务查询不一致'); $result['http_ranking_verified']=true; } echo json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE).PHP_EOL;