load(); \support\App::loadAllConfig(['route']); date_default_timezone_set('Asia/Shanghai'); use app\miniapi\auth\TestPhoneIdentityProvider; use plugin\saiadmin\app\model\water\WaterModel; use plugin\saiadmin\app\model\water\WaterEnterprise; use plugin\saiadmin\app\model\water\WaterSku; use plugin\saiadmin\app\model\water\WaterAccount; use plugin\saiadmin\app\model\water\WaterDevice; use plugin\saiadmin\app\model\water\WaterDeviceUsage; use plugin\saiadmin\app\model\water\WaterLedger; use plugin\saiadmin\app\service\alerts\ReplenishmentPolicy; const MINI_DEVICE_DEMO = 'TEST-MINI-DEVICE-49-20261007'; if (!TestPhoneIdentityProvider::enabled()) { throw new RuntimeException('Requires local test environment'); } $apply = in_array('--apply', $argv, true); $result = WaterModel::transaction(function () use ($apply): array { $enterprise = WaterEnterprise::query()->where('id', 49)->lockForUpdate()->first(); if (!$enterprise || $enterprise->name !== '【测试0910】科技园配送测试') { throw new RuntimeException('Expected named test enterprise 49'); } $sku = WaterSku::query()->where('name', '山泉水(测试)')->where('status', 1)->first(); if (!$sku) { throw new RuntimeException('Missing active test water specification'); } $record = WaterLedger::query()->where('kind', 'demo_seed')->where('reference', MINI_DEVICE_DEMO)->first(); if ($record) { return ['applied' => true, 'replayed' => true, 'note' => $record->note]; } if (!$apply) { return ['mode' => 'inspect', 'enterprise_id' => 49, 'sku_id' => (int) $sku->id, 'devices' => 3, 'usage_days' => 7]; } if (WaterDevice::query()->where('sn', 'like', MINI_DEVICE_DEMO . '%')->exists()) { throw new RuntimeException('Demo serial numbers already exist without batch record'); } $originalPeople = $enterprise->employee_count; $policy = (new ReplenishmentPolicy())->settings(); if ($enterprise->employee_count === null || (int) $enterprise->employee_count === 0) { $enterprise->employee_count = max(1, (int) round(7 * $policy['days_per_barrel'] / 12)); $enterprise->save(); } $accountKey = ['enterprise_id' => 49, 'sku_id' => (int) $sku->id]; $existingAccount = WaterAccount::query()->where($accountKey)->first(); $account = $existingAccount ?? WaterAccount::query()->create($accountKey + [ 'entitlement' => 64, 'frozen' => 0, 'full_qty' => 7, 'empty_qty' => 2, 'threshold_qty' => 3, 'daily_liters' => null, 'updated_at' => date('Y-m-d H:i:s'), ]); $samples = [ ['会议区智能饮水机', 18.6, [9.2, 14.0, 11.1, 17.3, 14.8, 18.6, 13.0]], ['前台智能饮水机', 12.4, [6.4, 9.5, 8.2, 11.6, 10.4, 14.0, 12.4]], ['茶水间智能饮水机', 23.8, [15.2, 17.6, 16.0, 20.3, 18.9, 25.4, 23.8]], ]; $deviceIds = []; $now = new DateTimeImmutable(); foreach ($samples as $index => [$name, $today, $history]) { $device = WaterDevice::query()->create([ 'sn' => MINI_DEVICE_DEMO . '-' . ($index + 1), 'enterprise_id' => 49, 'sku_id' => (int) $sku->id, 'name' => '【测试】' . $name, 'firmware' => 'mini-demo', 'last_seen' => $now->format('Y-m-d H:i:s'), 'today_liters' => $today, 'telemetry_date' => $now->format('Y-m-d'), 'fault' => '', 'created_at' => $now->format('Y-m-d H:i:s'), 'updated_at' => $now->format('Y-m-d H:i:s'), ]); $deviceIds[] = (int) $device->id; foreach ($history as $dayIndex => $liters) { $day = $now->modify('-' . (6 - $dayIndex) . ' days')->format('Y-m-d'); WaterDeviceUsage::query()->create([ 'device_id' => (int) $device->id, 'day' => $day, 'liters' => $dayIndex === 6 ? $today : $liters, 'reported_at' => $dayIndex === 6 ? $now->format('Y-m-d H:i:s') : $day . ' 17:00:00', ]); } } $manifest = [ 'device_ids' => $deviceIds, 'account_id' => (int) $account->id, 'account_created' => $existingAccount === null, 'original_employee_count' => $originalPeople, 'demo_employee_count' => (int) $enterprise->employee_count, 'note' => 'Only simulated telemetry and demo stock; no purchase, payment or automatic delivery executed.', ]; WaterLedger::query()->create([ 'enterprise_id' => 49, 'sku_id' => (int) $sku->id, 'kind' => 'demo_seed', 'reference' => MINI_DEVICE_DEMO, 'quantity' => 0, 'created_by' => 1, 'note' => json_encode($manifest, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 'created_at' => $now->format('Y-m-d H:i:s'), ]); return ['applied' => true, 'replayed' => false, 'usage_rows' => 21] + $manifest; }); echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . PHP_EOL;