fix: fetch document lines via $expand instead of standalone queries

The BC API v2.0 requires line entities (salesInvoiceLines, etc.) to be
accessed through their parent document - they cannot be queried directly.
Use OData $expand on parent documents to include lines inline, e.g.
salesInvoices?$expand=salesInvoiceLines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-10 07:57:46 +01:00
parent 77f48f326b
commit 4af9cd7f11

View File

@@ -18,22 +18,12 @@ $bcCompanyName = $env:BC_COMPANY_NAME # optional: filter to specific company
$baseUrl = "https://api.businesscentral.dynamics.com/v2.0/$tenantId/$environmentName/api/v2.0" $baseUrl = "https://api.businesscentral.dynamics.com/v2.0/$tenantId/$environmentName/api/v2.0"
# Entities to extract - critical business data # Standalone entities to extract
$entities = @( $entities = @(
"accounts", "accounts",
"customers", "customers",
"vendors", "vendors",
"items", "items",
"salesInvoices",
"salesInvoiceLines",
"salesOrders",
"salesOrderLines",
"salesCreditMemos",
"salesCreditMemoLines",
"purchaseInvoices",
"purchaseInvoiceLines",
"purchaseOrders",
"purchaseOrderLines",
"generalLedgerEntries", "generalLedgerEntries",
"bankAccounts", "bankAccounts",
"employees", "employees",
@@ -46,6 +36,16 @@ $entities = @(
"countriesRegions" "countriesRegions"
) )
# Document entities with line items - fetched with $expand to include lines
# Lines cannot be queried standalone; they require a parent document ID
$documentEntities = @{
"salesInvoices" = "salesInvoiceLines"
"salesOrders" = "salesOrderLines"
"salesCreditMemos" = "salesCreditMemoLines"
"purchaseInvoices" = "purchaseInvoiceLines"
"purchaseOrders" = "purchaseOrderLines"
}
function Write-Log { function Write-Log {
param([string]$Message, [string]$Level = "INFO") param([string]$Message, [string]$Level = "INFO")
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
@@ -158,6 +158,48 @@ function Export-EntityData {
} }
} }
function Export-DocumentWithLines {
param(
[string]$Token,
[string]$CompanyId,
[string]$CompanyName,
[string]$DocumentEntity,
[string]$LineEntity,
[string]$OutputDir
)
$entityUrl = "$baseUrl/companies($CompanyId)/$DocumentEntity" + '?$expand=' + $LineEntity
Write-Log " Exporting $DocumentEntity (with $LineEntity)..."
try {
$data = Get-BCData -Token $Token -Url $entityUrl
$docCount = 0
$lineCount = 0
if ($data) {
$docCount = $data.Count
foreach ($doc in $data) {
if ($doc.$LineEntity) {
$lineCount += $doc.$LineEntity.Count
}
}
}
# Save the documents (with lines embedded)
$outputFile = Join-Path $OutputDir "$DocumentEntity.json"
$data | ConvertTo-Json -Depth 10 | Out-File -FilePath $outputFile -Encoding utf8
Write-Log " $DocumentEntity : $docCount documents, $lineCount lines"
return ($docCount + $lineCount)
}
catch {
Write-Log " Failed to export ${DocumentEntity} with lines: $_" "WARN"
$outputFile = Join-Path $OutputDir "$DocumentEntity.json"
"[]" | Out-File -FilePath $outputFile -Encoding utf8
return 0
}
}
# Main execution # Main execution
try { try {
Write-Log "=========================================" Write-Log "========================================="
@@ -165,7 +207,7 @@ try {
Write-Log "=========================================" Write-Log "========================================="
Write-Log "Environment: $environmentName" Write-Log "Environment: $environmentName"
Write-Log "Output Path: $OutputPath" Write-Log "Output Path: $OutputPath"
Write-Log "Entities to extract: $($entities.Count)" Write-Log "Entities to extract: $($entities.Count + $documentEntities.Count) ($($documentEntities.Count) with line items)"
# Create output directory # Create output directory
$exportDir = $OutputPath $exportDir = $OutputPath
@@ -217,6 +259,7 @@ try {
New-Item -ItemType Directory -Path $companyDir -Force | Out-Null New-Item -ItemType Directory -Path $companyDir -Force | Out-Null
} }
# Export standalone entities
foreach ($entity in $entities) { foreach ($entity in $entities) {
$count = Export-EntityData ` $count = Export-EntityData `
-Token $token ` -Token $token `
@@ -232,6 +275,26 @@ try {
$failedEntities += "$companyName/$entity" $failedEntities += "$companyName/$entity"
} }
} }
# Export document entities with their line items via $expand
foreach ($docEntity in $documentEntities.Keys) {
$lineEntity = $documentEntities[$docEntity]
$count = Export-DocumentWithLines `
-Token $token `
-CompanyId $companyId `
-CompanyName $companyName `
-DocumentEntity $docEntity `
-LineEntity $lineEntity `
-OutputDir $companyDir
$totalRecords += $count
$totalEntities++
if ($count -eq 0) {
$failedEntities += "$companyName/$docEntity"
}
}
} }
# Save export metadata # Save export metadata