feat(import:v1): allow to source previously mapped data by prefixing it with "__" on transformations

This commit is contained in:
Herculino Trotta
2025-02-08 16:38:36 -03:00
parent 00e83cf6a2
commit d9e8be7efb

View File

@@ -131,7 +131,10 @@ class ImportService:
@staticmethod @staticmethod
def _transform_value( def _transform_value(
value: str, mapping: version_1.ColumnMapping, row: Dict[str, str] = None value: str,
mapping: version_1.ColumnMapping,
row: Dict[str, str] = None,
mapped_data: Dict[str, Any] = None,
) -> Any: ) -> Any:
transformed = value transformed = value
@@ -142,8 +145,12 @@ class ImportService:
for field in transform.fields: for field in transform.fields:
if field in row: if field in row:
values_to_hash.append(str(row[field])) values_to_hash.append(str(row[field]))
elif (
# Create hash from concatenated values field.startswith("__")
and mapped_data
and field[2:] in mapped_data
):
values_to_hash.append(str(mapped_data[field[2:]]))
if values_to_hash: if values_to_hash:
concatenated = "|".join(values_to_hash) concatenated = "|".join(values_to_hash)
transformed = hashlib.sha256(concatenated.encode()).hexdigest() transformed = hashlib.sha256(concatenated.encode()).hexdigest()
@@ -175,6 +182,12 @@ class ImportService:
for field in transform.fields: for field in transform.fields:
if field in row: if field in row:
values_to_merge.append(str(row[field])) values_to_merge.append(str(row[field]))
elif (
field.startswith("__")
and mapped_data
and field[2:] in mapped_data
):
values_to_merge.append(str(mapped_data[field[2:]]))
transformed = transform.separator.join(values_to_merge) transformed = transform.separator.join(values_to_merge)
elif transform.type == "split": elif transform.type == "split":
parts = transformed.split(transform.separator) parts = transformed.split(transform.separator)
@@ -484,35 +497,30 @@ class ImportService:
def _map_row(self, row: Dict[str, str]) -> Dict[str, Any]: def _map_row(self, row: Dict[str, str]) -> Dict[str, Any]:
mapped_data = {} mapped_data = {}
for field, mapping in self.mapping.items(): for field, mapping in self.mapping.items():
value = None value = None
if isinstance(mapping.source, str): if isinstance(mapping.source, str):
value = row.get(mapping.source, None) if mapping.source in row:
value = row[mapping.source]
if not value and mapping.source.startswith("__"): elif (
value = mapped_data.get(mapping.source[2:], None) mapping.source.startswith("__")
and mapping.source[2:] in mapped_data
):
value = mapped_data[mapping.source[2:]]
elif isinstance(mapping.source, list): elif isinstance(mapping.source, list):
for source in mapping.source: for source in mapping.source:
value = row.get(source, None) if source in row:
value = row[source]
if not value and source.startswith("__"): break
value = mapped_data.get(source[2:], None) elif source.startswith("__") and source[2:] in mapped_data:
value = mapped_data[source[2:]]
if value:
break break
else:
# If source is None, use None as the initial value
value = None
# Use default_value if value is None if value is None:
if not value:
value = mapping.default value = mapping.default
# Apply transformations
if mapping.transformations: if mapping.transformations:
value = self._transform_value(value, mapping, row) value = self._transform_value(value, mapping, row, mapped_data)
value = self._coerce_type(value, mapping) value = self._coerce_type(value, mapping)
@@ -520,12 +528,10 @@ class ImportService:
raise ValueError(f"Required field {field} is missing") raise ValueError(f"Required field {field} is missing")
if value is not None: if value is not None:
# Remove the prefix from the target field
target = mapping.target target = mapping.target
if self.settings.importing == "transactions": if self.settings.importing == "transactions":
mapped_data[target] = value mapped_data[target] = value
else: else:
# Remove the model prefix (e.g., "account_" from "account_name")
field_name = target.split("_", 1)[1] field_name = target.split("_", 1)[1]
mapped_data[field_name] = value mapped_data[field_name] = value