Skip to content

Commit

Permalink
SW-6162 Fix issue with disappearing variable value references / injec…
Browse files Browse the repository at this point in the history
…tions when a document is updated to a new variable manifest version (#2612)

When a document template has a new variable manifest uploaded for it, section variable IDs may be updated, for example if the section name goes from "Project Details" to "The Project Details". When this occurs, a user may "upgrade" their document (which points at the old version of the variable manifest) to the new version. 

During this upgrade, for project values within each section, "update" and "delete" operations were created to determine the upgrade path for the user-entered data. Now that the non-section variables exist outside of the manifest, and any out-dated references to them are updated during their own upgrade, there is no longer a need to create the "delete" operations which were responsible for cleaning up variable references that no longer existed. 

This solves a bug that was deleting references to variables within section text that belonged to sections that were part of an upgraded variable manifest.
  • Loading branch information
nickgraz authored Nov 20, 2024
1 parent 0e6f4b2 commit 14e5401
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,53 +155,34 @@ class DocumentUpgradeCalculator(
private fun sectionOperations(variable: SectionVariable): List<ValueOperation> {
return if (variable.id in existingValues) {
// The section wasn't replaced, so existing text values are fine, as are existing
// references to variables that weren't replaced or removed; we just need to update or
// delete any references to old variables. We do this in reverse list position order
// since deleting will cause new value IDs to be generated for items with higher list
// positions (at which point our in-memory list of existing values wouldn't be usable).
val sectionValues =
existingValues[variable.id]!!
.filterIsInstance<ExistingSectionValue>()
.sortedByDescending { it.listPosition }

val updateOperations =
sectionValues.mapNotNull { sectionValue ->
if (sectionValue.value is SectionValueVariable) {
val sectionValueVariable = sectionValue.value
val usedVariableId = sectionValueVariable.usedVariableId
if (usedVariableId in replacementVariableIds) {
UpdateValueOperation(
ExistingSectionValue(
BaseVariableValueProperties(
sectionValue.id,
projectId,
sectionValue.listPosition,
variable.id,
sectionValue.citation),
SectionValueVariable(
replacementVariableIds[usedVariableId]!!,
sectionValueVariable.usageType,
sectionValueVariable.displayStyle)))
} else {
null
}
} else {
null
}
}

val deleteOperations =
sectionValues.mapNotNull { sectionValue ->
if (sectionValue.value is SectionValueVariable &&
sectionValue.value.usedVariableId !in newManifestVariables &&
sectionValue.value.usedVariableId !in replacementVariableIds) {
DeleteValueOperation(projectId, sectionValue.id)
} else {
null
}
// references to variables that weren't replaced or removed; we just need to update
// any references to old variables.
val sectionValues = existingValues[variable.id]!!.filterIsInstance<ExistingSectionValue>()

sectionValues.mapNotNull { sectionValue ->
if (sectionValue.value is SectionValueVariable) {
val sectionValueVariable = sectionValue.value
val usedVariableId = sectionValueVariable.usedVariableId
if (usedVariableId in replacementVariableIds) {
UpdateValueOperation(
ExistingSectionValue(
BaseVariableValueProperties(
sectionValue.id,
projectId,
sectionValue.listPosition,
variable.id,
sectionValue.citation),
SectionValueVariable(
replacementVariableIds[usedVariableId]!!,
sectionValueVariable.usageType,
sectionValueVariable.displayStyle)))
} else {
null
}

updateOperations + deleteOperations
} else {
null
}
}
} else {
val sectionValues =
previousVariableIds[variable.id]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.terraformation.backend.db.docprod.DocumentId
import com.terraformation.backend.db.docprod.VariableId
import com.terraformation.backend.db.docprod.VariableInjectionDisplayStyle
import com.terraformation.backend.db.docprod.VariableManifestId
import com.terraformation.backend.db.docprod.VariableTextType
import com.terraformation.backend.db.docprod.VariableType
import com.terraformation.backend.db.docprod.VariableUsageType
import com.terraformation.backend.db.docprod.VariableValueId
Expand Down Expand Up @@ -223,45 +224,62 @@ class DocumentUpgradeCalculatorTest : DatabaseTest(), RunsAsUser {
}

@Test
fun `updates variable references in sections to use new variable IDs`() {
val oldManifestId = insertVariableManifest()
val outdatedVariableId =
insertVariableManifestEntry(insertTextVariable(), manifestId = oldManifestId)
val unmodifiedVariableId =
insertVariableManifestEntry(insertNumberVariable(), manifestId = oldManifestId)
val obsoleteVariableId =
insertVariableManifestEntry(insertTextVariable(), manifestId = oldManifestId)
val sectionVariableId = insertVariableManifestEntry(insertSectionVariable())
val newManifestId = insertVariableManifest()
val updatedVariableId =
insertVariableManifestEntry(
insertTextVariable(
insertVariable(type = VariableType.Text, replacesVariableId = outdatedVariableId)),
manifestId = newManifestId)
insertVariableManifestEntry(unmodifiedVariableId, manifestId = newManifestId)
insertVariableManifestEntry(sectionVariableId, manifestId = newManifestId)
fun `updates section values to point to new section variables for the same stable ID`() {
// A few variables are uploaded to the system
val outdatedVariableId = insertTextVariable(textType = VariableTextType.SingleLine)
val unmodifiedVariableId = insertNumberVariable()

val documentId = insertDocument(variableManifestId = oldManifestId)
val outdatedValueId =
insertSectionValue(sectionVariableId, listPosition = 0, usedVariableId = outdatedVariableId)
val obsoleteValueId =
insertSectionValue(sectionVariableId, listPosition = 1, usedVariableId = obsoleteVariableId)
insertSectionValue(sectionVariableId, listPosition = 2, textValue = "some text")
insertSectionValue(sectionVariableId, listPosition = 3, usedVariableId = unmodifiedVariableId)
// A manifest is created for the document template with a section
val firstManifestId = insertVariableManifest()
val firstSectionVariableId = insertVariableManifestEntry(insertSectionVariable())

assertEquals(
// A project document is created for the manifest
insertProject()
val documentId = insertDocument(variableManifestId = firstManifestId)

// Some project values are added to the document section
insertSectionValue(
firstSectionVariableId,
listPosition = 0,
textValue = "We must consider the value of this variable: ")
insertSectionValue(
firstSectionVariableId, listPosition = 1, usedVariableId = unmodifiedVariableId)
insertSectionValue(
firstSectionVariableId, listPosition = 2, textValue = ", additionally, this variable: ")
val outdatedVariableValueId =
insertSectionValue(
firstSectionVariableId, listPosition = 3, usedVariableId = outdatedVariableId)

// The variable is updated to a new version in the all variables upload
val updatedVariableId =
insertTextVariable(
id = insertVariable(type = VariableType.Text, replacesVariableId = outdatedVariableId),
textType = VariableTextType.MultiLine)

// A new manifest for the document template is uploaded
val secondManifestId = insertVariableManifest()
insertVariableManifestEntry(variableId = firstSectionVariableId)

// The user upgrades their project document to the latest version of the document template's
// variable manifest
val actual = calculateOperations(secondManifestId, documentId)
val expected =
listOf(
UpdateValueOperation(
ExistingSectionValue(
BaseVariableValueProperties(
outdatedValueId, inserted.projectId, 0, sectionVariableId, null),
outdatedVariableValueId,
inserted.projectId,
3,
firstSectionVariableId,
null),
SectionValueVariable(
updatedVariableId,
VariableUsageType.Injection,
VariableInjectionDisplayStyle.Block))),
DeleteValueOperation(inserted.projectId, obsoleteValueId),
),
calculateOperations(newManifestId, documentId))
)

assertEquals(expected, actual)
}

@Test
Expand Down

0 comments on commit 14e5401

Please sign in to comment.