Skip to content

Commit 26f240b

Browse files
committed
Fixes all tests pass
1 parent c5e82c9 commit 26f240b

File tree

2 files changed

+66
-54
lines changed

2 files changed

+66
-54
lines changed

src/odoo_data_flow/import_threaded.py

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ def _process_external_id_fields(
565565
return converted_vals, external_id_fields
566566

567567

568-
def _handle_create_error(
568+
def _handle_create_error( # noqa: C901
569569
i: int,
570570
create_error: Exception,
571571
line: list[Any],
@@ -978,36 +978,10 @@ def _execute_load_batch( # noqa: C901
978978
res = model.load(load_header, load_lines, context=context)
979979

980980
if res.get("messages"):
981-
error = res["messages"][0].get("message", "Batch load failed.")
981+
res["messages"][0].get("message", "Batch load failed.")
982982
# Don't raise immediately, log and continue to capture in fail file
983-
log.debug(
984-
f"Expected records: {len(load_lines)}, "
985-
f"Created records: {len(created_ids)}"
986-
)
987-
988-
# Always log detailed information about record creation
989-
if len(created_ids) != len(load_lines):
990-
log.warning(
991-
f"Record creation mismatch: Expected {len(load_lines)} records, "
992-
f"but only {len(created_ids)} were created"
993-
)
994-
if len(created_ids) == 0:
995-
log.error(
996-
f"No records were created in this batch of {len(load_lines)}. "
997-
f"This may indicate silent failures in the Odoo load operation. "
998-
f"Check Odoo server logs for validation errors."
999-
)
1000-
# Log the actual data being sent for debugging
1001-
if load_lines:
1002-
log.debug("First few lines being sent:")
1003-
for i, line in enumerate(load_lines[:3]):
1004-
log.debug(f" Line {i}: {dict(zip(load_header, line))}")
1005-
else:
1006-
log.warning(
1007-
f"Partial record creation: {len(created_ids)}/{len(load_lines)} "
1008-
f"records were created. Some records may have failed validation."
1009-
)
1010-
# Check for any Odoo server errors in the response that should halt processing
983+
# Check for any Odoo server errors in the response that should halt
984+
# processing
1011985
if res.get("messages"):
1012986
for message in res["messages"]:
1013987
msg_type = message.get("type", "unknown")
@@ -1023,7 +997,8 @@ def _execute_load_batch( # noqa: C901
1023997

1024998
created_ids = res.get("ids", [])
1025999
log.debug(
1026-
f"Expected records: {len(load_lines)}, Created records: {len(created_ids)}"
1000+
f"Expected records: {len(load_lines)}, "
1001+
f"Created records: {len(created_ids)}"
10271002
)
10281003

10291004
# Always log detailed information about record creation
@@ -1035,8 +1010,8 @@ def _execute_load_batch( # noqa: C901
10351010
if len(created_ids) == 0:
10361011
log.error(
10371012
f"No records were created in this batch of {len(load_lines)}. "
1038-
f"This may indicate silent failures in the Odoo load operation. "
1039-
f"Check Odoo server logs for validation errors."
1013+
f"This may indicate silent failures in the Odoo load operation."
1014+
f" Check Odoo server logs for validation errors."
10401015
)
10411016
# Log the actual data being sent for debugging
10421017
if load_lines:
@@ -1045,14 +1020,16 @@ def _execute_load_batch( # noqa: C901
10451020
log.debug(f" Line {i}: {dict(zip(load_header, line))}")
10461021
else:
10471022
log.warning(
1048-
f"Partial record creation: {len(created_ids)}/{len(load_lines)} "
1049-
f"records were created. Some records may have failed validation."
1023+
f"Partial record creation: {len(created_ids)}/{len(load_lines)}"
1024+
f"records were created. "
1025+
f"Some records may have failed validation."
10501026
)
10511027

10521028
# Instead of raising an exception, capture failures for the fail file
10531029
# But still create what records we can
10541030
if res.get("messages"):
1055-
# Extract error information and add to failed_lines to be written to fail file
1031+
# Extract error information and add to failed_lines to be written
1032+
# to fail file
10561033
error_msg = res["messages"][0].get("message", "Batch load failed.")
10571034
log.error(f"Capturing load failure for fail file: {error_msg}")
10581035
# We'll add the failed lines to aggregated_failed_lines at the end
@@ -1094,13 +1071,19 @@ def _execute_load_batch( # noqa: C901
10941071
failed_line = [*list(line), f"Load failed: {error_msg}"]
10951072
aggregated_failed_lines.append(failed_line)
10961073

1097-
# Create a new dictionary containing only the items with integer values
1074+
# Create a new dictionary containing only the items with
1075+
# integer values
10981076
filtered_id_map = {
10991077
key: value
11001078
for key, value in id_map.items()
11011079
if isinstance(value, int)
11021080
}
1103-
aggregated_id_map.update(filtered_id_map)
1081+
# Always update the aggregated map with successful records
1082+
# Create a new dictionary containing only the items with integer values
1083+
filtered_id_map = {
1084+
key: value for key, value in id_map.items() if isinstance(value, int)
1085+
}
1086+
aggregated_id_map.update(filtered_id_map)
11041087
lines_to_process = lines_to_process[chunk_size:]
11051088

11061089
# Reset serialization retry counter on successful processing

src/odoo_data_flow/lib/preflight.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
systemic errors early (e.g., missing languages, incorrect configuration).
55
"""
66

7+
import csv
78
import tempfile
89
from typing import Any, Callable, Optional, Union, cast
910

@@ -396,28 +397,52 @@ def _validate_header(
396397
return True
397398

398399

399-
def _auto_correct_field_types( # noqa: C901
400+
@register_check
401+
def type_correction_check( # noqa: C901
402+
preflight_mode: "PreflightMode",
403+
model: str,
400404
filename: str,
401-
header: list[str],
402-
odoo_fields: dict[str, Any],
403-
separator: str,
404-
encoding: str,
405-
) -> Optional[str]:
406-
"""Auto-correct field type mismatches using Polars casting.
405+
config: Union[str, dict[str, Any]],
406+
import_plan: dict[str, Any],
407+
**kwargs: Any,
408+
) -> bool:
409+
"""Auto-correct field type mismatches using Polars casting and store in import_plan.
407410
408411
Args:
412+
preflight_mode: The preflight mode (NORMAL or FAIL_MODE)
413+
model: The target Odoo model name
409414
filename: Path to the source CSV file
410-
header: List of CSV header columns
411-
odoo_fields: Dictionary of Odoo model fields and their metadata
412-
separator: CSV field separator
413-
encoding: File encoding
415+
config: Odoo connection configuration
416+
import_plan: Dictionary to store import-related data including corrected file
417+
**kwargs: Additional parameters like separator, encoding, etc.
414418
415419
Returns:
416-
Path to corrected CSV file, or None if no corrections needed/error occurred
420+
True if the check passed (regardless of whether corrections were needed)
417421
"""
418422
try:
419423
log.info("Running type validation and auto-correction...")
420424

425+
separator = kwargs.get("separator", ";")
426+
encoding = kwargs.get("encoding", "utf-8")
427+
428+
# Read header to validate
429+
with open(filename, encoding=encoding, newline="") as f:
430+
reader = csv.reader(f, delimiter=separator)
431+
header = next(reader)
432+
433+
if not header:
434+
log.warning("Source file has no header, skipping type correction check")
435+
return True
436+
437+
# Get Odoo model fields information
438+
odoo_fields = _get_odoo_fields(config, model)
439+
if not odoo_fields:
440+
log.warning(
441+
"Could not retrieve Odoo field information, "
442+
"skipping type correction check"
443+
)
444+
return True
445+
421446
# Read the CSV file with Polars
422447
df = pl.read_csv(
423448
filename, separator=separator, encoding=encoding, truncate_ragged_lines=True
@@ -456,10 +481,10 @@ def _auto_correct_field_types( # noqa: C901
456481
if corrections_needed:
457482
break
458483

459-
# If no corrections needed, return None to use original file
484+
# If no corrections needed, don't create a corrected file
460485
if not corrections_needed:
461486
log.info("No type corrections needed - using original CSV file")
462-
return None
487+
return True
463488

464489
# Apply corrections using Polars casting
465490
log.info("Applying type corrections using Polars casting...")
@@ -512,15 +537,19 @@ def _auto_correct_field_types( # noqa: C901
512537
corrected_file.name,
513538
)
514539

515-
return corrected_file.name
540+
# Store the corrected file path in the import plan so the importer can use it
541+
import_plan["_corrected_file"] = corrected_file.name
542+
543+
return True
516544

517545
except Exception as e:
518546
log.warning(
519547
"Type validation and auto-correction failed, proceeding with original "
520548
"file: %s",
521549
e,
522550
)
523-
return None
551+
# Still return True to allow import to continue with original file
552+
return True
524553

525554

526555
def _plan_deferrals_and_strategies(

0 commit comments

Comments
 (0)