$ErrorActionPreference = "Stop" function Read-DotEnv { param([string]$Path) $map = @{} Get-Content -Encoding UTF8 $Path | ForEach-Object { $line = $_.Trim() if ($line.Length -eq 0 -or $line.StartsWith("#")) { return } if ($line -match "^([^=]+)=(.*)$") { $map[$Matches[1].Trim()] = $Matches[2].Trim() } } return $map } function Invoke-Parse { param( [string]$Method, [string]$Path, [object]$Body = $null ) $headers = @{ "X-Parse-Application-Id" = $envMap["PARSE_APP_ID"] "X-Parse-REST-API-Key" = $envMap["PARSE_REST_API_KEY"] "X-Parse-Master-Key" = $envMap["PARSE_MASTER_KEY"] } $json = if ($null -ne $Body) { $Body | ConvertTo-Json -Depth 16 } else { $null } Invoke-RestMethod -Method $Method -Uri "$baseUrl$Path" -Headers $headers -ContentType "application/json" -Body $json } function Pointer { param([string]$ClassName, [string]$ObjectId) return @{ "__type" = "Pointer"; className = $ClassName; objectId = $ObjectId } } function AclForUsers { param([string[]]$UserIds) $acl = @{} foreach ($userId in $UserIds) { if ($userId) { $acl[$userId] = @{ read = $true; write = $true } } } return $acl } function Create-Object { param([string]$ClassName, [object]$Body) Invoke-Parse -Method "Post" -Path "/classes/$ClassName" -Body $Body } function Create-User { param( [string]$Username, [string]$Password, [string]$Name, [string]$Role, [string]$Phone, [object]$CompanyPointer = $null ) $body = @{ username = $Username email = $Username password = $Password name = $Name role = $Role phone = $Phone status = "enabled" mockBatch = $batch } if ($CompanyPointer) { $body.company = $CompanyPointer } try { return Invoke-Parse -Method "Post" -Path "/users" -Body $body } catch { Write-Host "Skip existing or invalid user: $Username" $where = [uri]::EscapeDataString((@{ username = $Username } | ConvertTo-Json -Compress)) $result = Invoke-Parse -Method "Get" -Path "/users?where=$where" return $result.results[0] } } $envPath = Join-Path $PSScriptRoot "..\.env" $envMap = Read-DotEnv -Path $envPath $baseUrl = $envMap["PARSE_SERVER_URL"].TrimEnd("/") $batch = "servicepilot-mock-20260601" $password = "Test@123456" Write-Host "Seeding ServicePilot mock data..." $companies = @( @{ name = "Huadong Yunqi Tech"; contactName = "Zhou Yuan"; contactPhone = "13800001001"; email = "contact01@example.com"; serviceLevel = "enterprise"; address = "Shanghai Pudong"; status = "enabled"; mockBatch = $batch }, @{ name = "Beichen Manufacturing"; contactName = "Liu Na"; contactPhone = "13800001002"; email = "contact02@example.com"; serviceLevel = "professional"; address = "Tianjin Binhai"; status = "enabled"; mockBatch = $batch }, @{ name = "Huilian Data Service"; contactName = "Chen Lin"; contactPhone = "13800001003"; email = "contact03@example.com"; serviceLevel = "standard"; address = "Hangzhou Xihu"; status = "enabled"; mockBatch = $batch } ) $companyObjects = @() foreach ($company in $companies) { $created = Create-Object -ClassName "Company" -Body $company $company.objectId = $created.objectId $companyObjects += $company Write-Host "Created Company $($company.name)" } $support = Create-User -Username "support@servicepilot.test" -Password $password -Name "Support Wang" -Role "support" -Phone "13900002001" $engineer = Create-User -Username "engineer@servicepilot.test" -Password $password -Name "Engineer Chen" -Role "engineer" -Phone "13900002002" $admin = Create-User -Username "admin@servicepilot.test" -Password $password -Name "System Admin" -Role "admin" -Phone "13900002003" $customers = @() for ($i = 0; $i -lt $companyObjects.Count; $i++) { $company = $companyObjects[$i] $customer = Create-User -Username "customer$($i + 1)@servicepilot.test" -Password $password -Name "$($company.name) Customer" -Role "customer" -Phone "1390000300$($i + 1)" -CompanyPointer (Pointer "Company" $company.objectId) $customers += $customer } $titles = @( "Monthly report export failed", "New employee cannot login", "API returns 500 occasionally", "Data sync job delayed", "Customer portal loads slowly", "Attachment preview failed", "Menu not refreshed after permission change", "Knowledge search is inaccurate", "Customer import failed", "SLA timeout reminder missing" ) $categories = @("software", "account", "data", "other") $priorities = @("low", "medium", "high", "urgent") $statuses = @("pending", "processing", "confirming", "resolved") for ($i = 0; $i -lt 60; $i++) { $company = $companyObjects[$i % $companyObjects.Count] $creator = $customers[$i % $customers.Count] $assignee = if ($i % 4 -eq 0) { $support } else { $engineer } $status = $statuses[$i % $statuses.Count] $priority = $priorities[$i % $priorities.Count] $ticketNo = "TK-20260601-$("{0:D3}" -f ($i + 1))" $acl = AclForUsers @($creator.objectId, $assignee.objectId, $support.objectId, $admin.objectId) $ticket = @{ ticketNo = $ticketNo title = $titles[$i % $titles.Count] description = "Mock ticket for CRUD, ACL isolation, API tests, UI automation, and performance tests." category = $categories[$i % $categories.Count] priority = $priority impactScope = if ($i % 3 -eq 0) { "company" } elseif ($i % 3 -eq 1) { "department" } else { "single-user" } status = $status company = Pointer "Company" $company.objectId companyName = $company.name creator = Pointer "_User" $creator.objectId assignee = Pointer "_User" $assignee.objectId ownerName = $assignee.name isOverdue = ($i % 9 -eq 0) slaDeadline = @{ "__type" = "Date"; iso = (Get-Date).AddHours(4 - ($i % 8)).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") } mockBatch = $batch ACL = $acl } $createdTicket = Create-Object -ClassName "Ticket" -Body $ticket if ($i -lt 12) { Create-Object -ClassName "TicketComment" -Body @{ ticket = Pointer "Ticket" $createdTicket.objectId author = Pointer "_User" $assignee.objectId content = "Issue received and investigation started." visibility = "public" mockBatch = $batch ACL = $acl } | Out-Null } } $slaRules = @( @{ priority = "urgent"; responseMinutes = 15; resolveHours = 4; alertBeforeMinutes = 30; enabled = $true; mockBatch = $batch }, @{ priority = "high"; responseMinutes = 30; resolveHours = 8; alertBeforeMinutes = 60; enabled = $true; mockBatch = $batch }, @{ priority = "medium"; responseMinutes = 120; resolveHours = 24; alertBeforeMinutes = 120; enabled = $true; mockBatch = $batch }, @{ priority = "low"; responseMinutes = 240; resolveHours = 48; alertBeforeMinutes = 240; enabled = $true; mockBatch = $batch } ) foreach ($rule in $slaRules) { Create-Object -ClassName "SlaRule" -Body $rule | Out-Null } $category = Create-Object -ClassName "KnowledgeCategory" -Body @{ name = "FAQ"; sortOrder = 1; enabled = $true; mockBatch = $batch } foreach ($articleTitle in @("Report export troubleshooting", "First login troubleshooting", "API 500 diagnosis", "Attachment preview troubleshooting")) { Create-Object -ClassName "KnowledgeArticle" -Body @{ title = $articleTitle category = Pointer "KnowledgeCategory" $category.objectId summary = "Mock article for knowledge search and ticket reference." content = "Step 1: confirm symptom. Step 2: collect logs. Step 3: resolve and update ticket." tags = @("test", "ticket", "knowledge") visibility = "customer" status = "published" author = Pointer "_User" $admin.objectId viewCount = 10 referenceCount = 2 mockBatch = $batch } | Out-Null } Write-Host "Mock users:" Write-Host " customer1@servicepilot.test / $password" Write-Host " customer2@servicepilot.test / $password" Write-Host " customer3@servicepilot.test / $password" Write-Host " support@servicepilot.test / $password" Write-Host " engineer@servicepilot.test / $password" Write-Host " admin@servicepilot.test / $password" Write-Host "Seed finished. Ticket count: 60"