Spaces:
Sleeping
Sleeping
Upload hts_validator.py
Browse files- hts_validator.py +74 -8
hts_validator.py
CHANGED
|
@@ -25,11 +25,13 @@ SCENARIO_SUMMARIES = {
|
|
| 25 |
"S7": "Dual Steel+Aluminum HTS - matches keyword, apply corresponding 232, no 99030125",
|
| 26 |
"S7a": "Dual Steel+Aluminum HTS + BOTH keywords - flag for manual review",
|
| 27 |
"S8": "Dual Steel+Aluminum HTS + NO keywords - flag for manual review",
|
| 28 |
-
"S9": "Copper keyword but NOT copper HTS -
|
| 29 |
"S11": "Dual Aluminum+Copper HTS + copper keyword - apply 99030133 + copper tariffs, no 99030125",
|
| 30 |
"S12": "Dual Aluminum+Copper HTS + aluminum keyword - apply 99030133 + aluminum 232, no 99030125",
|
| 31 |
"S13": "Zinc keyword - should ONLY apply 99030125, no 232 tariffs allowed",
|
| 32 |
"S14": "Plastics keyword + metal HTS - override, should ONLY apply 99030125",
|
|
|
|
|
|
|
| 33 |
"COPPER_OK": "Copper HTS + copper keyword - verify copper tariffs applied",
|
| 34 |
"NONE": "No applicable scenario - entry does not match any validation rules",
|
| 35 |
}
|
|
@@ -411,8 +413,35 @@ class HTSValidator:
|
|
| 411 |
|
| 412 |
# Priority 3: Single list scenarios
|
| 413 |
|
| 414 |
-
# Steel scenarios (S1)
|
| 415 |
if in_steel and not in_aluminum and not in_copper:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
if has_metal_kw:
|
| 417 |
# S1: Steel HTS + metal keyword + 232 tariff
|
| 418 |
if has_steel_232:
|
|
@@ -483,8 +512,35 @@ class HTSValidator:
|
|
| 483 |
issue="; ".join(issues) if issues else "Correct - metal keyword with non-steel HTS"
|
| 484 |
)
|
| 485 |
|
| 486 |
-
# Aluminum scenarios (S4)
|
| 487 |
if in_aluminum and not in_steel and not in_copper:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 488 |
if has_aluminum_kw:
|
| 489 |
# S4: Aluminum HTS + aluminum keyword + 232 tariff
|
| 490 |
if has_aluminum_232:
|
|
@@ -582,7 +638,17 @@ class HTSValidator:
|
|
| 582 |
|
| 583 |
# S9: Copper keyword but NOT in copper list
|
| 584 |
if has_copper_kw and not in_copper:
|
| 585 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 586 |
return ValidationResult(
|
| 587 |
entry_number=entry_number,
|
| 588 |
description=description,
|
|
@@ -591,10 +657,10 @@ class HTSValidator:
|
|
| 591 |
scenario_id="S9",
|
| 592 |
scenario_summary=SCENARIO_SUMMARIES["S9"],
|
| 593 |
status=status,
|
| 594 |
-
expected_hts=
|
| 595 |
-
missing_hts=[],
|
| 596 |
-
unexpected_hts=[],
|
| 597 |
-
issue="
|
| 598 |
)
|
| 599 |
|
| 600 |
# No applicable scenario
|
|
|
|
| 25 |
"S7": "Dual Steel+Aluminum HTS - matches keyword, apply corresponding 232, no 99030125",
|
| 26 |
"S7a": "Dual Steel+Aluminum HTS + BOTH keywords - flag for manual review",
|
| 27 |
"S8": "Dual Steel+Aluminum HTS + NO keywords - flag for manual review",
|
| 28 |
+
"S9": "Copper keyword but NOT copper HTS - should apply 99030125, no 232 tariffs",
|
| 29 |
"S11": "Dual Aluminum+Copper HTS + copper keyword - apply 99030133 + copper tariffs, no 99030125",
|
| 30 |
"S12": "Dual Aluminum+Copper HTS + aluminum keyword - apply 99030133 + aluminum 232, no 99030125",
|
| 31 |
"S13": "Zinc keyword - should ONLY apply 99030125, no 232 tariffs allowed",
|
| 32 |
"S14": "Plastics keyword + metal HTS - override, should ONLY apply 99030125",
|
| 33 |
+
"S15": "Steel HTS + aluminum keyword - should apply 99030125, no 99030133 or 232 tariffs",
|
| 34 |
+
"S16": "Aluminum HTS + steel keyword - should apply 99030125, no 99030133 or 232 tariffs",
|
| 35 |
"COPPER_OK": "Copper HTS + copper keyword - verify copper tariffs applied",
|
| 36 |
"NONE": "No applicable scenario - entry does not match any validation rules",
|
| 37 |
}
|
|
|
|
| 413 |
|
| 414 |
# Priority 3: Single list scenarios
|
| 415 |
|
| 416 |
+
# Steel scenarios (S1, S15)
|
| 417 |
if in_steel and not in_aluminum and not in_copper:
|
| 418 |
+
# S15: Steel HTS + aluminum keyword - mismatch, should apply 99030125
|
| 419 |
+
if has_aluminum_kw and not has_metal_kw:
|
| 420 |
+
expected = [MISMATCH_CODE]
|
| 421 |
+
issues = []
|
| 422 |
+
|
| 423 |
+
if not has_mismatch:
|
| 424 |
+
issues.append("Missing 99030125")
|
| 425 |
+
if has_steel_232 or has_aluminum_232:
|
| 426 |
+
issues.append("Should NOT have 232 tariffs - description says aluminum but HTS is steel")
|
| 427 |
+
if has_301:
|
| 428 |
+
issues.append("Should NOT have 99030133 - description says aluminum but HTS is steel")
|
| 429 |
+
|
| 430 |
+
status = "PASS" if not issues else "FAIL"
|
| 431 |
+
return ValidationResult(
|
| 432 |
+
entry_number=entry_number,
|
| 433 |
+
description=description,
|
| 434 |
+
primary_hts=primary_hts,
|
| 435 |
+
additional_hts=additional_hts,
|
| 436 |
+
scenario_id="S15",
|
| 437 |
+
scenario_summary=SCENARIO_SUMMARIES["S15"],
|
| 438 |
+
status=status,
|
| 439 |
+
expected_hts=expected,
|
| 440 |
+
missing_hts=[MISMATCH_CODE] if not has_mismatch else [],
|
| 441 |
+
unexpected_hts=self._get_unexpected_232(additional_set) + ([GENERAL_301_CODE] if has_301 else []),
|
| 442 |
+
issue="; ".join(issues) if issues else "Correct - steel HTS with aluminum keyword, has 99030125"
|
| 443 |
+
)
|
| 444 |
+
|
| 445 |
if has_metal_kw:
|
| 446 |
# S1: Steel HTS + metal keyword + 232 tariff
|
| 447 |
if has_steel_232:
|
|
|
|
| 512 |
issue="; ".join(issues) if issues else "Correct - metal keyword with non-steel HTS"
|
| 513 |
)
|
| 514 |
|
| 515 |
+
# Aluminum scenarios (S4, S16)
|
| 516 |
if in_aluminum and not in_steel and not in_copper:
|
| 517 |
+
# S16: Aluminum HTS + steel keyword - mismatch, should apply 99030125
|
| 518 |
+
if has_metal_kw and not has_aluminum_kw:
|
| 519 |
+
expected = [MISMATCH_CODE]
|
| 520 |
+
issues = []
|
| 521 |
+
|
| 522 |
+
if not has_mismatch:
|
| 523 |
+
issues.append("Missing 99030125")
|
| 524 |
+
if has_steel_232 or has_aluminum_232:
|
| 525 |
+
issues.append("Should NOT have 232 tariffs - description says steel but HTS is aluminum")
|
| 526 |
+
if has_301:
|
| 527 |
+
issues.append("Should NOT have 99030133 - description says steel but HTS is aluminum")
|
| 528 |
+
|
| 529 |
+
status = "PASS" if not issues else "FAIL"
|
| 530 |
+
return ValidationResult(
|
| 531 |
+
entry_number=entry_number,
|
| 532 |
+
description=description,
|
| 533 |
+
primary_hts=primary_hts,
|
| 534 |
+
additional_hts=additional_hts,
|
| 535 |
+
scenario_id="S16",
|
| 536 |
+
scenario_summary=SCENARIO_SUMMARIES["S16"],
|
| 537 |
+
status=status,
|
| 538 |
+
expected_hts=expected,
|
| 539 |
+
missing_hts=[MISMATCH_CODE] if not has_mismatch else [],
|
| 540 |
+
unexpected_hts=self._get_unexpected_232(additional_set) + ([GENERAL_301_CODE] if has_301 else []),
|
| 541 |
+
issue="; ".join(issues) if issues else "Correct - aluminum HTS with steel keyword, has 99030125"
|
| 542 |
+
)
|
| 543 |
+
|
| 544 |
if has_aluminum_kw:
|
| 545 |
# S4: Aluminum HTS + aluminum keyword + 232 tariff
|
| 546 |
if has_aluminum_232:
|
|
|
|
| 638 |
|
| 639 |
# S9: Copper keyword but NOT in copper list
|
| 640 |
if has_copper_kw and not in_copper:
|
| 641 |
+
expected = [MISMATCH_CODE]
|
| 642 |
+
issues = []
|
| 643 |
+
|
| 644 |
+
if not has_mismatch:
|
| 645 |
+
issues.append("Missing 99030125")
|
| 646 |
+
if has_steel_232 or has_aluminum_232 or has_copper_tariff:
|
| 647 |
+
issues.append("Should NOT have 232/copper tariffs - HTS not in copper list")
|
| 648 |
+
if has_301:
|
| 649 |
+
issues.append("Should NOT have 99030133 - HTS not in copper list")
|
| 650 |
+
|
| 651 |
+
status = "PASS" if not issues else "FAIL"
|
| 652 |
return ValidationResult(
|
| 653 |
entry_number=entry_number,
|
| 654 |
description=description,
|
|
|
|
| 657 |
scenario_id="S9",
|
| 658 |
scenario_summary=SCENARIO_SUMMARIES["S9"],
|
| 659 |
status=status,
|
| 660 |
+
expected_hts=expected,
|
| 661 |
+
missing_hts=[MISMATCH_CODE] if not has_mismatch else [],
|
| 662 |
+
unexpected_hts=self._get_unexpected_232(additional_set) + ([GENERAL_301_CODE] if has_301 else []),
|
| 663 |
+
issue="; ".join(issues) if issues else "Correct - copper keyword with non-copper HTS"
|
| 664 |
)
|
| 665 |
|
| 666 |
# No applicable scenario
|