diff --git a/bc-export.ps1 b/bc-export.ps1 index 367fdbb..dcda716 100755 --- a/bc-export.ps1 +++ b/bc-export.ps1 @@ -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" -# Entities to extract - critical business data +# Standalone entities to extract $entities = @( "accounts", "customers", "vendors", "items", - "salesInvoices", - "salesInvoiceLines", - "salesOrders", - "salesOrderLines", - "salesCreditMemos", - "salesCreditMemoLines", - "purchaseInvoices", - "purchaseInvoiceLines", - "purchaseOrders", - "purchaseOrderLines", "generalLedgerEntries", "bankAccounts", "employees", @@ -46,6 +36,16 @@ $entities = @( "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 { param([string]$Message, [string]$Level = "INFO") $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 try { Write-Log "=========================================" @@ -165,7 +207,7 @@ try { Write-Log "=========================================" Write-Log "Environment: $environmentName" 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 $exportDir = $OutputPath @@ -217,6 +259,7 @@ try { New-Item -ItemType Directory -Path $companyDir -Force | Out-Null } + # Export standalone entities foreach ($entity in $entities) { $count = Export-EntityData ` -Token $token ` @@ -232,6 +275,26 @@ try { $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