from data.diff_result import FieldResult from decimal import Decimal, InvalidOperation, ROUND_DOWN DEFAULT_TOLERANCE = 0.01 def compare_field( name: str, cobol_val: str, java_val: str, field_type: str = "decimal", tolerance: float = DEFAULT_TOLERANCE ) -> FieldResult: result = FieldResult(field_name=name, cobol_value=cobol_val, java_value=java_val) if field_type in ("decimal", "numeric"): return _compare_numeric(result, cobol_val, java_val, tolerance) if field_type == "date": return _compare_date(result, cobol_val, java_val) if field_type in ("string", "alpha"): return _compare_string(result, cobol_val, java_val) return _compare_generic(result, cobol_val, java_val) def _compare_numeric(fr: FieldResult, c: str, j: str, tol: float) -> FieldResult: c_val = _parse_number(c) j_val = _parse_number(j) if c_val is None and j_val is None: fr.status = "PASS" return fr if c_val is None: fr.status = "NOT_SET" fr.suggestion = "cobol_parse_error" return fr if j_val is None: fr.status = "MISMATCH" fr.suggestion = "java_missing_init: null/None where COBOL has value" return fr if c_val == j_val: fr.status = "PASS" return fr diff = abs(c_val - j_val) if isinstance(c_val, Decimal): diff = abs(float(c_val - j_val)) if diff <= tol: fr.status = "TOLERATED" fr.tolerance_applied = tol else: fr.status = "MISMATCH" return fr def _compare_date(fr: FieldResult, c: str, j: str) -> FieldResult: c_norm = _normalize_date(c) j_norm = _normalize_date(j) fr.status = "PASS" if c_norm == j_norm else "MISMATCH" return fr def _compare_string(fr: FieldResult, c: str, j: str) -> FieldResult: c_clean = c.strip() if c else "" j_clean = j.strip() if j else "" fr.status = "PASS" if c_clean == j_clean else "MISMATCH" return fr def _compare_generic(fr: FieldResult, c: str, j: str) -> FieldResult: fr.status = "PASS" if c == j else "MISMATCH" return fr def _parse_number(val: str): if val is None or val == "None": return None s = str(val).strip() if s in ("", "\x00", "\x00\x00\x00\x00\x00"): return Decimal("0") s = s.replace("\x00", "") try: return Decimal(s) except InvalidOperation: return None def _normalize_date(val: str, default: str = "1970-01-01") -> str: if not val: return default s = val.strip() if len(s) == 8 and s.isdigit(): return f"{s[0:4]}-{s[4:6]}-{s[6:8]}" if len(s) == 10 and s[4] == '-': return s return s