Add Sage Spain export artifacts
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
**********************
|
||||||
|
nStart der Windows PowerShell-Aufzeichnung
|
||||||
|
Startzeit: 20260427082528
|
||||||
|
Benutzername: TRAFAGCH\koi
|
||||||
|
RunAs-Benutzer: TRAFAGCH\koi
|
||||||
|
Konfigurationsname:
|
||||||
|
Computer: NB61258 (Microsoft Windows NT 10.0.26200.0)
|
||||||
|
Hostanwendung: C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Users\koi\source\repos\Ai\TrafagSalesExporter\.tmp_sap_probe\RunSapProbeInteractive.ps1 abap-activate Z_TEST3 --dry-run
|
||||||
|
Prozess-ID: 452
|
||||||
|
PSVersion: 5.1.26100.8115
|
||||||
|
PSEdition: Desktop
|
||||||
|
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.26100.8115
|
||||||
|
BuildVersion: 10.0.26100.8115
|
||||||
|
CLRVersion: 4.0.30319.42000
|
||||||
|
WSManStackVersion: 3.0
|
||||||
|
PSRemotingProtocolVersion: 2.3
|
||||||
|
SerializationVersion: 1.1.0.1
|
||||||
|
**********************
|
||||||
|
SAP NCo CLI
|
||||||
|
Architecture : x86
|
||||||
|
NCo Assembly : sapnco, Version=3.1.0.42, Culture=neutral, PublicKeyToken=50436dca5c7f7d23
|
||||||
|
Password prompt: [masked input omitted]
|
||||||
|
Target : travt762.sap.trafag.com / SYSNR 00 / CLIENT 100 / USER KOI
|
||||||
|
Ping : OK
|
||||||
|
|
||||||
|
Program : Z_TEST3
|
||||||
|
Lines : 69
|
||||||
|
Activation : RPY_PROGRAM_INSERT with SAVE_INACTIVE blank
|
||||||
|
Dry run : no SAP repository changes were written.
|
||||||
|
|
||||||
|
Exit code: 0
|
||||||
|
**********************
|
||||||
|
Ende der Windows PowerShell-Aufzeichnung
|
||||||
|
Endzeit: 20260427082529
|
||||||
|
**********************
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
Sage SQL CSV export
|
||||||
|
|
||||||
|
===================
|
||||||
|
|
||||||
|
Server instance: localhost
|
||||||
|
|
||||||
|
Database filter: (all accessible user databases)
|
||||||
|
|
||||||
|
From date: 2025-01-01
|
||||||
|
|
||||||
|
To date: 2026-01-01
|
||||||
|
|
||||||
|
Files:
|
||||||
|
|
||||||
|
- candidate_objects.csv: SQL tables/views that look relevant for sales/invoices.
|
||||||
|
|
||||||
|
- export_summary.csv: export status and row counts.
|
||||||
|
|
||||||
|
- *.csv: exported samples or selected full exports.
|
||||||
|
|
||||||
|
Recommended workflow:
|
||||||
|
|
||||||
|
1. Run discovery first:
|
||||||
|
|
||||||
|
.\Export-SageSqlCsv.ps1 -DiscoverOnly
|
||||||
|
|
||||||
|
2. Send candidate_objects.csv to Trafag/IT for selection.
|
||||||
|
|
||||||
|
3. Export selected objects:
|
||||||
|
|
||||||
|
.\Export-SageSqlCsv.ps1 -Database "DATABASE_NAME" -ObjectName "schema.table_or_view"
|
||||||
|
|
||||||
|
4. If the selected object is very large, add:
|
||||||
|
|
||||||
|
-FromDate "2025-01-01" -ToDate "2026-01-01" -MaxRowsPerObject 100000
|
||||||
|
|
||||||
|
The script only reads data. It does not change SQL Server or Sage.
|
||||||
|
|
||||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
|||||||
|
$scriptPath = Join-Path $PSScriptRoot "Export-SageSqlCsv.ps1"
|
||||||
|
|
||||||
|
& $scriptPath `
|
||||||
|
-Database "Sage" `
|
||||||
|
-ObjectName @(
|
||||||
|
"dbo.CabeceraAlbaranCliente",
|
||||||
|
"dbo.LineasAlbaranCliente",
|
||||||
|
"dbo.EstadisVenta",
|
||||||
|
"dbo.EstadisVentaTallas",
|
||||||
|
"dbo.FacturasTB",
|
||||||
|
"dbo.MovimientosFacturas",
|
||||||
|
"dbo.Vis_RTDV_EfectosFactura"
|
||||||
|
) `
|
||||||
|
-FromDate "2025-01-01" `
|
||||||
|
-ToDate "2026-01-01" `
|
||||||
|
-MaxRowsPerObject 10000
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
$scriptPath = Join-Path $PSScriptRoot "Export-SageSqlCsv.ps1"
|
||||||
|
|
||||||
|
& $scriptPath `
|
||||||
|
-Database "Sage" `
|
||||||
|
-ObjectName @(
|
||||||
|
"dbo.CabeceraAlbaranCliente",
|
||||||
|
"dbo.LineasAlbaranCliente",
|
||||||
|
"dbo.EstadisVenta",
|
||||||
|
"dbo.EstadisVentaTallas",
|
||||||
|
"dbo.FacturasTB",
|
||||||
|
"dbo.MovimientosFacturas",
|
||||||
|
"dbo.Vis_RTDV_EfectosFactura"
|
||||||
|
) `
|
||||||
|
-FromDate "2025-01-01" `
|
||||||
|
-ToDate "2026-01-01"
|
||||||
@@ -0,0 +1,410 @@
|
|||||||
|
param(
|
||||||
|
[string]$ServerInstance = "localhost",
|
||||||
|
[string]$Database = "",
|
||||||
|
[string[]]$ObjectName = @(),
|
||||||
|
[datetime]$FromDate = "2025-01-01",
|
||||||
|
[datetime]$ToDate = "2026-01-01",
|
||||||
|
[string]$OutputDirectory = (Join-Path $env:USERPROFILE "Desktop"),
|
||||||
|
[int]$SampleRows = 500,
|
||||||
|
[int]$MaxRowsPerObject = 0,
|
||||||
|
[switch]$DiscoverOnly,
|
||||||
|
[switch]$ExportCandidates,
|
||||||
|
[switch]$IncludeSystemDatabases
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function New-Connection {
|
||||||
|
param([string]$DbName)
|
||||||
|
|
||||||
|
$builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
|
||||||
|
$builder["Data Source"] = $ServerInstance
|
||||||
|
$builder["Initial Catalog"] = $DbName
|
||||||
|
$builder["Integrated Security"] = $true
|
||||||
|
$builder["TrustServerCertificate"] = $true
|
||||||
|
$builder["Connect Timeout"] = 15
|
||||||
|
return New-Object System.Data.SqlClient.SqlConnection($builder.ConnectionString)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-DataTable {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$Sql,
|
||||||
|
[hashtable]$Parameters = @{}
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection $DbName
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 300
|
||||||
|
|
||||||
|
foreach ($key in $Parameters.Keys) {
|
||||||
|
$param = $cmd.Parameters.Add("@$key", [System.Data.SqlDbType]::NVarChar, 4000)
|
||||||
|
$param.Value = [string]$Parameters[$key]
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = New-Object System.Data.DataTable
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
$table.Load($reader)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table
|
||||||
|
}
|
||||||
|
|
||||||
|
function Convert-ToCsvValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($null -eq $Value -or $Value -is [System.DBNull]) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Value -is [datetime]) {
|
||||||
|
$text = $Value.ToString("yyyy-MM-dd HH:mm:ss")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$text = [string]$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = $text.Replace('"', '""')
|
||||||
|
return '"' + $text + '"'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-QueryToCsv {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$Sql,
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection $DbName
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 0
|
||||||
|
|
||||||
|
$writer = New-Object System.IO.StreamWriter($Path, $false, [System.Text.Encoding]::UTF8)
|
||||||
|
$rowCount = 0
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
|
||||||
|
$headers = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetName($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($headers -join ";"))
|
||||||
|
|
||||||
|
while ($reader.Read()) {
|
||||||
|
$values = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetValue($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($values -join ";"))
|
||||||
|
$rowCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$writer.Dispose()
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rowCount
|
||||||
|
}
|
||||||
|
|
||||||
|
function Quote-NamePart {
|
||||||
|
param([string]$Name)
|
||||||
|
|
||||||
|
return "[" + $Name.Replace("]", "]]") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Split-SqlObjectName {
|
||||||
|
param([string]$Name)
|
||||||
|
|
||||||
|
$parts = $Name.Split(".", 2)
|
||||||
|
if ($parts.Count -eq 1) {
|
||||||
|
return [pscustomobject]@{ SchemaName = "dbo"; ObjectName = $parts[0] }
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pscustomobject]@{ SchemaName = $parts[0].Trim("[", "]"); ObjectName = $parts[1].Trim("[", "]") }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-UserDatabases {
|
||||||
|
$sql = @"
|
||||||
|
SELECT name
|
||||||
|
FROM sys.databases
|
||||||
|
WHERE state_desc = 'ONLINE'
|
||||||
|
AND HAS_DBACCESS(name) = 1
|
||||||
|
$(if ($IncludeSystemDatabases) { "" } else { "AND database_id > 4" })
|
||||||
|
ORDER BY name;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable "master" $sql | ForEach-Object { $_.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CandidateObjects {
|
||||||
|
param([string]$DbName)
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
WITH object_columns AS (
|
||||||
|
SELECT
|
||||||
|
s.name AS SchemaName,
|
||||||
|
o.name AS ObjectName,
|
||||||
|
o.type_desc AS ObjectType,
|
||||||
|
c.name AS ColumnName,
|
||||||
|
t.name AS TypeName,
|
||||||
|
c.max_length,
|
||||||
|
c.precision,
|
||||||
|
c.scale
|
||||||
|
FROM sys.objects o
|
||||||
|
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
||||||
|
JOIN sys.columns c ON c.object_id = o.object_id
|
||||||
|
JOIN sys.types t ON t.user_type_id = c.user_type_id
|
||||||
|
WHERE o.type IN ('U', 'V')
|
||||||
|
AND o.is_ms_shipped = 0
|
||||||
|
),
|
||||||
|
scored AS (
|
||||||
|
SELECT
|
||||||
|
SchemaName,
|
||||||
|
ObjectName,
|
||||||
|
ObjectType,
|
||||||
|
SUM(CASE WHEN LOWER(ObjectName) LIKE '%fact%' OR LOWER(ObjectName) LIKE '%invoice%' OR LOWER(ObjectName) LIKE '%venta%' OR LOWER(ObjectName) LIKE '%sales%' OR LOWER(ObjectName) LIKE '%albar%' OR LOWER(ObjectName) LIKE '%pedido%' THEN 5 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%fecha%' OR LOWER(ColumnName) LIKE '%date%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%cliente%' OR LOWER(ColumnName) LIKE '%customer%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%articulo%' OR LOWER(ColumnName) LIKE '%item%' OR LOWER(ColumnName) LIKE '%producto%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%importe%' OR LOWER(ColumnName) LIKE '%neto%' OR LOWER(ColumnName) LIKE '%total%' OR LOWER(ColumnName) LIKE '%amount%' THEN 3 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%cantidad%' OR LOWER(ColumnName) LIKE '%quantity%' OR LOWER(ColumnName) LIKE '%unidades%' THEN 2 ELSE 0 END) AS Score,
|
||||||
|
COUNT(*) AS ColumnCount,
|
||||||
|
STRING_AGG(CONVERT(nvarchar(max), ColumnName), ', ') WITHIN GROUP (ORDER BY ColumnName) AS Columns
|
||||||
|
FROM object_columns
|
||||||
|
GROUP BY SchemaName, ObjectName, ObjectType
|
||||||
|
)
|
||||||
|
SELECT TOP (80)
|
||||||
|
DB_NAME() AS DatabaseName,
|
||||||
|
SchemaName,
|
||||||
|
ObjectName,
|
||||||
|
ObjectType,
|
||||||
|
Score,
|
||||||
|
ColumnCount,
|
||||||
|
Columns
|
||||||
|
FROM scored
|
||||||
|
WHERE Score > 0
|
||||||
|
ORDER BY Score DESC, ObjectName;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable $DbName $sql
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-DateColumns {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$SchemaName,
|
||||||
|
[string]$ObjectNameValue
|
||||||
|
)
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
SELECT c.name AS ColumnName
|
||||||
|
FROM sys.objects o
|
||||||
|
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
||||||
|
JOIN sys.columns c ON c.object_id = o.object_id
|
||||||
|
JOIN sys.types t ON t.user_type_id = c.user_type_id
|
||||||
|
WHERE s.name = @schema
|
||||||
|
AND o.name = @object
|
||||||
|
AND (
|
||||||
|
t.name IN ('date', 'datetime', 'datetime2', 'smalldatetime')
|
||||||
|
OR LOWER(c.name) LIKE '%fecha%'
|
||||||
|
OR LOWER(c.name) LIKE '%date%'
|
||||||
|
)
|
||||||
|
ORDER BY
|
||||||
|
CASE
|
||||||
|
WHEN LOWER(c.name) LIKE '%fact%' OR LOWER(c.name) LIKE '%invoice%' THEN 0
|
||||||
|
WHEN LOWER(c.name) LIKE '%fecha%' OR LOWER(c.name) LIKE '%date%' THEN 1
|
||||||
|
ELSE 2
|
||||||
|
END,
|
||||||
|
c.column_id;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable $DbName $sql @{ schema = $SchemaName; object = $ObjectNameValue } |
|
||||||
|
ForEach-Object { $_.ColumnName }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-SelectSql {
|
||||||
|
param(
|
||||||
|
[string]$SchemaName,
|
||||||
|
[string]$ObjectNameValue,
|
||||||
|
[string]$DateColumn,
|
||||||
|
[int]$TopRows
|
||||||
|
)
|
||||||
|
|
||||||
|
$topClause = if ($TopRows -gt 0) { "TOP ($TopRows)" } else { "" }
|
||||||
|
$qualified = "$(Quote-NamePart $SchemaName).$(Quote-NamePart $ObjectNameValue)"
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($DateColumn)) {
|
||||||
|
return "SELECT $topClause * FROM $qualified;"
|
||||||
|
}
|
||||||
|
|
||||||
|
$from = $FromDate.ToString("yyyy-MM-dd")
|
||||||
|
$to = $ToDate.ToString("yyyy-MM-dd")
|
||||||
|
$dateColumnSql = Quote-NamePart $DateColumn
|
||||||
|
|
||||||
|
return @"
|
||||||
|
SELECT $topClause *
|
||||||
|
FROM $qualified
|
||||||
|
WHERE TRY_CONVERT(date, $dateColumnSql) >= CONVERT(date, '$from')
|
||||||
|
AND TRY_CONVERT(date, $dateColumnSql) < CONVERT(date, '$to')
|
||||||
|
ORDER BY TRY_CONVERT(date, $dateColumnSql);
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
function Normalize-FileName {
|
||||||
|
param([string]$Value)
|
||||||
|
|
||||||
|
return ($Value -replace '[\\/:*?"<>|]', '_')
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$runDirectory = Join-Path $OutputDirectory "Sage_SQL_CSV_Export_$timestamp"
|
||||||
|
New-Item -ItemType Directory -Path $runDirectory -Force | Out-Null
|
||||||
|
|
||||||
|
$databases = if ([string]::IsNullOrWhiteSpace($Database)) {
|
||||||
|
@(Get-UserDatabases)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@($Database)
|
||||||
|
}
|
||||||
|
|
||||||
|
$summary = New-Object System.Collections.Generic.List[object]
|
||||||
|
$allCandidates = New-Object System.Collections.Generic.List[object]
|
||||||
|
|
||||||
|
foreach ($db in $databases) {
|
||||||
|
Write-Host "Scanning database: $db"
|
||||||
|
try {
|
||||||
|
$candidates = @(Get-CandidateObjects $db)
|
||||||
|
foreach ($candidate in $candidates) {
|
||||||
|
$allCandidates.Add($candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = ""
|
||||||
|
Action = "Discovery failed"
|
||||||
|
Rows = 0
|
||||||
|
File = ""
|
||||||
|
Error = $_.Exception.Message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$candidatePath = Join-Path $runDirectory "candidate_objects.csv"
|
||||||
|
if ($allCandidates.Count -gt 0) {
|
||||||
|
$allCandidates | Export-Csv -LiteralPath $candidatePath -NoTypeInformation -Encoding UTF8 -Delimiter ";"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $DiscoverOnly) {
|
||||||
|
$objectsToExport = New-Object System.Collections.Generic.List[object]
|
||||||
|
|
||||||
|
foreach ($name in $ObjectName) {
|
||||||
|
if ([string]::IsNullOrWhiteSpace($name)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Database)) {
|
||||||
|
throw "When -ObjectName is used, pass -Database as well."
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = Split-SqlObjectName $name
|
||||||
|
$objectsToExport.Add([pscustomobject]@{
|
||||||
|
DatabaseName = $Database
|
||||||
|
SchemaName = $parsed.SchemaName
|
||||||
|
ObjectName = $parsed.ObjectName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ExportCandidates) {
|
||||||
|
foreach ($candidate in ($allCandidates | Sort-Object DatabaseName, @{Expression="Score"; Descending=$true} | Select-Object -First 25)) {
|
||||||
|
$objectsToExport.Add([pscustomobject]@{
|
||||||
|
DatabaseName = $candidate.DatabaseName
|
||||||
|
SchemaName = $candidate.SchemaName
|
||||||
|
ObjectName = $candidate.ObjectName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($object in $objectsToExport) {
|
||||||
|
$db = $object.DatabaseName
|
||||||
|
$schema = $object.SchemaName
|
||||||
|
$objectNameValue = $object.ObjectName
|
||||||
|
|
||||||
|
try {
|
||||||
|
$dateColumn = @(Get-DateColumns $db $schema $objectNameValue | Select-Object -First 1)[0]
|
||||||
|
$limit = if ($MaxRowsPerObject -gt 0) { $MaxRowsPerObject } elseif ($ObjectName.Count -gt 0) { 0 } else { $SampleRows }
|
||||||
|
$sql = Build-SelectSql $schema $objectNameValue $dateColumn $limit
|
||||||
|
$fileName = Normalize-FileName "$db.$schema.$objectNameValue.csv"
|
||||||
|
$path = Join-Path $runDirectory $fileName
|
||||||
|
Write-Host "Exporting $db.$schema.$objectNameValue -> $path"
|
||||||
|
$rows = Export-QueryToCsv $db $sql $path
|
||||||
|
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = "$schema.$objectNameValue"
|
||||||
|
Action = "Exported"
|
||||||
|
Rows = $rows
|
||||||
|
File = $path
|
||||||
|
DateColumn = $dateColumn
|
||||||
|
Error = ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = "$schema.$objectNameValue"
|
||||||
|
Action = "Export failed"
|
||||||
|
Rows = 0
|
||||||
|
File = ""
|
||||||
|
DateColumn = ""
|
||||||
|
Error = $_.Exception.Message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$summaryPath = Join-Path $runDirectory "export_summary.csv"
|
||||||
|
$summary | Export-Csv -LiteralPath $summaryPath -NoTypeInformation -Encoding UTF8 -Delimiter ";"
|
||||||
|
|
||||||
|
$readmePath = Join-Path $runDirectory "README.txt"
|
||||||
|
@"
|
||||||
|
Sage SQL CSV export
|
||||||
|
===================
|
||||||
|
|
||||||
|
Server instance: $ServerInstance
|
||||||
|
Database filter: $(if ($Database) { $Database } else { "(all accessible user databases)" })
|
||||||
|
From date: $($FromDate.ToString("yyyy-MM-dd"))
|
||||||
|
To date: $($ToDate.ToString("yyyy-MM-dd"))
|
||||||
|
|
||||||
|
Files:
|
||||||
|
- candidate_objects.csv: SQL tables/views that look relevant for sales/invoices.
|
||||||
|
- export_summary.csv: export status and row counts.
|
||||||
|
- *.csv: exported samples or selected full exports.
|
||||||
|
|
||||||
|
Recommended workflow:
|
||||||
|
1. Run discovery first:
|
||||||
|
.\Export-SageSqlCsv.ps1 -DiscoverOnly
|
||||||
|
2. Send candidate_objects.csv to Trafag/IT for selection.
|
||||||
|
3. Export selected objects:
|
||||||
|
.\Export-SageSqlCsv.ps1 -Database "DATABASE_NAME" -ObjectName "schema.table_or_view"
|
||||||
|
4. If the selected object is very large, add:
|
||||||
|
-FromDate "2025-01-01" -ToDate "2026-01-01" -MaxRowsPerObject 100000
|
||||||
|
|
||||||
|
The script only reads data. It does not change SQL Server or Sage.
|
||||||
|
"@ | Set-Content -LiteralPath $readmePath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Created folder:"
|
||||||
|
Write-Host " $runDirectory"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Main files:"
|
||||||
|
Write-Host " $candidatePath"
|
||||||
|
Write-Host " $summaryPath"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
Sage SQL CSV export
|
||||||
|
===================
|
||||||
|
|
||||||
|
Server instance: localhost
|
||||||
|
Database filter: Sage
|
||||||
|
From date: 2025-01-01
|
||||||
|
To date: 2026-01-01
|
||||||
|
|
||||||
|
Files:
|
||||||
|
- candidate_objects.csv: SQL tables/views that look relevant for sales/invoices.
|
||||||
|
- export_summary.csv: export status and row counts.
|
||||||
|
- *.csv: exported samples or selected full exports.
|
||||||
|
|
||||||
|
Recommended workflow:
|
||||||
|
1. Run discovery first:
|
||||||
|
.\Export-SageSqlCsv.ps1 -DiscoverOnly
|
||||||
|
2. Send candidate_objects.csv to Trafag/IT for selection.
|
||||||
|
3. Export selected objects:
|
||||||
|
.\Export-SageSqlCsv.ps1 -Database "DATABASE_NAME" -ObjectName "schema.table_or_view"
|
||||||
|
4. If the selected object is very large, add:
|
||||||
|
-FromDate "2025-01-01" -ToDate "2026-01-01" -MaxRowsPerObject 100000
|
||||||
|
|
||||||
|
The script only reads data. It does not change SQL Server or Sage.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
"CodigoEmpresa";"EstadisClave1";"EstadisClave2";"EstadisClave3";"Ejercicio";"Periodo";"Origen";"CodigoZona";"CodigoJefeZona_";"CodigoJefeVenta_";"CodigoComisionista";"CodigoComisionista2_";"CodigoComisionista3_";"CodigoComisionista4_";"CodigoCliente";"CodigoFamilia";"CodigoSubfamilia";"CodigoArticulo";"CodigoColor_";"GrupoTalla_";"UnidadesTalla01_";"UnidadesTalla02_";"UnidadesTalla03_";"UnidadesTalla04_";"UnidadesTalla05_";"UnidadesTalla06_";"UnidadesTalla07_";"UnidadesTalla08_";"UnidadesTalla09_";"UnidadesTalla10_";"UnidadesTalla11_";"UnidadesTalla12_";"UnidadesTalla13_";"UnidadesTalla14_";"UnidadesTalla15_";"UnidadesTalla16_";"UnidadesTalla17_";"UnidadesTalla18_";"UnidadesTalla19_";"UnidadesTalla20_";"UnidadesTalla21_";"UnidadesTalla22_";"UnidadesTalla23_";"UnidadesTalla24_";"UnidadesTalla25_";"UnidadesTalla26_";"UnidadesTalla27_";"UnidadesTalla28_";"UnidadesTalla29_";"UnidadesTalla30_";"UnidadesTalla31_";"UnidadesTalla32_";"UnidadesTalla33_";"UnidadesTalla34_";"UnidadesTalla35_";"UnidadesTalla36_";"UnidadesTalla37_";"UnidadesTalla38_";"UnidadesTalla39_";"UnidadesTalla40_";"ImporteTalla01_";"ImporteTalla02_";"ImporteTalla03_";"ImporteTalla04_";"ImporteTalla05_";"ImporteTalla06_";"ImporteTalla07_";"ImporteTalla08_";"ImporteTalla09_";"ImporteTalla10_";"ImporteTalla11_";"ImporteTalla12_";"ImporteTalla13_";"ImporteTalla14_";"ImporteTalla15_";"ImporteTalla16_";"ImporteTalla17_";"ImporteTalla18_";"ImporteTalla19_";"ImporteTalla20_";"ImporteTalla21_";"ImporteTalla22_";"ImporteTalla23_";"ImporteTalla24_";"ImporteTalla25_";"ImporteTalla26_";"ImporteTalla27_";"ImporteTalla28_";"ImporteTalla29_";"ImporteTalla30_";"ImporteTalla31_";"ImporteTalla32_";"ImporteTalla33_";"ImporteTalla34_";"ImporteTalla35_";"ImporteTalla36_";"ImporteTalla37_";"ImporteTalla38_";"ImporteTalla39_";"ImporteTalla40_";"UnidadesTotalTallas_";"ImporteTotalTallas_"
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
"oppCoId";"effeForecast";"effeNumber";"invoExercise";"invoSeries";"invoNumber";"effeOrder";"statusDelete";"customerCode";"customer";"effeAmount";"expirationDate";"invoDate";"emissionDate";"accountCode";"counterPart";"comment";"canalCode";"statusRemitted";"remittedType";"remittedDate";"remittedBank";"remittedNumber";"statusRisk";"statusUnpaid";"salesPersonId";"salesPerson";"effectType";"effectClass";"effeId";"invoId"
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
|||||||
|
"Database";"Object";"Action";"Rows";"File";"DateColumn";"Error"
|
||||||
|
"Sage";"dbo.CabeceraAlbaranCliente";"Exported";"1973";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.CabeceraAlbaranCliente.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.LineasAlbaranCliente";"Exported";"4814";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.LineasAlbaranCliente.csv";"FechaRegistro";""
|
||||||
|
"Sage";"dbo.EstadisVenta";"Exported";"16976";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.EstadisVenta.csv";;""
|
||||||
|
"Sage";"dbo.EstadisVentaTallas";"Exported";"0";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.EstadisVentaTallas.csv";;""
|
||||||
|
"Sage";"dbo.FacturasTB";"Exported";"3788";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.FacturasTB.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.MovimientosFacturas";"Exported";"6517";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.MovimientosFacturas.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.Vis_RTDV_EfectosFactura";"Exported";"0";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_103719\Sage.dbo.Vis_RTDV_EfectosFactura.csv";"expirationDate";""
|
||||||
|
Binary file not shown.
@@ -0,0 +1,215 @@
|
|||||||
|
param(
|
||||||
|
[string]$ServerInstance = "localhost",
|
||||||
|
[string]$Database = "Sage",
|
||||||
|
[datetime]$FromDate = "2025-01-01",
|
||||||
|
[datetime]$ToDate = "2026-01-01",
|
||||||
|
[string]$OutputDirectory = (Join-Path $env:USERPROFILE "Desktop")
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function New-Connection {
|
||||||
|
$builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
|
||||||
|
$builder["Data Source"] = $ServerInstance
|
||||||
|
$builder["Initial Catalog"] = $Database
|
||||||
|
$builder["Integrated Security"] = $true
|
||||||
|
$builder["TrustServerCertificate"] = $true
|
||||||
|
$builder["Connect Timeout"] = 15
|
||||||
|
return New-Object System.Data.SqlClient.SqlConnection($builder.ConnectionString)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Convert-ToCsvValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($null -eq $Value -or $Value -is [System.DBNull]) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Value -is [datetime]) {
|
||||||
|
$text = $Value.ToString("yyyy-MM-dd HH:mm:ss")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$text = [string]$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = $text.Replace('"', '""')
|
||||||
|
return '"' + $text + '"'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-QueryToCsv {
|
||||||
|
param(
|
||||||
|
[string]$Sql,
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 0
|
||||||
|
|
||||||
|
$fromParameter = $cmd.Parameters.Add("@FromDate", [System.Data.SqlDbType]::Date)
|
||||||
|
$fromParameter.Value = $FromDate.Date
|
||||||
|
|
||||||
|
$toParameter = $cmd.Parameters.Add("@ToDate", [System.Data.SqlDbType]::Date)
|
||||||
|
$toParameter.Value = $ToDate.Date
|
||||||
|
|
||||||
|
$writer = New-Object System.IO.StreamWriter($Path, $false, [System.Text.Encoding]::UTF8)
|
||||||
|
$rowCount = 0
|
||||||
|
$salesSum = [decimal]0
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
|
||||||
|
$headers = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetName($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($headers -join ";"))
|
||||||
|
|
||||||
|
$salesIndex = -1
|
||||||
|
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
if ($reader.GetName($i) -eq "SalesPriceValue") {
|
||||||
|
$salesIndex = $i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($reader.Read()) {
|
||||||
|
$values = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetValue($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($values -join ";"))
|
||||||
|
$rowCount++
|
||||||
|
|
||||||
|
if ($salesIndex -ge 0 -and -not $reader.IsDBNull($salesIndex)) {
|
||||||
|
$salesSum += [decimal]$reader.GetValue($salesIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$writer.Dispose()
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pscustomobject]@{
|
||||||
|
Rows = $rowCount
|
||||||
|
SalesPriceValueSum = $salesSum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$runDirectory = Join-Path $OutputDirectory "Sage_Spain_Sales_Export_$timestamp"
|
||||||
|
New-Item -ItemType Directory -Path $runDirectory -Force | Out-Null
|
||||||
|
|
||||||
|
$csvPath = Join-Path $runDirectory "Spain_Sales_2025.csv"
|
||||||
|
$summaryPath = Join-Path $runDirectory "Spain_Sales_2025_summary.txt"
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
SELECT
|
||||||
|
'TRES' AS TSC,
|
||||||
|
'Spanien' AS Land,
|
||||||
|
'Sage' AS SourceSystem,
|
||||||
|
c.CodigoEmpresa AS CompanyCode,
|
||||||
|
c.EjercicioAlbaran AS DeliveryYear,
|
||||||
|
c.SerieAlbaran AS DeliverySeries,
|
||||||
|
c.NumeroAlbaran AS DeliveryNumber,
|
||||||
|
c.EjercicioFactura AS InvoiceYear,
|
||||||
|
c.SerieFactura AS InvoiceSeries,
|
||||||
|
c.NumeroFactura AS InvoiceNumber,
|
||||||
|
l.Orden AS PositionOnInvoice,
|
||||||
|
l.LineasPosicion AS SourceLineId,
|
||||||
|
l.CodigoArticulo AS Material,
|
||||||
|
l.DescripcionArticulo AS Name,
|
||||||
|
l.Descripcion2Articulo AS Description2,
|
||||||
|
l.DescripcionLinea AS DescriptionLine,
|
||||||
|
l.CodigoFamilia AS ProductGroup,
|
||||||
|
l.CodigoSubfamilia AS ProductSubGroup,
|
||||||
|
CAST(l.Unidades AS decimal(19, 6)) AS Quantity,
|
||||||
|
c.CodigoCliente AS CustomerNumber,
|
||||||
|
c.Nombre AS CustomerName,
|
||||||
|
c.CodigoNacion AS CustomerCountryCode,
|
||||||
|
c.Nacion AS CustomerCountry,
|
||||||
|
CAST(l.PrecioCoste AS decimal(19, 6)) AS StandardCost,
|
||||||
|
CAST(l.ImporteCoste AS decimal(19, 6)) AS StandardCostValue,
|
||||||
|
'EUR' AS StandardCostCurrency,
|
||||||
|
CAST(l.ImporteNeto AS decimal(19, 6)) AS SalesPriceValue,
|
||||||
|
'EUR' AS SalesCurrency,
|
||||||
|
'EUR' AS DocumentCurrency,
|
||||||
|
'EUR' AS CompanyCurrency,
|
||||||
|
c.CodigoDivisa AS SageCurrencyCode,
|
||||||
|
CAST(c.BaseImponible AS decimal(19, 6)) AS DocumentNetAmount,
|
||||||
|
CAST(c.TotalIva AS decimal(19, 6)) AS DocumentVatAmount,
|
||||||
|
CAST(c.ImporteFactura AS decimal(19, 6)) AS DocumentGrossAmount,
|
||||||
|
c.FechaFactura AS InvoiceDate,
|
||||||
|
c.FechaAlbaran AS DeliveryDate,
|
||||||
|
l.FechaRegistro AS LineRegistrationDate,
|
||||||
|
c.EjercicioPedido AS OrderYear,
|
||||||
|
c.SeriePedido AS OrderSeries,
|
||||||
|
c.NumeroPedido AS OrderNumber,
|
||||||
|
c.SuPedido AS PurchaseOrderNumber,
|
||||||
|
c.CodigoExportacion_ AS Incoterms2020,
|
||||||
|
c.CondicionExportacion_ AS IncotermsText,
|
||||||
|
c.CodigoComisionista AS SalesResponsibleEmployee,
|
||||||
|
c.StatusAbono AS CreditStatus,
|
||||||
|
c.NoFacturable AS NonBillable,
|
||||||
|
c.TipoNuevaFra AS InvoiceType,
|
||||||
|
c.StatusFacturado AS BillingStatus,
|
||||||
|
CASE
|
||||||
|
WHEN c.TipoNuevaFra = 2 OR c.SerieFactura = 'REC' OR c.StatusAbono <> 0 THEN 'Credit Note'
|
||||||
|
ELSE 'Invoice'
|
||||||
|
END AS DocumentType
|
||||||
|
FROM dbo.CabeceraAlbaranCliente c
|
||||||
|
JOIN dbo.LineasAlbaranCliente l
|
||||||
|
ON l.CodigoEmpresa = c.CodigoEmpresa
|
||||||
|
AND l.EjercicioAlbaran = c.EjercicioAlbaran
|
||||||
|
AND l.SerieAlbaran = c.SerieAlbaran
|
||||||
|
AND l.NumeroAlbaran = c.NumeroAlbaran
|
||||||
|
WHERE c.FechaFactura >= @FromDate
|
||||||
|
AND c.FechaFactura < @ToDate
|
||||||
|
ORDER BY
|
||||||
|
c.FechaFactura,
|
||||||
|
c.SerieFactura,
|
||||||
|
c.NumeroFactura,
|
||||||
|
l.Orden;
|
||||||
|
"@
|
||||||
|
|
||||||
|
$result = Export-QueryToCsv -Sql $sql -Path $csvPath
|
||||||
|
|
||||||
|
@"
|
||||||
|
Sage Spain Sales CSV export
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Created: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
||||||
|
Server instance: $ServerInstance
|
||||||
|
Database: $Database
|
||||||
|
From date: $($FromDate.ToString("yyyy-MM-dd"))
|
||||||
|
To date: $($ToDate.ToString("yyyy-MM-dd"))
|
||||||
|
|
||||||
|
Output:
|
||||||
|
$csvPath
|
||||||
|
|
||||||
|
Rows:
|
||||||
|
$($result.Rows)
|
||||||
|
|
||||||
|
SalesPriceValue sum:
|
||||||
|
$($result.SalesPriceValueSum)
|
||||||
|
|
||||||
|
Source:
|
||||||
|
dbo.CabeceraAlbaranCliente joined with dbo.LineasAlbaranCliente
|
||||||
|
|
||||||
|
Filter:
|
||||||
|
CabeceraAlbaranCliente.FechaFactura >= FromDate
|
||||||
|
CabeceraAlbaranCliente.FechaFactura < ToDate
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Currency is set to EUR because Sage exports EnEuros_=-1 and CodigoDivisa is empty in the analysed rows.
|
||||||
|
- SalesPriceValue uses LineasAlbaranCliente.ImporteNeto.
|
||||||
|
- DocumentNetAmount uses CabeceraAlbaranCliente.BaseImponible.
|
||||||
|
- Credit notes are marked when TipoNuevaFra=2, SerieFactura='REC', or StatusAbono is non-zero.
|
||||||
|
"@ | Set-Content -LiteralPath $summaryPath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host "Created:"
|
||||||
|
Write-Host " $csvPath"
|
||||||
|
Write-Host " $summaryPath"
|
||||||
|
Write-Host "Rows: $($result.Rows)"
|
||||||
|
Write-Host "SalesPriceValue sum: $($result.SalesPriceValueSum)"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
Sage Spain final sales export candidate
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Run on the Spain Sage SQL Server machine.
|
||||||
|
|
||||||
|
PowerShell commands:
|
||||||
|
|
||||||
|
Set-ExecutionPolicy -Scope Process Bypass
|
||||||
|
.\Export-SageSpainSalesCsv.ps1
|
||||||
|
|
||||||
|
Output folder on Desktop:
|
||||||
|
|
||||||
|
Sage_Spain_Sales_Export_YYYYMMDD_HHMMSS
|
||||||
|
|
||||||
|
Files created:
|
||||||
|
|
||||||
|
- Spain_Sales_2025.csv
|
||||||
|
- Spain_Sales_2025_summary.txt
|
||||||
|
|
||||||
|
The script only reads SQL Server data. It does not change Sage or SQL Server.
|
||||||
|
|
||||||
|
Default source:
|
||||||
|
|
||||||
|
- Database: Sage
|
||||||
|
- Header: dbo.CabeceraAlbaranCliente
|
||||||
|
- Lines: dbo.LineasAlbaranCliente
|
||||||
|
- Date filter: CabeceraAlbaranCliente.FechaFactura from 2025-01-01 to 2026-01-01
|
||||||
|
- Sales value: LineasAlbaranCliente.ImporteNeto
|
||||||
|
|
||||||
|
If the SQL instance or database name differs:
|
||||||
|
|
||||||
|
.\Export-SageSpainSalesCsv.ps1 -ServerInstance "localhost" -Database "Sage"
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"CapturedAt": "2026-05-05T10:05:13.9281781+02:00",
|
||||||
|
"ComputerName": "WIN-4BJQJ9S1PVJ",
|
||||||
|
"UserName": "WIN-4BJQJ9S1PVJ\\Administrador",
|
||||||
|
"Windows": {
|
||||||
|
"Caption": "Microsoft Windows Server 2019 Standard",
|
||||||
|
"Version": "10.0.17763",
|
||||||
|
"BuildNumber": "17763",
|
||||||
|
"InstallDate": "\/Date(1601446676000)\/"
|
||||||
|
},
|
||||||
|
"SageUninstallEntries": [
|
||||||
|
{
|
||||||
|
"DisplayName": "JRE 2.5",
|
||||||
|
"DisplayVersion": null,
|
||||||
|
"Publisher": "Sage Logic Control",
|
||||||
|
"InstallDate": null,
|
||||||
|
"InstallLocation": null,
|
||||||
|
"UninstallString": "\"C:\\Windows\\unins000.exe\"",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\JRE_is1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"DisplayName": "Sage 200c",
|
||||||
|
"DisplayVersion": "2026.56.000",
|
||||||
|
"Publisher": "Sage Spain",
|
||||||
|
"InstallDate": null,
|
||||||
|
"InstallLocation": null,
|
||||||
|
"UninstallString": "C:\\Program Files (x86)\\Sage\\Sage 200c\\Setup\\Uninstall\\Sage.Uninstall.exe",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Sage 200c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"DisplayName": "Sage Renta Componentes",
|
||||||
|
"DisplayVersion": "1.00.0000",
|
||||||
|
"Publisher": "Sage Spain",
|
||||||
|
"InstallDate": "20201021",
|
||||||
|
"InstallLocation": "C:\\Windows\\SysWOW64\\",
|
||||||
|
"UninstallString": "MsiExec.exe /X{0ADD979C-205B-4264-B903-6F953F362917}",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{0ADD979C-205B-4264-B903-6F953F362917}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"DisplayName": "Sage SGE Runtime",
|
||||||
|
"DisplayVersion": "1.00.0000",
|
||||||
|
"Publisher": "Sage Spain",
|
||||||
|
"InstallDate": "20201021",
|
||||||
|
"InstallLocation": "C:\\Windows\\SysWOW64\\",
|
||||||
|
"UninstallString": "MsiExec.exe /X{1FFF90A6-3F93-4123-9C3B-54EBBDD22757}",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{1FFF90A6-3F93-4123-9C3B-54EBBDD22757}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"DisplayName": "Sage Live Update Service",
|
||||||
|
"DisplayVersion": "1.0.8.0",
|
||||||
|
"Publisher": "Sage",
|
||||||
|
"InstallDate": "20230314",
|
||||||
|
"InstallLocation": "",
|
||||||
|
"UninstallString": "MsiExec.exe /I{6D538240-299A-47CC-8782-2062AD2F2189}",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{6D538240-299A-47CC-8782-2062AD2F2189}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"DisplayName": "Sage API OnPremise Service",
|
||||||
|
"DisplayVersion": "1.2.8.0",
|
||||||
|
"Publisher": "Sage",
|
||||||
|
"InstallDate": "20201021",
|
||||||
|
"InstallLocation": "",
|
||||||
|
"UninstallString": "MsiExec.exe /I{9881C355-CB1B-4007-AB3A-B12F222318DB}",
|
||||||
|
"PSPath": "Microsoft.PowerShell.Core\\Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9881C355-CB1B-4007-AB3A-B12F222318DB}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SageFileVersions": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"SqlRegistryInstances": [
|
||||||
|
{
|
||||||
|
"InstanceName": "MSSQLSERVER",
|
||||||
|
"InstanceId": "MSSQL15.MSSQLSERVER",
|
||||||
|
"Edition": "Standard Edition",
|
||||||
|
"Version": "15.0.2000.5",
|
||||||
|
"PatchLevel": "15.0.2155.2",
|
||||||
|
"ProductCode": "{A60B3D8E-5311-4BF1-AF7A-D1AC15F9152E}",
|
||||||
|
"SQLPath": "C:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL",
|
||||||
|
"SetupPath": "HKLM:\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\Setup"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SqlServices": [
|
||||||
|
{
|
||||||
|
"Name": "MSSQLFDLauncher",
|
||||||
|
"DisplayName": "SQL Full-text Filter Daemon Launcher (MSSQLSERVER)",
|
||||||
|
"State": "Running",
|
||||||
|
"StartMode": "Manual",
|
||||||
|
"PathName": "\"C:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Binn\\fdlauncher.exe\" -s MSSQL15.MSSQLSERVER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "MSSQLSERVER",
|
||||||
|
"DisplayName": "SQL Server (MSSQLSERVER)",
|
||||||
|
"State": "Running",
|
||||||
|
"StartMode": "Auto",
|
||||||
|
"PathName": "\"C:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Binn\\sqlservr.exe\" -sMSSQLSERVER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "SQLBrowser",
|
||||||
|
"DisplayName": "SQL Server Browser",
|
||||||
|
"State": "Stopped",
|
||||||
|
"StartMode": "Disabled",
|
||||||
|
"PathName": "\"C:\\Program Files (x86)\\Microsoft SQL Server\\90\\Shared\\sqlbrowser.exe\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "SQLSERVERAGENT",
|
||||||
|
"DisplayName": "Agente SQL Server (MSSQLSERVER)",
|
||||||
|
"State": "Running",
|
||||||
|
"StartMode": "Auto",
|
||||||
|
"PathName": "\"C:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Binn\\SQLAGENT.EXE\" -i MSSQLSERVER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "SQLTELEMETRY",
|
||||||
|
"DisplayName": "Servicio CEIP de SQL Server (MSSQLSERVER)",
|
||||||
|
"State": "Running",
|
||||||
|
"StartMode": "Auto",
|
||||||
|
"PathName": "\"C:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Binn\\sqlceip.exe\" -Service "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "SQLWriter",
|
||||||
|
"DisplayName": "SQL Server VSS Writer",
|
||||||
|
"State": "Running",
|
||||||
|
"StartMode": "Auto",
|
||||||
|
"PathName": "\"C:\\Program Files\\Microsoft SQL Server\\90\\Shared\\sqlwriter.exe\""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SqlcmdPath": "C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\SQLCMD.EXE",
|
||||||
|
"SqlQueryResults": [
|
||||||
|
{
|
||||||
|
"Instance": "localhost",
|
||||||
|
"Success": true,
|
||||||
|
"Output": "FullVersion|ProductVersion|ProductLevel|Edition|EngineEdition|MachineName|ServerName|InstanceName|Collation\r\n-----------|--------------|------------|-------|-------------|-----------|----------|------------|---------\r\nMicrosoft SQL Server 2019 (RTM-GDR) (KB5068405) - 15.0.2155.2 (X64) \r\n\tOct 7 2025 21:11:52 \r\n\tCopyright (C) 2019 Microsoft Corporation\r\n\tStandard Edition (64-bit) on Windows Server 2019 Standard 10.0 \u003cX64\u003e (Build 17763: ) (Hypervisor)\r\n|15.0.2155.2|RTM|Standard Edition (64-bit)|2|WIN-4BJQJ9S1PVJ|WIN-4BJQJ9S1PVJ|NULL|Latin1_General_CI_AI"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
============================================================
|
||||||
|
Capture metadata
|
||||||
|
============================================================
|
||||||
|
Timestamp: 2026-05-05 10:05:13
|
||||||
|
Computer: WIN-4BJQJ9S1PVJ
|
||||||
|
User: WIN-4BJQJ9S1PVJ\Administrador
|
||||||
|
Output text: C:\Users\Administrador\Desktop\Sage_SQL_Environment_20260505_100511.txt
|
||||||
|
Output json: C:\Users\Administrador\Desktop\Sage_SQL_Environment_20260505_100511.json
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
Windows / machine
|
||||||
|
============================================================
|
||||||
|
Manufacturer: Xen
|
||||||
|
Model: HVM domU
|
||||||
|
OS: Microsoft Windows Server 2019 Standard
|
||||||
|
OS Version: 10.0.17763
|
||||||
|
OS Build: 17763
|
||||||
|
Install date: 09/30/2020 08:17:56
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
Sage entries from installed programs
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
|
||||||
|
DisplayName : JRE 2.5
|
||||||
|
DisplayVersion :
|
||||||
|
Publisher : Sage Logic Control
|
||||||
|
InstallDate :
|
||||||
|
InstallLocation :
|
||||||
|
UninstallString : "C:\Windows\unins000.exe"
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\JRE_is1
|
||||||
|
|
||||||
|
DisplayName : Sage 200c
|
||||||
|
DisplayVersion : 2026.56.000
|
||||||
|
Publisher : Sage Spain
|
||||||
|
InstallDate :
|
||||||
|
InstallLocation :
|
||||||
|
UninstallString : C:\Program Files (x86)\Sage\Sage 200c\Setup\Uninstall\Sage.Uninstall.exe
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Sage 200c
|
||||||
|
|
||||||
|
DisplayName : Sage Renta Componentes
|
||||||
|
DisplayVersion : 1.00.0000
|
||||||
|
Publisher : Sage Spain
|
||||||
|
InstallDate : 20201021
|
||||||
|
InstallLocation : C:\Windows\SysWOW64\
|
||||||
|
UninstallString : MsiExec.exe /X{0ADD979C-205B-4264-B903-6F953F362917}
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{0ADD979C-205B-4264-B903-6F953F3
|
||||||
|
62917}
|
||||||
|
|
||||||
|
DisplayName : Sage SGE Runtime
|
||||||
|
DisplayVersion : 1.00.0000
|
||||||
|
Publisher : Sage Spain
|
||||||
|
InstallDate : 20201021
|
||||||
|
InstallLocation : C:\Windows\SysWOW64\
|
||||||
|
UninstallString : MsiExec.exe /X{1FFF90A6-3F93-4123-9C3B-54EBBDD22757}
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{1FFF90A6-3F93-4123-9C3B-54EBBDD
|
||||||
|
22757}
|
||||||
|
|
||||||
|
DisplayName : Sage Live Update Service
|
||||||
|
DisplayVersion : 1.0.8.0
|
||||||
|
Publisher : Sage
|
||||||
|
InstallDate : 20230314
|
||||||
|
InstallLocation :
|
||||||
|
UninstallString : MsiExec.exe /I{6D538240-299A-47CC-8782-2062AD2F2189}
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{6D538240-299A-47CC-8782-2062AD2
|
||||||
|
F2189}
|
||||||
|
|
||||||
|
DisplayName : Sage API OnPremise Service
|
||||||
|
DisplayVersion : 1.2.8.0
|
||||||
|
Publisher : Sage
|
||||||
|
InstallDate : 20201021
|
||||||
|
InstallLocation :
|
||||||
|
UninstallString : MsiExec.exe /I{9881C355-CB1B-4007-AB3A-B12F222318DB}
|
||||||
|
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{9881C355-CB1B-4007-AB3A-B12F222
|
||||||
|
318DB}
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
Sage file versions
|
||||||
|
============================================================
|
||||||
|
Skipped. Re-run with -ScanProgramFiles for file version scan.
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
SQL Server instances from registry
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
|
||||||
|
InstanceName : MSSQLSERVER
|
||||||
|
InstanceId : MSSQL15.MSSQLSERVER
|
||||||
|
Edition : Standard Edition
|
||||||
|
Version : 15.0.2000.5
|
||||||
|
PatchLevel : 15.0.2155.2
|
||||||
|
ProductCode : {A60B3D8E-5311-4BF1-AF7A-D1AC15F9152E}
|
||||||
|
SQLPath : C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL
|
||||||
|
SetupPath : HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MSSQLSERVER\Setup
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
SQL Server services
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
Name DisplayName State StartMode PathName
|
||||||
|
---- ----------- ----- --------- --------
|
||||||
|
MSSQLFDLauncher SQL Full-text Filter Daemon Launcher (MSSQLSERVER) Running Manual "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Binn\fdlauncher....
|
||||||
|
MSSQLSERVER SQL Server (MSSQLSERVER) Running Auto "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Binn\sqlservr.ex...
|
||||||
|
SQLBrowser SQL Server Browser Stopped Disabled "C:\Program Files (x86)\Microsoft SQL Server\90\Shared\sqlbrowser.exe"
|
||||||
|
SQLSERVERAGENT Agente SQL Server (MSSQLSERVER) Running Auto "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Binn\SQLAGENT.EX...
|
||||||
|
SQLTELEMETRY Servicio CEIP de SQL Server (MSSQLSERVER) Running Auto "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Binn\sqlceip.exe...
|
||||||
|
SQLWriter SQL Server VSS Writer Running Auto "C:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe"
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
SQL Server live query
|
||||||
|
============================================================
|
||||||
|
sqlcmd path: C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\SQLCMD.EXE
|
||||||
|
|
||||||
|
Instance: localhost
|
||||||
|
Success: True
|
||||||
|
FullVersion|ProductVersion|ProductLevel|Edition|EngineEdition|MachineName|ServerName|InstanceName|Collation
|
||||||
|
-----------|--------------|------------|-------|-------------|-----------|----------|------------|---------
|
||||||
|
Microsoft SQL Server 2019 (RTM-GDR) (KB5068405) - 15.0.2155.2 (X64)
|
||||||
|
Oct 7 2025 21:11:52
|
||||||
|
Copyright (C) 2019 Microsoft Corporation
|
||||||
|
Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor)
|
||||||
|
|15.0.2155.2|RTM|Standard Edition (64-bit)|2|WIN-4BJQJ9S1PVJ|WIN-4BJQJ9S1PVJ|NULL|Latin1_General_CI_AI
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
|
|
@@ -0,0 +1,8 @@
|
|||||||
|
info: Microsoft.Hosting.Lifetime[14]
|
||||||
|
Now listening on: http://localhost:55417
|
||||||
|
info: Microsoft.Hosting.Lifetime[0]
|
||||||
|
Application started. Press Ctrl+C to shut down.
|
||||||
|
info: Microsoft.Hosting.Lifetime[0]
|
||||||
|
Hosting environment: Production
|
||||||
|
info: Microsoft.Hosting.Lifetime[0]
|
||||||
|
Content root path: C:\Users\koi\source\repos\Ai\TrafagSalesExporter
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
Sage SQL CSV export
|
||||||
|
===================
|
||||||
|
|
||||||
|
Server instance: localhost
|
||||||
|
Database filter: Sage
|
||||||
|
From date: 2025-01-01
|
||||||
|
To date: 2026-01-01
|
||||||
|
|
||||||
|
Files:
|
||||||
|
- candidate_objects.csv: SQL tables/views that look relevant for sales/invoices.
|
||||||
|
- export_summary.csv: export status and row counts.
|
||||||
|
- *.csv: exported samples or selected full exports.
|
||||||
|
|
||||||
|
Recommended workflow:
|
||||||
|
1. Run discovery first:
|
||||||
|
.\Export-SageSqlCsv.ps1 -DiscoverOnly
|
||||||
|
2. Send candidate_objects.csv to Trafag/IT for selection.
|
||||||
|
3. Export selected objects:
|
||||||
|
.\Export-SageSqlCsv.ps1 -Database "DATABASE_NAME" -ObjectName "schema.table_or_view"
|
||||||
|
4. If the selected object is very large, add:
|
||||||
|
-FromDate "2025-01-01" -ToDate "2026-01-01" -MaxRowsPerObject 100000
|
||||||
|
|
||||||
|
The script only reads data. It does not change SQL Server or Sage.
|
||||||
+1974
File diff suppressed because it is too large
Load Diff
+16977
File diff suppressed because it is too large
Load Diff
+1
@@ -0,0 +1 @@
|
|||||||
|
"CodigoEmpresa";"EstadisClave1";"EstadisClave2";"EstadisClave3";"Ejercicio";"Periodo";"Origen";"CodigoZona";"CodigoJefeZona_";"CodigoJefeVenta_";"CodigoComisionista";"CodigoComisionista2_";"CodigoComisionista3_";"CodigoComisionista4_";"CodigoCliente";"CodigoFamilia";"CodigoSubfamilia";"CodigoArticulo";"CodigoColor_";"GrupoTalla_";"UnidadesTalla01_";"UnidadesTalla02_";"UnidadesTalla03_";"UnidadesTalla04_";"UnidadesTalla05_";"UnidadesTalla06_";"UnidadesTalla07_";"UnidadesTalla08_";"UnidadesTalla09_";"UnidadesTalla10_";"UnidadesTalla11_";"UnidadesTalla12_";"UnidadesTalla13_";"UnidadesTalla14_";"UnidadesTalla15_";"UnidadesTalla16_";"UnidadesTalla17_";"UnidadesTalla18_";"UnidadesTalla19_";"UnidadesTalla20_";"UnidadesTalla21_";"UnidadesTalla22_";"UnidadesTalla23_";"UnidadesTalla24_";"UnidadesTalla25_";"UnidadesTalla26_";"UnidadesTalla27_";"UnidadesTalla28_";"UnidadesTalla29_";"UnidadesTalla30_";"UnidadesTalla31_";"UnidadesTalla32_";"UnidadesTalla33_";"UnidadesTalla34_";"UnidadesTalla35_";"UnidadesTalla36_";"UnidadesTalla37_";"UnidadesTalla38_";"UnidadesTalla39_";"UnidadesTalla40_";"ImporteTalla01_";"ImporteTalla02_";"ImporteTalla03_";"ImporteTalla04_";"ImporteTalla05_";"ImporteTalla06_";"ImporteTalla07_";"ImporteTalla08_";"ImporteTalla09_";"ImporteTalla10_";"ImporteTalla11_";"ImporteTalla12_";"ImporteTalla13_";"ImporteTalla14_";"ImporteTalla15_";"ImporteTalla16_";"ImporteTalla17_";"ImporteTalla18_";"ImporteTalla19_";"ImporteTalla20_";"ImporteTalla21_";"ImporteTalla22_";"ImporteTalla23_";"ImporteTalla24_";"ImporteTalla25_";"ImporteTalla26_";"ImporteTalla27_";"ImporteTalla28_";"ImporteTalla29_";"ImporteTalla30_";"ImporteTalla31_";"ImporteTalla32_";"ImporteTalla33_";"ImporteTalla34_";"ImporteTalla35_";"ImporteTalla36_";"ImporteTalla37_";"ImporteTalla38_";"ImporteTalla39_";"ImporteTalla40_";"UnidadesTotalTallas_";"ImporteTotalTallas_"
|
||||||
|
+3789
File diff suppressed because it is too large
Load Diff
+36412
File diff suppressed because it is too large
Load Diff
+6518
File diff suppressed because it is too large
Load Diff
+1
@@ -0,0 +1 @@
|
|||||||
|
"oppCoId";"effeForecast";"effeNumber";"invoExercise";"invoSeries";"invoNumber";"effeOrder";"statusDelete";"customerCode";"customer";"effeAmount";"expirationDate";"invoDate";"emissionDate";"accountCode";"counterPart";"comment";"canalCode";"statusRemitted";"remittedType";"remittedDate";"remittedBank";"remittedNumber";"statusRisk";"statusUnpaid";"salesPersonId";"salesPerson";"effectType";"effectClass";"effeId";"invoId"
|
||||||
|
+81
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
|||||||
|
"Database";"Object";"Action";"Rows";"File";"DateColumn";"Error"
|
||||||
|
"Sage";"dbo.CabeceraAlbaranCliente";"Exported";"1973";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.CabeceraAlbaranCliente.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.LineasAlbaranCliente";"Exported";"4814";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.LineasAlbaranCliente.csv";"FechaRegistro";""
|
||||||
|
"Sage";"dbo.EstadisVenta";"Exported";"16976";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.EstadisVenta.csv";;""
|
||||||
|
"Sage";"dbo.EstadisVentaTallas";"Exported";"0";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.EstadisVentaTallas.csv";;""
|
||||||
|
"Sage";"dbo.FacturasTB";"Exported";"3788";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.FacturasTB.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.MovimientosFacturas";"Exported";"6517";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.MovimientosFacturas.csv";"FechaFactura";""
|
||||||
|
"Sage";"dbo.Vis_RTDV_EfectosFactura";"Exported";"0";"C:\Users\Administrador\Desktop\Sage_SQL_CSV_Export_20260505_102507\Sage.dbo.Vis_RTDV_EfectosFactura.csv";"expirationDate";""
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
Sage Spain Sales CSV export
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Created: 2026-05-05 10:44:06
|
||||||
|
Server instance: localhost
|
||||||
|
Database: Sage
|
||||||
|
From date: 2025-01-01
|
||||||
|
To date: 2026-01-01
|
||||||
|
|
||||||
|
Output:
|
||||||
|
C:\Users\Administrador\Desktop\Sage_Spain_Sales_Export_20260505_104358\Spain_Sales_2025.csv
|
||||||
|
|
||||||
|
Rows:
|
||||||
|
4341
|
||||||
|
|
||||||
|
SalesPriceValue sum:
|
||||||
|
3082320.180000
|
||||||
|
|
||||||
|
Source:
|
||||||
|
dbo.CabeceraAlbaranCliente joined with dbo.LineasAlbaranCliente
|
||||||
|
|
||||||
|
Filter:
|
||||||
|
CabeceraAlbaranCliente.FechaFactura >= FromDate
|
||||||
|
CabeceraAlbaranCliente.FechaFactura < ToDate
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Currency is set to EUR because Sage exports EnEuros_=-1 and CodigoDivisa is empty in the analysed rows.
|
||||||
|
- SalesPriceValue uses LineasAlbaranCliente.ImporteNeto.
|
||||||
|
- DocumentNetAmount uses CabeceraAlbaranCliente.BaseImponible.
|
||||||
|
- Credit notes are marked when TipoNuevaFra=2, SerieFactura='REC', or StatusAbono is non-zero.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
$scriptPath = Join-Path $PSScriptRoot "Export-SageSqlCsv.ps1"
|
||||||
|
|
||||||
|
& $scriptPath `
|
||||||
|
-Database "Sage" `
|
||||||
|
-ObjectName @(
|
||||||
|
"dbo.CabeceraAlbaranCliente",
|
||||||
|
"dbo.LineasAlbaranCliente",
|
||||||
|
"dbo.EstadisVenta",
|
||||||
|
"dbo.EstadisVentaTallas",
|
||||||
|
"dbo.FacturasTB",
|
||||||
|
"dbo.MovimientosFacturas",
|
||||||
|
"dbo.Vis_RTDV_EfectosFactura"
|
||||||
|
) `
|
||||||
|
-FromDate "2025-01-01" `
|
||||||
|
-ToDate "2026-01-01" `
|
||||||
|
-MaxRowsPerObject 10000
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
$scriptPath = Join-Path $PSScriptRoot "Export-SageSqlCsv.ps1"
|
||||||
|
|
||||||
|
& $scriptPath `
|
||||||
|
-Database "Sage" `
|
||||||
|
-ObjectName @(
|
||||||
|
"dbo.CabeceraAlbaranCliente",
|
||||||
|
"dbo.LineasAlbaranCliente",
|
||||||
|
"dbo.EstadisVenta",
|
||||||
|
"dbo.EstadisVentaTallas",
|
||||||
|
"dbo.FacturasTB",
|
||||||
|
"dbo.MovimientosFacturas",
|
||||||
|
"dbo.Vis_RTDV_EfectosFactura"
|
||||||
|
) `
|
||||||
|
-FromDate "2025-01-01" `
|
||||||
|
-ToDate "2026-01-01"
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
param(
|
||||||
|
[string]$ServerInstance = "localhost",
|
||||||
|
[string]$Database = "Sage",
|
||||||
|
[datetime]$FromDate = "2025-01-01",
|
||||||
|
[datetime]$ToDate = "2026-01-01",
|
||||||
|
[string]$OutputDirectory = (Join-Path $env:USERPROFILE "Desktop")
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function New-Connection {
|
||||||
|
$builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
|
||||||
|
$builder["Data Source"] = $ServerInstance
|
||||||
|
$builder["Initial Catalog"] = $Database
|
||||||
|
$builder["Integrated Security"] = $true
|
||||||
|
$builder["TrustServerCertificate"] = $true
|
||||||
|
$builder["Connect Timeout"] = 15
|
||||||
|
return New-Object System.Data.SqlClient.SqlConnection($builder.ConnectionString)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Convert-ToCsvValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($null -eq $Value -or $Value -is [System.DBNull]) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Value -is [datetime]) {
|
||||||
|
$text = $Value.ToString("yyyy-MM-dd HH:mm:ss")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$text = [string]$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = $text.Replace('"', '""')
|
||||||
|
return '"' + $text + '"'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-QueryToCsv {
|
||||||
|
param(
|
||||||
|
[string]$Sql,
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 0
|
||||||
|
|
||||||
|
$fromParameter = $cmd.Parameters.Add("@FromDate", [System.Data.SqlDbType]::Date)
|
||||||
|
$fromParameter.Value = $FromDate.Date
|
||||||
|
|
||||||
|
$toParameter = $cmd.Parameters.Add("@ToDate", [System.Data.SqlDbType]::Date)
|
||||||
|
$toParameter.Value = $ToDate.Date
|
||||||
|
|
||||||
|
$writer = New-Object System.IO.StreamWriter($Path, $false, [System.Text.Encoding]::UTF8)
|
||||||
|
$rowCount = 0
|
||||||
|
$salesSum = [decimal]0
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
|
||||||
|
$headers = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetName($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($headers -join ";"))
|
||||||
|
|
||||||
|
$salesIndex = -1
|
||||||
|
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
if ($reader.GetName($i) -eq "SalesPriceValue") {
|
||||||
|
$salesIndex = $i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($reader.Read()) {
|
||||||
|
$values = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetValue($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($values -join ";"))
|
||||||
|
$rowCount++
|
||||||
|
|
||||||
|
if ($salesIndex -ge 0 -and -not $reader.IsDBNull($salesIndex)) {
|
||||||
|
$salesSum += [decimal]$reader.GetValue($salesIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$writer.Dispose()
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pscustomobject]@{
|
||||||
|
Rows = $rowCount
|
||||||
|
SalesPriceValueSum = $salesSum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$runDirectory = Join-Path $OutputDirectory "Sage_Spain_Sales_Export_$timestamp"
|
||||||
|
New-Item -ItemType Directory -Path $runDirectory -Force | Out-Null
|
||||||
|
|
||||||
|
$csvPath = Join-Path $runDirectory "Spain_Sales_2025.csv"
|
||||||
|
$summaryPath = Join-Path $runDirectory "Spain_Sales_2025_summary.txt"
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
SELECT
|
||||||
|
'TRES' AS TSC,
|
||||||
|
'Spanien' AS Land,
|
||||||
|
'Sage' AS SourceSystem,
|
||||||
|
c.CodigoEmpresa AS CompanyCode,
|
||||||
|
c.EjercicioAlbaran AS DeliveryYear,
|
||||||
|
c.SerieAlbaran AS DeliverySeries,
|
||||||
|
c.NumeroAlbaran AS DeliveryNumber,
|
||||||
|
c.EjercicioFactura AS InvoiceYear,
|
||||||
|
c.SerieFactura AS InvoiceSeries,
|
||||||
|
c.NumeroFactura AS InvoiceNumber,
|
||||||
|
l.Orden AS PositionOnInvoice,
|
||||||
|
l.LineasPosicion AS SourceLineId,
|
||||||
|
l.CodigoArticulo AS Material,
|
||||||
|
l.DescripcionArticulo AS Name,
|
||||||
|
l.Descripcion2Articulo AS Description2,
|
||||||
|
l.DescripcionLinea AS DescriptionLine,
|
||||||
|
l.CodigoFamilia AS ProductGroup,
|
||||||
|
l.CodigoSubfamilia AS ProductSubGroup,
|
||||||
|
CAST(l.Unidades AS decimal(19, 6)) AS Quantity,
|
||||||
|
c.CodigoCliente AS CustomerNumber,
|
||||||
|
c.Nombre AS CustomerName,
|
||||||
|
c.CodigoNacion AS CustomerCountryCode,
|
||||||
|
c.Nacion AS CustomerCountry,
|
||||||
|
CAST(l.PrecioCoste AS decimal(19, 6)) AS StandardCost,
|
||||||
|
CAST(l.ImporteCoste AS decimal(19, 6)) AS StandardCostValue,
|
||||||
|
'EUR' AS StandardCostCurrency,
|
||||||
|
CAST(l.ImporteNeto AS decimal(19, 6)) AS SalesPriceValue,
|
||||||
|
'EUR' AS SalesCurrency,
|
||||||
|
'EUR' AS DocumentCurrency,
|
||||||
|
'EUR' AS CompanyCurrency,
|
||||||
|
c.CodigoDivisa AS SageCurrencyCode,
|
||||||
|
CAST(c.BaseImponible AS decimal(19, 6)) AS DocumentNetAmount,
|
||||||
|
CAST(c.TotalIva AS decimal(19, 6)) AS DocumentVatAmount,
|
||||||
|
CAST(c.ImporteFactura AS decimal(19, 6)) AS DocumentGrossAmount,
|
||||||
|
c.FechaFactura AS InvoiceDate,
|
||||||
|
c.FechaAlbaran AS DeliveryDate,
|
||||||
|
l.FechaRegistro AS LineRegistrationDate,
|
||||||
|
c.EjercicioPedido AS OrderYear,
|
||||||
|
c.SeriePedido AS OrderSeries,
|
||||||
|
c.NumeroPedido AS OrderNumber,
|
||||||
|
c.SuPedido AS PurchaseOrderNumber,
|
||||||
|
c.CodigoExportacion_ AS Incoterms2020,
|
||||||
|
c.CondicionExportacion_ AS IncotermsText,
|
||||||
|
c.CodigoComisionista AS SalesResponsibleEmployee,
|
||||||
|
c.StatusAbono AS CreditStatus,
|
||||||
|
c.NoFacturable AS NonBillable,
|
||||||
|
c.TipoNuevaFra AS InvoiceType,
|
||||||
|
c.StatusFacturado AS BillingStatus,
|
||||||
|
CASE
|
||||||
|
WHEN c.TipoNuevaFra = 2 OR c.SerieFactura = 'REC' OR c.StatusAbono <> 0 THEN 'Credit Note'
|
||||||
|
ELSE 'Invoice'
|
||||||
|
END AS DocumentType
|
||||||
|
FROM dbo.CabeceraAlbaranCliente c
|
||||||
|
JOIN dbo.LineasAlbaranCliente l
|
||||||
|
ON l.CodigoEmpresa = c.CodigoEmpresa
|
||||||
|
AND l.EjercicioAlbaran = c.EjercicioAlbaran
|
||||||
|
AND l.SerieAlbaran = c.SerieAlbaran
|
||||||
|
AND l.NumeroAlbaran = c.NumeroAlbaran
|
||||||
|
WHERE c.FechaFactura >= @FromDate
|
||||||
|
AND c.FechaFactura < @ToDate
|
||||||
|
ORDER BY
|
||||||
|
c.FechaFactura,
|
||||||
|
c.SerieFactura,
|
||||||
|
c.NumeroFactura,
|
||||||
|
l.Orden;
|
||||||
|
"@
|
||||||
|
|
||||||
|
$result = Export-QueryToCsv -Sql $sql -Path $csvPath
|
||||||
|
|
||||||
|
@"
|
||||||
|
Sage Spain Sales CSV export
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Created: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
||||||
|
Server instance: $ServerInstance
|
||||||
|
Database: $Database
|
||||||
|
From date: $($FromDate.ToString("yyyy-MM-dd"))
|
||||||
|
To date: $($ToDate.ToString("yyyy-MM-dd"))
|
||||||
|
|
||||||
|
Output:
|
||||||
|
$csvPath
|
||||||
|
|
||||||
|
Rows:
|
||||||
|
$($result.Rows)
|
||||||
|
|
||||||
|
SalesPriceValue sum:
|
||||||
|
$($result.SalesPriceValueSum)
|
||||||
|
|
||||||
|
Source:
|
||||||
|
dbo.CabeceraAlbaranCliente joined with dbo.LineasAlbaranCliente
|
||||||
|
|
||||||
|
Filter:
|
||||||
|
CabeceraAlbaranCliente.FechaFactura >= FromDate
|
||||||
|
CabeceraAlbaranCliente.FechaFactura < ToDate
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Currency is set to EUR because Sage exports EnEuros_=-1 and CodigoDivisa is empty in the analysed rows.
|
||||||
|
- SalesPriceValue uses LineasAlbaranCliente.ImporteNeto.
|
||||||
|
- DocumentNetAmount uses CabeceraAlbaranCliente.BaseImponible.
|
||||||
|
- Credit notes are marked when TipoNuevaFra=2, SerieFactura='REC', or StatusAbono is non-zero.
|
||||||
|
"@ | Set-Content -LiteralPath $summaryPath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host "Created:"
|
||||||
|
Write-Host " $csvPath"
|
||||||
|
Write-Host " $summaryPath"
|
||||||
|
Write-Host "Rows: $($result.Rows)"
|
||||||
|
Write-Host "SalesPriceValue sum: $($result.SalesPriceValueSum)"
|
||||||
@@ -0,0 +1,410 @@
|
|||||||
|
param(
|
||||||
|
[string]$ServerInstance = "localhost",
|
||||||
|
[string]$Database = "",
|
||||||
|
[string[]]$ObjectName = @(),
|
||||||
|
[datetime]$FromDate = "2025-01-01",
|
||||||
|
[datetime]$ToDate = "2026-01-01",
|
||||||
|
[string]$OutputDirectory = (Join-Path $env:USERPROFILE "Desktop"),
|
||||||
|
[int]$SampleRows = 500,
|
||||||
|
[int]$MaxRowsPerObject = 0,
|
||||||
|
[switch]$DiscoverOnly,
|
||||||
|
[switch]$ExportCandidates,
|
||||||
|
[switch]$IncludeSystemDatabases
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function New-Connection {
|
||||||
|
param([string]$DbName)
|
||||||
|
|
||||||
|
$builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
|
||||||
|
$builder["Data Source"] = $ServerInstance
|
||||||
|
$builder["Initial Catalog"] = $DbName
|
||||||
|
$builder["Integrated Security"] = $true
|
||||||
|
$builder["TrustServerCertificate"] = $true
|
||||||
|
$builder["Connect Timeout"] = 15
|
||||||
|
return New-Object System.Data.SqlClient.SqlConnection($builder.ConnectionString)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-DataTable {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$Sql,
|
||||||
|
[hashtable]$Parameters = @{}
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection $DbName
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 300
|
||||||
|
|
||||||
|
foreach ($key in $Parameters.Keys) {
|
||||||
|
$param = $cmd.Parameters.Add("@$key", [System.Data.SqlDbType]::NVarChar, 4000)
|
||||||
|
$param.Value = [string]$Parameters[$key]
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = New-Object System.Data.DataTable
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
$table.Load($reader)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table
|
||||||
|
}
|
||||||
|
|
||||||
|
function Convert-ToCsvValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($null -eq $Value -or $Value -is [System.DBNull]) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Value -is [datetime]) {
|
||||||
|
$text = $Value.ToString("yyyy-MM-dd HH:mm:ss")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$text = [string]$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = $text.Replace('"', '""')
|
||||||
|
return '"' + $text + '"'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-QueryToCsv {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$Sql,
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$conn = New-Connection $DbName
|
||||||
|
$cmd = $conn.CreateCommand()
|
||||||
|
$cmd.CommandText = $Sql
|
||||||
|
$cmd.CommandTimeout = 0
|
||||||
|
|
||||||
|
$writer = New-Object System.IO.StreamWriter($Path, $false, [System.Text.Encoding]::UTF8)
|
||||||
|
$rowCount = 0
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn.Open()
|
||||||
|
$reader = $cmd.ExecuteReader()
|
||||||
|
|
||||||
|
$headers = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetName($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($headers -join ";"))
|
||||||
|
|
||||||
|
while ($reader.Read()) {
|
||||||
|
$values = for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
||||||
|
Convert-ToCsvValue $reader.GetValue($i)
|
||||||
|
}
|
||||||
|
$writer.WriteLine(($values -join ";"))
|
||||||
|
$rowCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$writer.Dispose()
|
||||||
|
$conn.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rowCount
|
||||||
|
}
|
||||||
|
|
||||||
|
function Quote-NamePart {
|
||||||
|
param([string]$Name)
|
||||||
|
|
||||||
|
return "[" + $Name.Replace("]", "]]") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Split-SqlObjectName {
|
||||||
|
param([string]$Name)
|
||||||
|
|
||||||
|
$parts = $Name.Split(".", 2)
|
||||||
|
if ($parts.Count -eq 1) {
|
||||||
|
return [pscustomobject]@{ SchemaName = "dbo"; ObjectName = $parts[0] }
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pscustomobject]@{ SchemaName = $parts[0].Trim("[", "]"); ObjectName = $parts[1].Trim("[", "]") }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-UserDatabases {
|
||||||
|
$sql = @"
|
||||||
|
SELECT name
|
||||||
|
FROM sys.databases
|
||||||
|
WHERE state_desc = 'ONLINE'
|
||||||
|
AND HAS_DBACCESS(name) = 1
|
||||||
|
$(if ($IncludeSystemDatabases) { "" } else { "AND database_id > 4" })
|
||||||
|
ORDER BY name;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable "master" $sql | ForEach-Object { $_.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-CandidateObjects {
|
||||||
|
param([string]$DbName)
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
WITH object_columns AS (
|
||||||
|
SELECT
|
||||||
|
s.name AS SchemaName,
|
||||||
|
o.name AS ObjectName,
|
||||||
|
o.type_desc AS ObjectType,
|
||||||
|
c.name AS ColumnName,
|
||||||
|
t.name AS TypeName,
|
||||||
|
c.max_length,
|
||||||
|
c.precision,
|
||||||
|
c.scale
|
||||||
|
FROM sys.objects o
|
||||||
|
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
||||||
|
JOIN sys.columns c ON c.object_id = o.object_id
|
||||||
|
JOIN sys.types t ON t.user_type_id = c.user_type_id
|
||||||
|
WHERE o.type IN ('U', 'V')
|
||||||
|
AND o.is_ms_shipped = 0
|
||||||
|
),
|
||||||
|
scored AS (
|
||||||
|
SELECT
|
||||||
|
SchemaName,
|
||||||
|
ObjectName,
|
||||||
|
ObjectType,
|
||||||
|
SUM(CASE WHEN LOWER(ObjectName) LIKE '%fact%' OR LOWER(ObjectName) LIKE '%invoice%' OR LOWER(ObjectName) LIKE '%venta%' OR LOWER(ObjectName) LIKE '%sales%' OR LOWER(ObjectName) LIKE '%albar%' OR LOWER(ObjectName) LIKE '%pedido%' THEN 5 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%fecha%' OR LOWER(ColumnName) LIKE '%date%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%cliente%' OR LOWER(ColumnName) LIKE '%customer%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%articulo%' OR LOWER(ColumnName) LIKE '%item%' OR LOWER(ColumnName) LIKE '%producto%' THEN 2 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%importe%' OR LOWER(ColumnName) LIKE '%neto%' OR LOWER(ColumnName) LIKE '%total%' OR LOWER(ColumnName) LIKE '%amount%' THEN 3 ELSE 0 END) +
|
||||||
|
SUM(CASE WHEN LOWER(ColumnName) LIKE '%cantidad%' OR LOWER(ColumnName) LIKE '%quantity%' OR LOWER(ColumnName) LIKE '%unidades%' THEN 2 ELSE 0 END) AS Score,
|
||||||
|
COUNT(*) AS ColumnCount,
|
||||||
|
STRING_AGG(CONVERT(nvarchar(max), ColumnName), ', ') WITHIN GROUP (ORDER BY ColumnName) AS Columns
|
||||||
|
FROM object_columns
|
||||||
|
GROUP BY SchemaName, ObjectName, ObjectType
|
||||||
|
)
|
||||||
|
SELECT TOP (80)
|
||||||
|
DB_NAME() AS DatabaseName,
|
||||||
|
SchemaName,
|
||||||
|
ObjectName,
|
||||||
|
ObjectType,
|
||||||
|
Score,
|
||||||
|
ColumnCount,
|
||||||
|
Columns
|
||||||
|
FROM scored
|
||||||
|
WHERE Score > 0
|
||||||
|
ORDER BY Score DESC, ObjectName;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable $DbName $sql
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-DateColumns {
|
||||||
|
param(
|
||||||
|
[string]$DbName,
|
||||||
|
[string]$SchemaName,
|
||||||
|
[string]$ObjectNameValue
|
||||||
|
)
|
||||||
|
|
||||||
|
$sql = @"
|
||||||
|
SELECT c.name AS ColumnName
|
||||||
|
FROM sys.objects o
|
||||||
|
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
||||||
|
JOIN sys.columns c ON c.object_id = o.object_id
|
||||||
|
JOIN sys.types t ON t.user_type_id = c.user_type_id
|
||||||
|
WHERE s.name = @schema
|
||||||
|
AND o.name = @object
|
||||||
|
AND (
|
||||||
|
t.name IN ('date', 'datetime', 'datetime2', 'smalldatetime')
|
||||||
|
OR LOWER(c.name) LIKE '%fecha%'
|
||||||
|
OR LOWER(c.name) LIKE '%date%'
|
||||||
|
)
|
||||||
|
ORDER BY
|
||||||
|
CASE
|
||||||
|
WHEN LOWER(c.name) LIKE '%fact%' OR LOWER(c.name) LIKE '%invoice%' THEN 0
|
||||||
|
WHEN LOWER(c.name) LIKE '%fecha%' OR LOWER(c.name) LIKE '%date%' THEN 1
|
||||||
|
ELSE 2
|
||||||
|
END,
|
||||||
|
c.column_id;
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-DataTable $DbName $sql @{ schema = $SchemaName; object = $ObjectNameValue } |
|
||||||
|
ForEach-Object { $_.ColumnName }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-SelectSql {
|
||||||
|
param(
|
||||||
|
[string]$SchemaName,
|
||||||
|
[string]$ObjectNameValue,
|
||||||
|
[string]$DateColumn,
|
||||||
|
[int]$TopRows
|
||||||
|
)
|
||||||
|
|
||||||
|
$topClause = if ($TopRows -gt 0) { "TOP ($TopRows)" } else { "" }
|
||||||
|
$qualified = "$(Quote-NamePart $SchemaName).$(Quote-NamePart $ObjectNameValue)"
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($DateColumn)) {
|
||||||
|
return "SELECT $topClause * FROM $qualified;"
|
||||||
|
}
|
||||||
|
|
||||||
|
$from = $FromDate.ToString("yyyy-MM-dd")
|
||||||
|
$to = $ToDate.ToString("yyyy-MM-dd")
|
||||||
|
$dateColumnSql = Quote-NamePart $DateColumn
|
||||||
|
|
||||||
|
return @"
|
||||||
|
SELECT $topClause *
|
||||||
|
FROM $qualified
|
||||||
|
WHERE TRY_CONVERT(date, $dateColumnSql) >= CONVERT(date, '$from')
|
||||||
|
AND TRY_CONVERT(date, $dateColumnSql) < CONVERT(date, '$to')
|
||||||
|
ORDER BY TRY_CONVERT(date, $dateColumnSql);
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
function Normalize-FileName {
|
||||||
|
param([string]$Value)
|
||||||
|
|
||||||
|
return ($Value -replace '[\\/:*?"<>|]', '_')
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$runDirectory = Join-Path $OutputDirectory "Sage_SQL_CSV_Export_$timestamp"
|
||||||
|
New-Item -ItemType Directory -Path $runDirectory -Force | Out-Null
|
||||||
|
|
||||||
|
$databases = if ([string]::IsNullOrWhiteSpace($Database)) {
|
||||||
|
@(Get-UserDatabases)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@($Database)
|
||||||
|
}
|
||||||
|
|
||||||
|
$summary = New-Object System.Collections.Generic.List[object]
|
||||||
|
$allCandidates = New-Object System.Collections.Generic.List[object]
|
||||||
|
|
||||||
|
foreach ($db in $databases) {
|
||||||
|
Write-Host "Scanning database: $db"
|
||||||
|
try {
|
||||||
|
$candidates = @(Get-CandidateObjects $db)
|
||||||
|
foreach ($candidate in $candidates) {
|
||||||
|
$allCandidates.Add($candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = ""
|
||||||
|
Action = "Discovery failed"
|
||||||
|
Rows = 0
|
||||||
|
File = ""
|
||||||
|
Error = $_.Exception.Message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$candidatePath = Join-Path $runDirectory "candidate_objects.csv"
|
||||||
|
if ($allCandidates.Count -gt 0) {
|
||||||
|
$allCandidates | Export-Csv -LiteralPath $candidatePath -NoTypeInformation -Encoding UTF8 -Delimiter ";"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $DiscoverOnly) {
|
||||||
|
$objectsToExport = New-Object System.Collections.Generic.List[object]
|
||||||
|
|
||||||
|
foreach ($name in $ObjectName) {
|
||||||
|
if ([string]::IsNullOrWhiteSpace($name)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Database)) {
|
||||||
|
throw "When -ObjectName is used, pass -Database as well."
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = Split-SqlObjectName $name
|
||||||
|
$objectsToExport.Add([pscustomobject]@{
|
||||||
|
DatabaseName = $Database
|
||||||
|
SchemaName = $parsed.SchemaName
|
||||||
|
ObjectName = $parsed.ObjectName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ExportCandidates) {
|
||||||
|
foreach ($candidate in ($allCandidates | Sort-Object DatabaseName, @{Expression="Score"; Descending=$true} | Select-Object -First 25)) {
|
||||||
|
$objectsToExport.Add([pscustomobject]@{
|
||||||
|
DatabaseName = $candidate.DatabaseName
|
||||||
|
SchemaName = $candidate.SchemaName
|
||||||
|
ObjectName = $candidate.ObjectName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($object in $objectsToExport) {
|
||||||
|
$db = $object.DatabaseName
|
||||||
|
$schema = $object.SchemaName
|
||||||
|
$objectNameValue = $object.ObjectName
|
||||||
|
|
||||||
|
try {
|
||||||
|
$dateColumn = @(Get-DateColumns $db $schema $objectNameValue | Select-Object -First 1)[0]
|
||||||
|
$limit = if ($MaxRowsPerObject -gt 0) { $MaxRowsPerObject } elseif ($ObjectName.Count -gt 0) { 0 } else { $SampleRows }
|
||||||
|
$sql = Build-SelectSql $schema $objectNameValue $dateColumn $limit
|
||||||
|
$fileName = Normalize-FileName "$db.$schema.$objectNameValue.csv"
|
||||||
|
$path = Join-Path $runDirectory $fileName
|
||||||
|
Write-Host "Exporting $db.$schema.$objectNameValue -> $path"
|
||||||
|
$rows = Export-QueryToCsv $db $sql $path
|
||||||
|
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = "$schema.$objectNameValue"
|
||||||
|
Action = "Exported"
|
||||||
|
Rows = $rows
|
||||||
|
File = $path
|
||||||
|
DateColumn = $dateColumn
|
||||||
|
Error = ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$summary.Add([pscustomobject]@{
|
||||||
|
Database = $db
|
||||||
|
Object = "$schema.$objectNameValue"
|
||||||
|
Action = "Export failed"
|
||||||
|
Rows = 0
|
||||||
|
File = ""
|
||||||
|
DateColumn = ""
|
||||||
|
Error = $_.Exception.Message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$summaryPath = Join-Path $runDirectory "export_summary.csv"
|
||||||
|
$summary | Export-Csv -LiteralPath $summaryPath -NoTypeInformation -Encoding UTF8 -Delimiter ";"
|
||||||
|
|
||||||
|
$readmePath = Join-Path $runDirectory "README.txt"
|
||||||
|
@"
|
||||||
|
Sage SQL CSV export
|
||||||
|
===================
|
||||||
|
|
||||||
|
Server instance: $ServerInstance
|
||||||
|
Database filter: $(if ($Database) { $Database } else { "(all accessible user databases)" })
|
||||||
|
From date: $($FromDate.ToString("yyyy-MM-dd"))
|
||||||
|
To date: $($ToDate.ToString("yyyy-MM-dd"))
|
||||||
|
|
||||||
|
Files:
|
||||||
|
- candidate_objects.csv: SQL tables/views that look relevant for sales/invoices.
|
||||||
|
- export_summary.csv: export status and row counts.
|
||||||
|
- *.csv: exported samples or selected full exports.
|
||||||
|
|
||||||
|
Recommended workflow:
|
||||||
|
1. Run discovery first:
|
||||||
|
.\Export-SageSqlCsv.ps1 -DiscoverOnly
|
||||||
|
2. Send candidate_objects.csv to Trafag/IT for selection.
|
||||||
|
3. Export selected objects:
|
||||||
|
.\Export-SageSqlCsv.ps1 -Database "DATABASE_NAME" -ObjectName "schema.table_or_view"
|
||||||
|
4. If the selected object is very large, add:
|
||||||
|
-FromDate "2025-01-01" -ToDate "2026-01-01" -MaxRowsPerObject 100000
|
||||||
|
|
||||||
|
The script only reads data. It does not change SQL Server or Sage.
|
||||||
|
"@ | Set-Content -LiteralPath $readmePath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Created folder:"
|
||||||
|
Write-Host " $runDirectory"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Main files:"
|
||||||
|
Write-Host " $candidatePath"
|
||||||
|
Write-Host " $summaryPath"
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
param(
|
||||||
|
[string[]]$SqlInstance = @(),
|
||||||
|
[string]$OutputDirectory = (Join-Path $env:USERPROFILE "Desktop"),
|
||||||
|
[switch]$ScanProgramFiles
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Continue"
|
||||||
|
|
||||||
|
function Add-Section {
|
||||||
|
param([string]$Title)
|
||||||
|
|
||||||
|
$script:reportLines += ""
|
||||||
|
$script:reportLines += "============================================================"
|
||||||
|
$script:reportLines += $Title
|
||||||
|
$script:reportLines += "============================================================"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-Line {
|
||||||
|
param([string]$Text = "")
|
||||||
|
|
||||||
|
$script:reportLines += $Text
|
||||||
|
}
|
||||||
|
|
||||||
|
function Read-RegistryValues {
|
||||||
|
param([string]$Path)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Test-Path $Path) {
|
||||||
|
return Get-ItemProperty -Path $Path -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Add-Line "Registry read failed: $Path :: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SageUninstallEntries {
|
||||||
|
$paths = @(
|
||||||
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
|
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($path in $paths) {
|
||||||
|
Get-ItemProperty -Path $path -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object {
|
||||||
|
$_.DisplayName -and (
|
||||||
|
$_.DisplayName -match "Sage" -or
|
||||||
|
$_.Publisher -match "Sage"
|
||||||
|
)
|
||||||
|
} |
|
||||||
|
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate, InstallLocation, UninstallString, PSPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SageFileVersions {
|
||||||
|
$roots = @(
|
||||||
|
$env:ProgramFiles,
|
||||||
|
${env:ProgramFiles(x86)},
|
||||||
|
$env:ProgramData
|
||||||
|
) | Where-Object { $_ -and (Test-Path $_) }
|
||||||
|
|
||||||
|
foreach ($root in $roots) {
|
||||||
|
Get-ChildItem -LiteralPath $root -Directory -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.Name -match "Sage" } |
|
||||||
|
ForEach-Object {
|
||||||
|
Get-ChildItem -LiteralPath $_.FullName -Recurse -File -Include *.exe,*.dll -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.VersionInfo.ProductName -match "Sage" -or $_.VersionInfo.CompanyName -match "Sage" -or $_.Name -match "Sage" } |
|
||||||
|
Select-Object FullName,
|
||||||
|
@{Name="FileVersion"; Expression={$_.VersionInfo.FileVersion}},
|
||||||
|
@{Name="ProductVersion"; Expression={$_.VersionInfo.ProductVersion}},
|
||||||
|
@{Name="ProductName"; Expression={$_.VersionInfo.ProductName}},
|
||||||
|
@{Name="CompanyName"; Expression={$_.VersionInfo.CompanyName}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SqlInstancesFromRegistry {
|
||||||
|
$instanceRoots = @(
|
||||||
|
"HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\Instance Names\SQL"
|
||||||
|
)
|
||||||
|
|
||||||
|
$instances = New-Object System.Collections.Generic.List[object]
|
||||||
|
|
||||||
|
foreach ($root in $instanceRoots) {
|
||||||
|
$values = Read-RegistryValues $root
|
||||||
|
if (-not $values) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$values.PSObject.Properties |
|
||||||
|
Where-Object { $_.Name -notlike "PS*" } |
|
||||||
|
ForEach-Object {
|
||||||
|
$instanceName = $_.Name
|
||||||
|
$instanceId = [string]$_.Value
|
||||||
|
$setupPaths = @(
|
||||||
|
"HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$instanceId\Setup",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\$instanceId\Setup"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($setupPath in $setupPaths) {
|
||||||
|
$setup = Read-RegistryValues $setupPath
|
||||||
|
if ($setup) {
|
||||||
|
$instances.Add([pscustomobject]@{
|
||||||
|
InstanceName = $instanceName
|
||||||
|
InstanceId = $instanceId
|
||||||
|
Edition = $setup.Edition
|
||||||
|
Version = $setup.Version
|
||||||
|
PatchLevel = $setup.PatchLevel
|
||||||
|
ProductCode = $setup.ProductCode
|
||||||
|
SQLPath = $setup.SQLPath
|
||||||
|
SetupPath = $setupPath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $instances
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SqlServices {
|
||||||
|
Get-CimInstance Win32_Service -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.Name -like "MSSQL*" -or $_.Name -like "SQLAgent*" -or $_.DisplayName -like "*SQL Server*" } |
|
||||||
|
Select-Object Name, DisplayName, State, StartMode, PathName
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-Sqlcmd {
|
||||||
|
$cmd = Get-Command sqlcmd.exe -ErrorAction SilentlyContinue
|
||||||
|
if ($cmd) {
|
||||||
|
return $cmd.Source
|
||||||
|
}
|
||||||
|
|
||||||
|
$candidates = @(
|
||||||
|
"$env:ProgramFiles\Microsoft SQL Server\Client SDK\ODBC\*\Tools\Binn\sqlcmd.exe",
|
||||||
|
"${env:ProgramFiles(x86)}\Microsoft SQL Server\Client SDK\ODBC\*\Tools\Binn\sqlcmd.exe",
|
||||||
|
"$env:ProgramFiles\Microsoft SQL Server\*\Tools\Binn\sqlcmd.exe",
|
||||||
|
"${env:ProgramFiles(x86)}\Microsoft SQL Server\*\Tools\Binn\sqlcmd.exe"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($candidate in $candidates) {
|
||||||
|
$match = Get-ChildItem -Path $candidate -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($match) {
|
||||||
|
return $match.FullName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-SqlVersionQuery {
|
||||||
|
param(
|
||||||
|
[string]$SqlcmdPath,
|
||||||
|
[string]$Instance
|
||||||
|
)
|
||||||
|
|
||||||
|
$query = @"
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
SELECT
|
||||||
|
@@VERSION AS FullVersion,
|
||||||
|
SERVERPROPERTY('ProductVersion') AS ProductVersion,
|
||||||
|
SERVERPROPERTY('ProductLevel') AS ProductLevel,
|
||||||
|
SERVERPROPERTY('Edition') AS Edition,
|
||||||
|
SERVERPROPERTY('EngineEdition') AS EngineEdition,
|
||||||
|
SERVERPROPERTY('MachineName') AS MachineName,
|
||||||
|
SERVERPROPERTY('ServerName') AS ServerName,
|
||||||
|
SERVERPROPERTY('InstanceName') AS InstanceName,
|
||||||
|
SERVERPROPERTY('Collation') AS Collation;
|
||||||
|
"@
|
||||||
|
|
||||||
|
$tempQuery = Join-Path $env:TEMP ("sql_version_query_{0}.sql" -f ([guid]::NewGuid().ToString("N")))
|
||||||
|
Set-Content -LiteralPath $tempQuery -Value $query -Encoding UTF8
|
||||||
|
|
||||||
|
try {
|
||||||
|
$output = & $SqlcmdPath -S $Instance -E -i $tempQuery -W -s "|" -b 2>&1
|
||||||
|
[pscustomobject]@{
|
||||||
|
Instance = $Instance
|
||||||
|
Success = $LASTEXITCODE -eq 0
|
||||||
|
Output = ($output -join [Environment]::NewLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
[pscustomobject]@{
|
||||||
|
Instance = $Instance
|
||||||
|
Success = $false
|
||||||
|
Output = $_.Exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Remove-Item -LiteralPath $tempQuery -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
|
||||||
|
|
||||||
|
$reportPath = Join-Path $OutputDirectory "Sage_SQL_Environment_$timestamp.txt"
|
||||||
|
$jsonPath = Join-Path $OutputDirectory "Sage_SQL_Environment_$timestamp.json"
|
||||||
|
$reportLines = New-Object System.Collections.Generic.List[string]
|
||||||
|
|
||||||
|
$computer = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue
|
||||||
|
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
|
||||||
|
$sageEntries = @(Get-SageUninstallEntries)
|
||||||
|
$sqlRegistryInstances = @(Get-SqlInstancesFromRegistry)
|
||||||
|
$sqlServices = @(Get-SqlServices)
|
||||||
|
$sageFileVersions = @()
|
||||||
|
|
||||||
|
if ($ScanProgramFiles) {
|
||||||
|
$sageFileVersions = @(Get-SageFileVersions)
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlcmdPath = Resolve-Sqlcmd
|
||||||
|
$queryInstances = New-Object System.Collections.Generic.List[string]
|
||||||
|
|
||||||
|
foreach ($instance in $SqlInstance) {
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($instance)) {
|
||||||
|
$queryInstances.Add($instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($queryInstances.Count -eq 0) {
|
||||||
|
$machineName = $env:COMPUTERNAME
|
||||||
|
foreach ($instance in $sqlRegistryInstances) {
|
||||||
|
if ($instance.InstanceName -eq "MSSQLSERVER") {
|
||||||
|
$queryInstances.Add("localhost")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$queryInstances.Add("localhost\$($instance.InstanceName)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryInstances = @($queryInstances | Select-Object -Unique)
|
||||||
|
$sqlQueryResults = @()
|
||||||
|
if ($sqlcmdPath -and $queryInstances.Count -gt 0) {
|
||||||
|
foreach ($instance in $queryInstances) {
|
||||||
|
$sqlQueryResults += Invoke-SqlVersionQuery -SqlcmdPath $sqlcmdPath -Instance $instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Section "Capture metadata"
|
||||||
|
Add-Line "Timestamp: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"
|
||||||
|
Add-Line "Computer: $env:COMPUTERNAME"
|
||||||
|
Add-Line "User: $env:USERDOMAIN\$env:USERNAME"
|
||||||
|
Add-Line "Output text: $reportPath"
|
||||||
|
Add-Line "Output json: $jsonPath"
|
||||||
|
|
||||||
|
Add-Section "Windows / machine"
|
||||||
|
Add-Line "Manufacturer: $($computer.Manufacturer)"
|
||||||
|
Add-Line "Model: $($computer.Model)"
|
||||||
|
Add-Line "OS: $($os.Caption)"
|
||||||
|
Add-Line "OS Version: $($os.Version)"
|
||||||
|
Add-Line "OS Build: $($os.BuildNumber)"
|
||||||
|
Add-Line "Install date: $($os.InstallDate)"
|
||||||
|
|
||||||
|
Add-Section "Sage entries from installed programs"
|
||||||
|
if ($sageEntries.Count -eq 0) {
|
||||||
|
Add-Line "No Sage uninstall entries found."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sageEntries | Format-List | Out-String | ForEach-Object { Add-Line $_.TrimEnd() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Section "Sage file versions"
|
||||||
|
if (-not $ScanProgramFiles) {
|
||||||
|
Add-Line "Skipped. Re-run with -ScanProgramFiles for file version scan."
|
||||||
|
}
|
||||||
|
elseif ($sageFileVersions.Count -eq 0) {
|
||||||
|
Add-Line "No Sage file versions found under Program Files / ProgramData."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sageFileVersions | Sort-Object ProductName, ProductVersion, FullName | Format-Table -AutoSize | Out-String | ForEach-Object { Add-Line $_.TrimEnd() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Section "SQL Server instances from registry"
|
||||||
|
if ($sqlRegistryInstances.Count -eq 0) {
|
||||||
|
Add-Line "No SQL Server registry instances found."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sqlRegistryInstances | Format-List | Out-String | ForEach-Object { Add-Line $_.TrimEnd() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Section "SQL Server services"
|
||||||
|
if ($sqlServices.Count -eq 0) {
|
||||||
|
Add-Line "No SQL Server services found."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sqlServices | Format-Table -AutoSize | Out-String | ForEach-Object { Add-Line $_.TrimEnd() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Section "SQL Server live query"
|
||||||
|
Add-Line "sqlcmd path: $(if ($sqlcmdPath) { $sqlcmdPath } else { "not found" })"
|
||||||
|
if (-not $sqlcmdPath) {
|
||||||
|
Add-Line "Cannot query SQL Server live because sqlcmd.exe was not found."
|
||||||
|
}
|
||||||
|
elseif ($queryInstances.Count -eq 0) {
|
||||||
|
Add-Line "No SQL instances to query. Pass -SqlInstance server\instance if needed."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach ($result in $sqlQueryResults) {
|
||||||
|
Add-Line ""
|
||||||
|
Add-Line "Instance: $($result.Instance)"
|
||||||
|
Add-Line "Success: $($result.Success)"
|
||||||
|
Add-Line $result.Output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [pscustomobject]@{
|
||||||
|
CapturedAt = (Get-Date).ToString("o")
|
||||||
|
ComputerName = $env:COMPUTERNAME
|
||||||
|
UserName = "$env:USERDOMAIN\$env:USERNAME"
|
||||||
|
Windows = [pscustomobject]@{
|
||||||
|
Caption = $os.Caption
|
||||||
|
Version = $os.Version
|
||||||
|
BuildNumber = $os.BuildNumber
|
||||||
|
InstallDate = $os.InstallDate
|
||||||
|
}
|
||||||
|
SageUninstallEntries = $sageEntries
|
||||||
|
SageFileVersions = $sageFileVersions
|
||||||
|
SqlRegistryInstances = $sqlRegistryInstances
|
||||||
|
SqlServices = $sqlServices
|
||||||
|
SqlcmdPath = $sqlcmdPath
|
||||||
|
SqlQueryResults = $sqlQueryResults
|
||||||
|
}
|
||||||
|
|
||||||
|
$reportLines | Set-Content -LiteralPath $reportPath -Encoding UTF8
|
||||||
|
$data | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host "Created:"
|
||||||
|
Write-Host " $reportPath"
|
||||||
|
Write-Host " $jsonPath"
|
||||||
Reference in New Issue
Block a user