mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-15 10:24:57 +03:00
feat(stub-db-create): scan Form.xml for register column names
Parse form attributes of RegisterRecordSet types and extract column names from DataPath references. Generate matching Dimension/Attribute stubs in register metadata so form field bindings survive the build. Limitation: column categories (Dimension vs Resource vs Attribute) cannot be determined from EPF sources alone — only names are preserved. Also add /Out log for UpdateDBCfg errors in both PS1 and PY. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,6 +92,73 @@ foreach ($f in $xmlFiles) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- 1b. Scan Form.xml for register record set columns ---
|
||||
# When a form attribute has type like InformationRegisterRecordSet.XXX,
|
||||
# the form references columns via DataPath "AttrName.ColumnName".
|
||||
# We need to create matching dimensions/resources/attributes in stub registers.
|
||||
|
||||
$registerColumns = @{} # "RegisterType.RegisterName" -> @{ col1=$true; col2=$true }
|
||||
|
||||
# Standard attributes that don't need explicit declaration
|
||||
$stdRegCols = @("LineNumber","Period","Recorder","Active","RecordType")
|
||||
|
||||
foreach ($f in $xmlFiles) {
|
||||
$content = [System.IO.File]::ReadAllText($f.FullName, [System.Text.Encoding]::UTF8)
|
||||
|
||||
# Find form attributes with register record set types using XmlDocument for reliability
|
||||
$regAttrMap = @{} # formAttrName -> "RegisterType.RegisterName"
|
||||
|
||||
# Only process Form.xml files (they contain <Attributes> with <Attribute> children)
|
||||
if ($f.Name -eq "Form.xml" -and $content -match '<Attributes>') {
|
||||
try {
|
||||
$xml = New-Object System.Xml.XmlDocument
|
||||
$xml.LoadXml($content)
|
||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
|
||||
$nsMgr.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
||||
$nsMgr.AddNamespace("f", "http://v8.1c.ru/8.3/xcf/logform")
|
||||
$attrNodes = $xml.SelectNodes("//f:Attributes/f:Attribute", $nsMgr)
|
||||
foreach ($attrNode in $attrNodes) {
|
||||
$attrName = $attrNode.GetAttribute("name")
|
||||
$typeNodes = $attrNode.SelectNodes("f:Type/v8:Type", $nsMgr)
|
||||
foreach ($tn in $typeNodes) {
|
||||
$typeText = $tn.InnerText
|
||||
$rsMatch = [regex]::Match($typeText, '^(?:cfg:|d\dp1:)(InformationRegisterRecordSet|AccumulationRegisterRecordSet|AccountingRegisterRecordSet|CalculationRegisterRecordSet)\.(.+)$')
|
||||
if ($rsMatch.Success) {
|
||||
$rsPrefix = $rsMatch.Groups[1].Value
|
||||
$regName = $rsMatch.Groups[2].Value
|
||||
$regType = switch ($rsPrefix) {
|
||||
"InformationRegisterRecordSet" { "InformationRegister" }
|
||||
"AccumulationRegisterRecordSet" { "AccumulationRegister" }
|
||||
"AccountingRegisterRecordSet" { "AccountingRegister" }
|
||||
"CalculationRegisterRecordSet" { "CalculationRegister" }
|
||||
}
|
||||
$regKey = "$regType.$regName"
|
||||
$regAttrMap[$attrName] = $regKey
|
||||
if (-not $registerColumns.ContainsKey($regKey)) {
|
||||
$registerColumns[$regKey] = @{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
# XML parse failed, skip
|
||||
}
|
||||
}
|
||||
|
||||
# Now find DataPath references like "AttrName.ColumnName"
|
||||
if ($regAttrMap.Count -gt 0) {
|
||||
$dpPattern = '<DataPath>([A-Za-z\u0400-\u04FF\d_]+)\.([A-Za-z\u0400-\u04FF\d_]+)</DataPath>'
|
||||
foreach ($m in [regex]::Matches($content, $dpPattern)) {
|
||||
$attrName = $m.Groups[1].Value
|
||||
$colName = $m.Groups[2].Value
|
||||
if ($regAttrMap.ContainsKey($attrName) -and $colName -notin $stdRegCols) {
|
||||
$regKey = $regAttrMap[$attrName]
|
||||
$registerColumns[$regKey][$colName] = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hasRefTypes = $typeMap.Count -gt 0
|
||||
|
||||
# --- 2. Determine TempBasePath ---
|
||||
@@ -977,13 +1044,23 @@ $stdAttrs <Characteristics/>
|
||||
if ($metaType -eq "DefinedType") {
|
||||
$childObjLine = ""
|
||||
} elseif ($metaType -eq "InformationRegister") {
|
||||
$dimUuid = [guid]::NewGuid().ToString()
|
||||
$childObjLine = @"
|
||||
|
||||
<ChildObjects>
|
||||
<Dimension uuid="$dimUuid">
|
||||
# Check if we have actual column names from form scanning
|
||||
$regKey = "InformationRegister.$objName"
|
||||
$cols = if ($registerColumns.ContainsKey($regKey) -and $registerColumns[$regKey].Count -gt 0) {
|
||||
$registerColumns[$regKey].Keys
|
||||
} else {
|
||||
@("Заглушка")
|
||||
}
|
||||
# First column as Dimension (for MainFilter), rest as Attributes (no index pressure)
|
||||
$dimXmlParts = @()
|
||||
$isFirst = $true
|
||||
foreach ($colName in $cols) {
|
||||
$elemUuid = [guid]::NewGuid().ToString()
|
||||
if ($isFirst) {
|
||||
$dimXmlParts += @"
|
||||
<Dimension uuid="$elemUuid">
|
||||
<Properties>
|
||||
<Name>Заглушка</Name>
|
||||
<Name>$colName</Name>
|
||||
<Synonym/>
|
||||
<Comment/>
|
||||
<Type>
|
||||
@@ -1022,14 +1099,63 @@ $stdAttrs <Characteristics/>
|
||||
<DataHistory>Use</DataHistory>
|
||||
</Properties>
|
||||
</Dimension>
|
||||
</ChildObjects>
|
||||
"@
|
||||
$isFirst = $false
|
||||
} else {
|
||||
$dimXmlParts += @"
|
||||
<Attribute uuid="$elemUuid">
|
||||
<Properties>
|
||||
<Name>$colName</Name>
|
||||
<Synonym/>
|
||||
<Comment/>
|
||||
<Type>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</Type>
|
||||
<PasswordMode>false</PasswordMode>
|
||||
<Format/>
|
||||
<EditFormat/>
|
||||
<ToolTip/>
|
||||
<MarkNegatives>false</MarkNegatives>
|
||||
<Mask/>
|
||||
<MultiLine>false</MultiLine>
|
||||
<ExtendedEdit>false</ExtendedEdit>
|
||||
<MinValue xsi:nil="true"/>
|
||||
<MaxValue xsi:nil="true"/>
|
||||
<FillFromFillingValue>false</FillFromFillingValue>
|
||||
<FillValue xsi:nil="true"/>
|
||||
<FillChecking>DontCheck</FillChecking>
|
||||
<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>
|
||||
<ChoiceParameterLinks/>
|
||||
<ChoiceParameters/>
|
||||
<QuickChoice>Auto</QuickChoice>
|
||||
<CreateOnInput>Auto</CreateOnInput>
|
||||
<ChoiceForm/>
|
||||
<LinkByType/>
|
||||
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
<FullTextSearch>Use</FullTextSearch>
|
||||
</Properties>
|
||||
</Attribute>
|
||||
"@
|
||||
}
|
||||
}
|
||||
$childObjLine = "`r`n`t`t<ChildObjects>`r`n$($dimXmlParts -join "`r`n")`r`n`t`t</ChildObjects>"
|
||||
} elseif ($metaType -in @("AccumulationRegister","AccountingRegister","CalculationRegister")) {
|
||||
$resUuid = [guid]::NewGuid().ToString()
|
||||
$childObjLine = @"
|
||||
|
||||
<ChildObjects>
|
||||
<Resource uuid="$resUuid">
|
||||
# Check if we have actual column names from form scanning
|
||||
$regKey = "$metaType.$objName"
|
||||
$cols = if ($registerColumns.ContainsKey($regKey) -and $registerColumns[$regKey].Count -gt 0) {
|
||||
$registerColumns[$regKey].Keys
|
||||
} else {
|
||||
@()
|
||||
}
|
||||
$childParts = @()
|
||||
# AccumulationRegister requires at least one Resource
|
||||
$stubResUuid = [guid]::NewGuid().ToString()
|
||||
$childParts += @"
|
||||
<Resource uuid="$stubResUuid">
|
||||
<Properties>
|
||||
<Name>Заглушка</Name>
|
||||
<Synonym/>
|
||||
@@ -1064,8 +1190,48 @@ $stdAttrs <Characteristics/>
|
||||
<FullTextSearch>Use</FullTextSearch>
|
||||
</Properties>
|
||||
</Resource>
|
||||
</ChildObjects>
|
||||
"@
|
||||
# Add all form-referenced columns as Dimensions (short strings to avoid index overflow)
|
||||
foreach ($colName in $cols) {
|
||||
$dimUuid = [guid]::NewGuid().ToString()
|
||||
$childParts += @"
|
||||
<Dimension uuid="$dimUuid">
|
||||
<Properties>
|
||||
<Name>$colName</Name>
|
||||
<Synonym/>
|
||||
<Comment/>
|
||||
<Type>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</Type>
|
||||
<PasswordMode>false</PasswordMode>
|
||||
<Format/>
|
||||
<EditFormat/>
|
||||
<ToolTip/>
|
||||
<MarkNegatives>false</MarkNegatives>
|
||||
<Mask/>
|
||||
<MultiLine>false</MultiLine>
|
||||
<ExtendedEdit>false</ExtendedEdit>
|
||||
<MinValue xsi:nil="true"/>
|
||||
<MaxValue xsi:nil="true"/>
|
||||
<FillChecking>DontCheck</FillChecking>
|
||||
<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>
|
||||
<ChoiceParameterLinks/>
|
||||
<ChoiceParameters/>
|
||||
<QuickChoice>Auto</QuickChoice>
|
||||
<CreateOnInput>Auto</CreateOnInput>
|
||||
<ChoiceForm/>
|
||||
<LinkByType/>
|
||||
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
<FullTextSearch>Use</FullTextSearch>
|
||||
</Properties>
|
||||
</Dimension>
|
||||
"@
|
||||
}
|
||||
$childObjLine = "`r`n`t`t<ChildObjects>`r`n$($childParts -join "`r`n")`r`n`t`t</ChildObjects>"
|
||||
}
|
||||
$objXml = @"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -1108,9 +1274,11 @@ if ($hasRefTypes) {
|
||||
|
||||
# UpdateDBCfg
|
||||
Write-Host "Updating database configuration..."
|
||||
$updateArgs = "DESIGNER /F`"$TempBasePath`" /UpdateDBCfg /DisableStartupDialogs"
|
||||
$updateLog = Join-Path $env:TEMP "stub_update_log.txt"
|
||||
$updateArgs = "DESIGNER /F`"$TempBasePath`" /UpdateDBCfg /Out `"$updateLog`" /DisableStartupDialogs"
|
||||
$proc = Start-Process -FilePath $V8Path -ArgumentList $updateArgs -NoNewWindow -Wait -PassThru
|
||||
if ($proc.ExitCode -ne 0) {
|
||||
if (Test-Path $updateLog) { Get-Content $updateLog -Raw -ErrorAction SilentlyContinue | Write-Host }
|
||||
Write-Error "Failed to update DB config (code: $($proc.ExitCode))"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -89,6 +89,68 @@ def scan_ref_types(source_dir):
|
||||
return type_map
|
||||
|
||||
|
||||
def scan_register_columns(source_dir):
|
||||
"""Scan Form.xml for register record set columns referenced via DataPath.
|
||||
Returns {"RegisterType.RegisterName": {"col1": True, "col2": True}}."""
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
register_columns = {}
|
||||
std_cols = {'LineNumber', 'Period', 'Recorder', 'Active', 'RecordType'}
|
||||
rs_type_map = {
|
||||
'InformationRegisterRecordSet': 'InformationRegister',
|
||||
'AccumulationRegisterRecordSet': 'AccumulationRegister',
|
||||
'AccountingRegisterRecordSet': 'AccountingRegister',
|
||||
'CalculationRegisterRecordSet': 'CalculationRegister',
|
||||
}
|
||||
rs_pattern = re.compile(
|
||||
r'^(?:cfg:|d\dp1:)(InformationRegisterRecordSet|AccumulationRegisterRecordSet'
|
||||
r'|AccountingRegisterRecordSet|CalculationRegisterRecordSet)\.(.+)$'
|
||||
)
|
||||
dp_pattern = re.compile(r'<DataPath>([A-Za-z\u0400-\u04FF\d_]+)\.([A-Za-z\u0400-\u04FF\d_]+)</DataPath>')
|
||||
|
||||
ns = {
|
||||
'v8': 'http://v8.1c.ru/8.1/data/core',
|
||||
'f': 'http://v8.1c.ru/8.3/xcf/logform',
|
||||
}
|
||||
|
||||
for dirpath, _, filenames in os.walk(source_dir):
|
||||
for fn in filenames:
|
||||
if fn != 'Form.xml':
|
||||
continue
|
||||
fp = os.path.join(dirpath, fn)
|
||||
try:
|
||||
with open(fp, 'r', encoding='utf-8-sig') as fh:
|
||||
content = fh.read()
|
||||
except Exception:
|
||||
continue
|
||||
if '<Attributes>' not in content:
|
||||
continue
|
||||
|
||||
# Parse form attributes to find register recordset types
|
||||
reg_attr_map = {} # formAttrName -> "RegisterType.RegisterName"
|
||||
try:
|
||||
root = ET.fromstring(content)
|
||||
for attr_node in root.iter('{http://v8.1c.ru/8.3/xcf/logform}Attribute'):
|
||||
attr_name = attr_node.get('name', '')
|
||||
for type_node in attr_node.iter('{http://v8.1c.ru/8.1/data/core}Type'):
|
||||
m = rs_pattern.match(type_node.text or '')
|
||||
if m:
|
||||
reg_type = rs_type_map[m.group(1)]
|
||||
reg_key = f"{reg_type}.{m.group(2)}"
|
||||
reg_attr_map[attr_name] = reg_key
|
||||
register_columns.setdefault(reg_key, {})
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Find DataPath references like "AttrName.ColumnName"
|
||||
for m in dp_pattern.finditer(content):
|
||||
attr_name, col_name = m.group(1), m.group(2)
|
||||
if attr_name in reg_attr_map and col_name not in std_cols:
|
||||
register_columns[reg_attr_map[attr_name]][col_name] = True
|
||||
|
||||
return register_columns
|
||||
|
||||
|
||||
NS = (
|
||||
'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" '
|
||||
'xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" '
|
||||
@@ -722,6 +784,7 @@ def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
type_map = scan_ref_types(args.SourceDir)
|
||||
register_columns = scan_register_columns(args.SourceDir)
|
||||
has_ref_types = len(type_map) > 0
|
||||
|
||||
temp_base = args.TempBasePath or os.path.join(tempfile.gettempdir(), f'epf_stub_db_{random.randint(0,999999)}')
|
||||
@@ -882,91 +945,77 @@ def main():
|
||||
if meta_type == 'DefinedType':
|
||||
child_obj_xml = ''
|
||||
elif meta_type == 'InformationRegister':
|
||||
dim_uuid = new_uuid()
|
||||
child_obj_xml = f"""
|
||||
\t\t<ChildObjects>
|
||||
\t\t\t<Dimension uuid="{dim_uuid}">
|
||||
reg_key = f'InformationRegister.{obj_name}'
|
||||
cols = list(register_columns.get(reg_key, {}).keys()) or ['\u0417\u0430\u0433\u043b\u0443\u0448\u043a\u0430']
|
||||
parts = []
|
||||
for i, col in enumerate(cols):
|
||||
u = new_uuid()
|
||||
if i == 0:
|
||||
parts.append(f"""\t\t\t<Dimension uuid="{u}">
|
||||
\t\t\t\t<Properties>
|
||||
\t\t\t\t\t<Name>\u0417\u0430\u0433\u043b\u0443\u0448\u043a\u0430</Name>
|
||||
\t\t\t\t\t<Synonym/>
|
||||
\t\t\t\t\t<Comment/>
|
||||
\t\t\t\t\t<Type>
|
||||
\t\t\t\t\t\t<v8:Type>xs:string</v8:Type>
|
||||
\t\t\t\t\t\t<v8:StringQualifiers>
|
||||
\t\t\t\t\t\t\t<v8:Length>10</v8:Length>
|
||||
\t\t\t\t\t\t\t<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
\t\t\t\t\t\t</v8:StringQualifiers>
|
||||
\t\t\t\t\t</Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode>
|
||||
\t\t\t\t\t<Format/>
|
||||
\t\t\t\t\t<EditFormat/>
|
||||
\t\t\t\t\t<ToolTip/>
|
||||
\t\t\t\t\t<MarkNegatives>false</MarkNegatives>
|
||||
\t\t\t\t\t<Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine>
|
||||
\t\t\t\t\t<ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<MaxValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<FillFromFillingValue>false</FillFromFillingValue>
|
||||
\t\t\t\t\t<FillValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>
|
||||
\t\t\t\t\t<ChoiceParameterLinks/>
|
||||
\t\t\t\t\t<ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice>
|
||||
\t\t\t\t\t<CreateOnInput>Auto</CreateOnInput>
|
||||
\t\t\t\t\t<ChoiceForm/>
|
||||
\t\t\t\t\t<LinkByType/>
|
||||
\t\t\t\t\t<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<Master>false</Master>
|
||||
\t\t\t\t\t<MainFilter>true</MainFilter>
|
||||
\t\t\t\t\t<DenyIncompleteValues>false</DenyIncompleteValues>
|
||||
\t\t\t\t\t<Indexing>DontIndex</Indexing>
|
||||
\t\t\t\t\t<FullTextSearch>Use</FullTextSearch>
|
||||
\t\t\t\t\t<DataHistory>Use</DataHistory>
|
||||
\t\t\t\t\t<Name>{col}</Name>
|
||||
\t\t\t\t\t<Synonym/><Comment/>
|
||||
\t\t\t\t\t<Type><v8:Type>xs:string</v8:Type><v8:StringQualifiers><v8:Length>10</v8:Length><v8:AllowedLength>Variable</v8:AllowedLength></v8:StringQualifiers></Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode><Format/><EditFormat/><ToolTip/><MarkNegatives>false</MarkNegatives><Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine><ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/><MaxValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<FillFromFillingValue>false</FillFromFillingValue><FillValue xsi:nil="true"/><FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems><ChoiceParameterLinks/><ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice><CreateOnInput>Auto</CreateOnInput><ChoiceForm/><LinkByType/><ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<Master>false</Master><MainFilter>true</MainFilter><DenyIncompleteValues>false</DenyIncompleteValues>
|
||||
\t\t\t\t\t<Indexing>DontIndex</Indexing><FullTextSearch>Use</FullTextSearch><DataHistory>Use</DataHistory>
|
||||
\t\t\t\t</Properties>
|
||||
\t\t\t</Dimension>
|
||||
\t\t</ChildObjects>"""
|
||||
\t\t\t</Dimension>""")
|
||||
else:
|
||||
parts.append(f"""\t\t\t<Attribute uuid="{u}">
|
||||
\t\t\t\t<Properties>
|
||||
\t\t\t\t\t<Name>{col}</Name>
|
||||
\t\t\t\t\t<Synonym/><Comment/>
|
||||
\t\t\t\t\t<Type><v8:Type>xs:string</v8:Type><v8:StringQualifiers><v8:Length>10</v8:Length><v8:AllowedLength>Variable</v8:AllowedLength></v8:StringQualifiers></Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode><Format/><EditFormat/><ToolTip/><MarkNegatives>false</MarkNegatives><Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine><ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/><MaxValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<FillFromFillingValue>false</FillFromFillingValue><FillValue xsi:nil="true"/><FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems><ChoiceParameterLinks/><ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice><CreateOnInput>Auto</CreateOnInput><ChoiceForm/><LinkByType/><ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<Indexing>DontIndex</Indexing><FullTextSearch>Use</FullTextSearch><DataHistory>Use</DataHistory>
|
||||
\t\t\t\t</Properties>
|
||||
\t\t\t</Attribute>""")
|
||||
child_obj_xml = '\n\t\t<ChildObjects>\n' + '\n'.join(parts) + '\n\t\t</ChildObjects>'
|
||||
elif meta_type in ('AccumulationRegister', 'AccountingRegister', 'CalculationRegister'):
|
||||
res_uuid = new_uuid()
|
||||
child_obj_xml = f"""
|
||||
\t\t<ChildObjects>
|
||||
\t\t\t<Resource uuid="{res_uuid}">
|
||||
reg_key = f'{meta_type}.{obj_name}'
|
||||
cols = list(register_columns.get(reg_key, {}).keys())
|
||||
parts = []
|
||||
# Required stub Resource
|
||||
parts.append(f"""\t\t\t<Resource uuid="{new_uuid()}">
|
||||
\t\t\t\t<Properties>
|
||||
\t\t\t\t\t<Name>\u0417\u0430\u0433\u043b\u0443\u0448\u043a\u0430</Name>
|
||||
\t\t\t\t\t<Synonym/>
|
||||
\t\t\t\t\t<Comment/>
|
||||
\t\t\t\t\t<Type>
|
||||
\t\t\t\t\t\t<v8:Type>xs:decimal</v8:Type>
|
||||
\t\t\t\t\t\t<v8:NumberQualifiers>
|
||||
\t\t\t\t\t\t\t<v8:Digits>15</v8:Digits>
|
||||
\t\t\t\t\t\t\t<v8:FractionDigits>2</v8:FractionDigits>
|
||||
\t\t\t\t\t\t\t<v8:AllowedSign>Any</v8:AllowedSign>
|
||||
\t\t\t\t\t\t</v8:NumberQualifiers>
|
||||
\t\t\t\t\t</Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode>
|
||||
\t\t\t\t\t<Format/>
|
||||
\t\t\t\t\t<EditFormat/>
|
||||
\t\t\t\t\t<ToolTip/>
|
||||
\t\t\t\t\t<MarkNegatives>false</MarkNegatives>
|
||||
\t\t\t\t\t<Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine>
|
||||
\t\t\t\t\t<ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<MaxValue xsi:nil="true"/>
|
||||
\t\t\t\t\t<FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>
|
||||
\t\t\t\t\t<ChoiceParameterLinks/>
|
||||
\t\t\t\t\t<ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice>
|
||||
\t\t\t\t\t<CreateOnInput>Auto</CreateOnInput>
|
||||
\t\t\t\t\t<ChoiceForm/>
|
||||
\t\t\t\t\t<LinkByType/>
|
||||
\t\t\t\t\t<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<Synonym/><Comment/>
|
||||
\t\t\t\t\t<Type><v8:Type>xs:decimal</v8:Type><v8:NumberQualifiers><v8:Digits>15</v8:Digits><v8:FractionDigits>2</v8:FractionDigits><v8:AllowedSign>Any</v8:AllowedSign></v8:NumberQualifiers></Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode><Format/><EditFormat/><ToolTip/><MarkNegatives>false</MarkNegatives><Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine><ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/><MaxValue xsi:nil="true"/><FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems><ChoiceParameterLinks/><ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice><CreateOnInput>Auto</CreateOnInput><ChoiceForm/><LinkByType/><ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<FullTextSearch>Use</FullTextSearch>
|
||||
\t\t\t\t</Properties>
|
||||
\t\t\t</Resource>
|
||||
\t\t</ChildObjects>"""
|
||||
\t\t\t</Resource>""")
|
||||
# Form-referenced columns as Dimensions
|
||||
for col in cols:
|
||||
parts.append(f"""\t\t\t<Dimension uuid="{new_uuid()}">
|
||||
\t\t\t\t<Properties>
|
||||
\t\t\t\t\t<Name>{col}</Name>
|
||||
\t\t\t\t\t<Synonym/><Comment/>
|
||||
\t\t\t\t\t<Type><v8:Type>xs:string</v8:Type><v8:StringQualifiers><v8:Length>10</v8:Length><v8:AllowedLength>Variable</v8:AllowedLength></v8:StringQualifiers></Type>
|
||||
\t\t\t\t\t<PasswordMode>false</PasswordMode><Format/><EditFormat/><ToolTip/><MarkNegatives>false</MarkNegatives><Mask/>
|
||||
\t\t\t\t\t<MultiLine>false</MultiLine><ExtendedEdit>false</ExtendedEdit>
|
||||
\t\t\t\t\t<MinValue xsi:nil="true"/><MaxValue xsi:nil="true"/><FillChecking>DontCheck</FillChecking>
|
||||
\t\t\t\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems><ChoiceParameterLinks/><ChoiceParameters/>
|
||||
\t\t\t\t\t<QuickChoice>Auto</QuickChoice><CreateOnInput>Auto</CreateOnInput><ChoiceForm/><LinkByType/><ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
\t\t\t\t\t<FullTextSearch>Use</FullTextSearch>
|
||||
\t\t\t\t</Properties>
|
||||
\t\t\t</Dimension>""")
|
||||
child_obj_xml = '\n\t\t<ChildObjects>\n' + '\n'.join(parts) + '\n\t\t</ChildObjects>'
|
||||
else:
|
||||
child_obj_xml = '\n\t\t<ChildObjects/>'
|
||||
|
||||
@@ -1007,11 +1056,18 @@ def main():
|
||||
|
||||
# UpdateDBCfg
|
||||
print('Updating database configuration...')
|
||||
update_log = os.path.join(tempfile.gettempdir(), 'stub_update_log.txt')
|
||||
result = subprocess.run(
|
||||
[args.V8Path, 'DESIGNER', f'/F{temp_base}', '/UpdateDBCfg', '/DisableStartupDialogs'],
|
||||
[args.V8Path, 'DESIGNER', f'/F{temp_base}', '/UpdateDBCfg', '/Out', update_log, '/DisableStartupDialogs'],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
if os.path.isfile(update_log):
|
||||
try:
|
||||
with open(update_log, 'r', encoding='utf-8-sig') as f:
|
||||
print(f.read())
|
||||
except Exception:
|
||||
pass
|
||||
print(f'Failed to update DB config (code: {result.returncode})', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user