joycecast commited on
Commit
625d5ba
·
verified ·
1 Parent(s): 350560b

Upload 2 files

Browse files
Files changed (2) hide show
  1. README.md +112 -112
  2. hts_validator.py +28 -1
README.md CHANGED
@@ -1,112 +1,112 @@
1
- ---
2
- title: HTS Review Tool
3
- sdk: streamlit
4
- emoji: 👀
5
- colorFrom: blue
6
- colorTo: green
7
- ---
8
- # HTS Checker - Tariff Audit Tool
9
-
10
- A Streamlit application for auditing HTS (Harmonized Tariff Schedule) codes, validating primary HTS against additional tariffs and description keywords.
11
-
12
- ## Features
13
-
14
- - **Auto-validation**: Validation runs automatically when file is uploaded
15
- - **14+ Scenarios**: Validates Steel, Aluminum, Copper tariff classifications
16
- - **Unique Combinations View**: De-duplicates entries by HTS+Description for efficient review
17
- - **Interactive Filters**: Filter by HTS, description, status, scenario
18
- - **Bulk Export**: Add filtered results to cache and export to Excel
19
- - **HTS Reference**: View all Steel/Aluminum/Copper HTS lists with overlap analysis
20
- - **Editable Keywords**: Customize metal, aluminum, copper, zinc, plastics keyword lists
21
-
22
- ## Validation Scenarios
23
-
24
- | ID | Description |
25
- |----|-------------|
26
- | S1 | Steel HTS + 232 tariff applied - verify 99030133 present, no 99030125 |
27
- | S2 | Metal keyword but NOT steel HTS - should apply 99030125, no 232 tariffs |
28
- | S3 | Steel HTS but NO metal keyword - description mismatch, should apply 99030125 |
29
- | S4 | Aluminum HTS + 232 tariff applied - verify 99030133 present |
30
- | S5 | Aluminum keyword but NOT aluminum HTS - should apply 99030125, no 232 tariffs |
31
- | S6 | Aluminum HTS but NO aluminum keyword - description mismatch |
32
- | S7 | Dual Steel+Aluminum HTS - matches keyword, apply corresponding 232 |
33
- | S7a | Dual Steel+Aluminum HTS + BOTH keywords - flag for manual review |
34
- | S8 | Dual Steel+Aluminum HTS + NO keywords - should apply 99030125 |
35
- | S9 | Copper keyword but NOT copper HTS - potential misclassification |
36
- | S10 | Copper HTS but NO copper keyword - description mismatch |
37
- | S11 | Dual Aluminum+Copper HTS + copper keyword - apply 99030133 + copper tariffs |
38
- | S12 | Dual Aluminum+Copper HTS + aluminum keyword - apply 99030133 + aluminum 232 |
39
- | S13 | Zinc keyword - should ONLY apply 99030125, no 232 tariffs allowed |
40
- | S14 | Plastics keyword + metal HTS - override, should ONLY apply 99030125 |
41
-
42
- ## Key Additional HTS Codes
43
-
44
- | Code | Type |
45
- |------|------|
46
- | 99038190, 99038191 | Steel Section 232 |
47
- | 99038507, 99038508 | Aluminum Section 232 |
48
- | 99037801, 99037802 | Copper tariffs |
49
- | 99030133 | General 301 (accompanies 232) |
50
- | 99030125 | Mismatch/Override code |
51
-
52
- ## Input File Format
53
-
54
- Upload Excel file with these columns:
55
- - **Column E (Description)**: Product description for keyword matching
56
- - **Column F (Tariff)**: 10-digit Primary HTS code
57
- - **Columns I-N (Primary 1-6)**: Additional HTS codes applied
58
-
59
- ## Default Keywords
60
-
61
- **Metal**: steel, stainless steel, carbon steel, iron, metal
62
-
63
- **Aluminum**: aluminum, aluminium
64
-
65
- **Copper**: copper
66
-
67
- **Zinc**: zinc
68
-
69
- **Plastics**: plastic, abs, pu, pvc, polyester, nylon
70
-
71
- ## Tabs
72
-
73
- 1. **Upload & Filter**: Upload Excel file, apply initial filters
74
- 2. **Validation Results**: View all results with interactive filters, add to export cache
75
- 3. **Unique Combinations**: De-duplicated view by HTS+Description with occurrence count
76
- 4. **Keyword Management**: Edit keyword lists used for validation
77
- 5. **Export Selection**: Manage export cache and download Excel reports
78
- 6. **HTS Reference**: View Steel/Aluminum/Copper HTS lists and overlaps
79
-
80
- ## Local Development
81
-
82
- ```bash
83
- cd HTS_Checker
84
- pip install -r requirements.txt
85
- streamlit run app.py
86
- ```
87
-
88
- ## Hugging Face Deployment
89
-
90
- 1. Create a new Space on [Hugging Face](https://huggingface.co/spaces)
91
- 2. Select **Streamlit** as the SDK
92
- 3. Upload these files:
93
- - `app.py`
94
- - `hts_validator.py`
95
- - `HTS_list.py`
96
- - `requirements.txt`
97
- 4. The app will auto-deploy
98
-
99
- ## Files
100
-
101
- | File | Description |
102
- |------|-------------|
103
- | `app.py` | Streamlit UI application |
104
- | `hts_validator.py` | Core validation logic |
105
- | `HTS_list.py` | Steel, Aluminum, Copper HTS code lists |
106
- | `requirements.txt` | Python dependencies |
107
-
108
- ## Requirements
109
-
110
- - streamlit
111
- - pandas
112
- - openpyxl
 
1
+ ---
2
+ title: HTS Review Tool
3
+ sdk: streamlit
4
+ emoji: 👀
5
+ colorFrom: blue
6
+ colorTo: green
7
+ ---
8
+ # HTS Checker - Tariff Audit Tool
9
+
10
+ A Streamlit application for auditing HTS (Harmonized Tariff Schedule) codes, validating primary HTS against additional tariffs and description keywords.
11
+
12
+ ## Features
13
+
14
+ - **Auto-validation**: Validation runs automatically when file is uploaded
15
+ - **17 Scenarios**: Validates Steel, Aluminum, Copper tariff classifications
16
+ - **Unique Combinations View**: De-duplicates entries by HTS+Description for efficient review
17
+ - **Interactive Filters**: Filter by HTS, description, status, scenario
18
+ - **Bulk Export**: Add filtered results to cache and export to Excel
19
+ - **HTS Reference**: View all Steel/Aluminum/Copper HTS lists with overlap analysis
20
+ - **Editable Keywords**: Customize metal, aluminum, copper, zinc, plastics keyword lists
21
+
22
+ ## Validation Scenarios
23
+
24
+ | ID | Description |
25
+ |----|-------------|
26
+ | S1 | Steel HTS + 232 tariff applied - verify 99030133 present, no 99030125 |
27
+ | S2 | Metal keyword but NOT steel HTS - should apply 99030125, no 232 tariffs |
28
+ | S4 | Aluminum HTS + 232 tariff applied - verify 99030133 present, no 99030125 |
29
+ | S5 | Aluminum keyword but NOT aluminum HTS - should apply 99030125, no 232 tariffs |
30
+ | S7 | Dual Steel+Aluminum HTS - matches keyword, apply corresponding 232, no 99030125 |
31
+ | S7a | Dual Steel+Aluminum HTS + BOTH keywords - flag for manual review |
32
+ | S8 | Dual Steel+Aluminum HTS + NO keywords - flag for manual review |
33
+ | S9 | Copper keyword but NOT copper HTS - should apply 99030125, no 232 tariffs |
34
+ | S11 | Dual Aluminum+Copper HTS + copper keyword - apply 99030133 + copper tariffs, no 99030125 |
35
+ | S12 | Dual Aluminum+Copper HTS + aluminum keyword - apply 99030133 + aluminum 232, no 99030125 |
36
+ | S13 | Zinc keyword - should ONLY apply 99030125, no 232 tariffs allowed |
37
+ | S14 | Plastics keyword + metal HTS - override, should ONLY apply 99030125 |
38
+ | S15 | Steel HTS + aluminum keyword - should apply 99030125, no 99030133 or 232 tariffs |
39
+ | S16 | Aluminum HTS + steel keyword - should apply 99030125, no 99030133 or 232 tariffs |
40
+ | S17 | Copper HTS but NO copper keyword - should apply copper tariffs + 99030125, no 99030133 |
41
+
42
+ ## Key Additional HTS Codes
43
+
44
+ | Code | Type |
45
+ |------|------|
46
+ | 99038190, 99038191 | Steel Section 232 |
47
+ | 99038507, 99038508 | Aluminum Section 232 |
48
+ | 99037801, 99037802 | Copper tariffs |
49
+ | 99030133 | General 301 (accompanies 232) |
50
+ | 99030125 | Mismatch/Override code |
51
+
52
+ ## Input File Format
53
+
54
+ Upload Excel file with these columns:
55
+ - **Column E (Description)**: Product description for keyword matching
56
+ - **Column F (Tariff)**: 10-digit Primary HTS code
57
+ - **Columns I-N (Primary 1-6)**: Additional HTS codes applied
58
+
59
+ ## Default Keywords
60
+
61
+ **Metal**: steel, stainless steel, carbon steel, iron, metal
62
+
63
+ **Aluminum**: aluminum, aluminium
64
+
65
+ **Copper**: copper
66
+
67
+ **Zinc**: zinc
68
+
69
+ **Plastics**: plastic, abs, pu, pvc, polyester, nylon
70
+
71
+ ## Tabs
72
+
73
+ 1. **Upload & Filter**: Upload Excel file, apply initial filters
74
+ 2. **Validation Results**: View all results with interactive filters, add to export cache
75
+ 3. **Unique Combinations**: De-duplicated view by HTS+Description with occurrence count
76
+ 4. **Keyword Management**: Edit keyword lists used for validation
77
+ 5. **Export Selection**: Manage export cache and download Excel reports
78
+ 6. **HTS Reference**: View Steel/Aluminum/Copper HTS lists and overlaps
79
+
80
+ ## Local Development
81
+
82
+ ```bash
83
+ cd HTS_Checker
84
+ pip install -r requirements.txt
85
+ streamlit run app.py
86
+ ```
87
+
88
+ ## Hugging Face Deployment
89
+
90
+ 1. Create a new Space on [Hugging Face](https://huggingface.co/spaces)
91
+ 2. Select **Streamlit** as the SDK
92
+ 3. Upload these files:
93
+ - `app.py`
94
+ - `hts_validator.py`
95
+ - `HTS_list.py`
96
+ - `requirements.txt`
97
+ 4. The app will auto-deploy
98
+
99
+ ## Files
100
+
101
+ | File | Description |
102
+ |------|-------------|
103
+ | `app.py` | Streamlit UI application |
104
+ | `hts_validator.py` | Core validation logic |
105
+ | `HTS_list.py` | Steel, Aluminum, Copper HTS code lists |
106
+ | `requirements.txt` | Python dependencies |
107
+
108
+ ## Requirements
109
+
110
+ - streamlit
111
+ - pandas
112
+ - openpyxl
hts_validator.py CHANGED
@@ -32,6 +32,7 @@ SCENARIO_SUMMARIES = {
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
  }
@@ -611,7 +612,7 @@ class HTSValidator:
611
  issue="; ".join(issues) if issues else "Correct - aluminum keyword with non-aluminum HTS"
612
  )
613
 
614
- # Copper scenarios (COPPER_OK)
615
  if in_copper and not in_steel and not in_aluminum:
616
  if has_copper_kw:
617
  # COPPER_OK: Copper HTS + copper keyword
@@ -635,6 +636,32 @@ class HTSValidator:
635
  unexpected_hts=[],
636
  issue="; ".join(issues) if issues else "Correct - copper HTS + keyword"
637
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
 
639
  # S9: Copper keyword but NOT in copper list
640
  if has_copper_kw and not in_copper:
 
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
+ "S17": "Copper HTS but NO copper keyword - should apply copper tariffs + 99030125, no 99030133",
36
  "COPPER_OK": "Copper HTS + copper keyword - verify copper tariffs applied",
37
  "NONE": "No applicable scenario - entry does not match any validation rules",
38
  }
 
612
  issue="; ".join(issues) if issues else "Correct - aluminum keyword with non-aluminum HTS"
613
  )
614
 
615
+ # Copper scenarios (COPPER_OK, S17)
616
  if in_copper and not in_steel and not in_aluminum:
617
  if has_copper_kw:
618
  # COPPER_OK: Copper HTS + copper keyword
 
636
  unexpected_hts=[],
637
  issue="; ".join(issues) if issues else "Correct - copper HTS + keyword"
638
  )
639
+ else:
640
+ # S17: Copper HTS but NO copper keyword - apply copper tariffs + 99030125, no 99030133
641
+ expected = list(COPPER_CODES) + [MISMATCH_CODE]
642
+ issues = []
643
+
644
+ if not has_copper_tariff:
645
+ issues.append("Missing copper tariff (99037801/02)")
646
+ if not has_mismatch:
647
+ issues.append("Missing 99030125 - copper HTS without copper keyword")
648
+ if has_301:
649
+ issues.append("Should NOT have 99030133 - no copper keyword in description")
650
+
651
+ status = "PASS" if not issues else "FAIL"
652
+ return ValidationResult(
653
+ entry_number=entry_number,
654
+ description=description,
655
+ primary_hts=primary_hts,
656
+ additional_hts=additional_hts,
657
+ scenario_id="S17",
658
+ scenario_summary=SCENARIO_SUMMARIES["S17"],
659
+ status=status,
660
+ expected_hts=expected,
661
+ missing_hts=(list(COPPER_CODES) if not has_copper_tariff else []) + ([MISMATCH_CODE] if not has_mismatch else []),
662
+ unexpected_hts=[GENERAL_301_CODE] if has_301 else [],
663
+ issue="; ".join(issues) if issues else "Correct - copper HTS without keyword, has copper tariffs + 99030125"
664
+ )
665
 
666
  # S9: Copper keyword but NOT in copper list
667
  if has_copper_kw and not in_copper: