DrAbbas commited on
Commit
ebe709f
ยท
verified ยท
1 Parent(s): b73f2ca

๐Ÿ”ฑ SONAR-AI v18.2 | 2026-04-11 08:29:38

Browse files
Files changed (1) hide show
  1. app.py +63 -14
app.py CHANGED
@@ -240,14 +240,31 @@ def load_tsc_database():
240
  try:
241
  df = pd.read_excel(path, engine='openpyxl')
242
  for _, row in df.iterrows():
243
- hs = str(int(row['IDE_HSC_NB1']))
 
 
 
244
  if hs not in TSC_DATABASE:
 
 
 
 
 
 
 
 
 
 
 
245
  TSC_DATABASE[hs] = {
246
- 'desc': str(row['GDS_DS2']).strip()[:100] if pd.notna(row['GDS_DS2']) else '',
247
- 'avg_price': round(float(row['AVR_MNT']), 2) if pd.notna(row['AVR_MNT']) else 0,
248
- 'unit': str(row['AVR_UNT']) if pd.notna(row['AVR_UNT']) else '',
249
- 'nb5': str(row['IDE_HSC_NB5']) if pd.notna(row['IDE_HSC_NB5']) else '',
250
- 'currency': 'USD',
 
 
 
251
  }
252
  print(f"โœ… TSC loaded: {len(TSC_DATABASE)} HS codes from {path}")
253
  return
@@ -1211,16 +1228,20 @@ def lookup_hs(hs_code):
1211
  def get_hs_info(cargo_key):
1212
  if cargo_key not in CARGO_DATABASE:
1213
  return {'en': cargo_key.upper(), 'ar': cargo_key, 'hs': '999999', 'ch': '99',
1214
- 'ch_name': '', 'duty': 15, 'tsc_desc': '', 'avg_price': 0, 'unit': '', 'tsc_code': ''}
 
1215
  c = CARGO_DATABASE[cargo_key]
1216
  tsc = lookup_hs(c['hs'])
1217
  return {
1218
  'en': cargo_key.upper().replace('_', ' '), 'ar': c['ar'], 'hs': c['hs'], 'ch': c['ch'],
1219
- 'ch_name': HS_CHAPTERS.get(c['ch'], ''), 'duty': c['duty'],
1220
  'tsc_desc': tsc['desc'] if tsc else c['ar'],
1221
  'avg_price': tsc['avg_price'] if tsc else 0,
1222
- 'unit': tsc['unit'] if tsc else '',
1223
- 'tsc_code': tsc['nb5'] if tsc else '',
 
 
 
1224
  }
1225
 
1226
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
@@ -3480,10 +3501,10 @@ def analyze_full(img, declared_text):
3480
 
3481
  # โ•โ• ุฏู…ุฌ ุฐูƒูŠ ู„ู„ูุฆุงุช ุงู„ู…ุชุดุงุจู‡ุฉ โ•โ•
3482
  _SMART_GROUPS = {
3483
- 'rice': (['seeds','rice','food','canned_food','sugar'], 'ุฑุฒ', '๐ŸŒพ'),
3484
- 'banana': (['banana','fruit','food'], 'ู…ูˆุฒ', '๐ŸŒ'),
3485
- 'pharmaceutical': (['pharmaceutical','medicine','medical','pharmacy'], 'ุฃุฏูˆูŠุฉ', '๐Ÿ’Š'),
3486
- 'tobacco': (['tobacco','cigarette','snacks','smoking'], 'ุณุฌุงุฆุฑ', '๐Ÿšฌ'),
3487
  }
3488
 
3489
  def smart_category(top5):
@@ -3580,11 +3601,24 @@ def analyze_full(img, declared_text):
3580
  ar4 = info4.get('ar', best_cat14) or best_cat14
3581
  hs4 = info4.get('hs', 'โ€”') or 'โ€”'
3582
  duty4 = info4.get('duty', 0)
 
 
 
 
 
3583
  is_d4 = any(d in best_cat14.lower() for d in DANGER_48)
3584
  bg4 = '#FFEBEE' if is_d4 else '#E8F5E9'
3585
  clr4 = '#B71C1C' if is_d4 else '#1B5E20'
3586
  icon4 = '๐Ÿšจ' if is_d4 else 'โœ…'
3587
  smart_badge14 = f"<span style='background:#1565C0;color:white;font-size:11px;padding:2px 7px;border-radius:8px;margin-top:4px;display:inline-block;'>{smart_note14}</span>" if smart_note14 else ""
 
 
 
 
 
 
 
 
3588
  rows4 = ''.join([
3589
  f"<div style='display:flex;justify-content:space-between;padding:4px 8px;"
3590
  f"border-bottom:1px solid #F0F0F0;font-size:13px;'>"
@@ -3603,6 +3637,7 @@ def analyze_full(img, declared_text):
3603
  <div style='font-size:12px;color:{clr4};margin-top:2px;'>HS: {hs4} | ุงู„ุฑุณูˆู…: {duty4}% | ุซู‚ุฉ: {best_conf14:.1%}</div>
3604
  {smart_badge14}
3605
  </div>
 
3606
  <div style='padding:4px 0;'>{rows4}</div>
3607
  </div>"""
3608
  except Exception as e:
@@ -3702,11 +3737,24 @@ def analyze_full(img, declared_text):
3702
  ar17 = info17.get('ar', best_cat17) or best_cat17
3703
  hs17 = info17.get('hs', 'โ€”') or 'โ€”'
3704
  duty17 = info17.get('duty', 0)
 
 
 
 
 
3705
  is_d17 = any(d in best_cat17.lower() for d in DANGER_48)
3706
  bg17 = '#FFEBEE' if is_d17 else '#E8F5E9'
3707
  clr17 = '#B71C1C' if is_d17 else '#1B5E20'
3708
  icon17 = '๐Ÿšจ' if is_d17 else 'โœ…'
3709
  smart_badge17 = f"<span style='background:#1565C0;color:white;font-size:11px;padding:2px 7px;border-radius:8px;margin-top:4px;display:inline-block;'>{smart_note17}</span>" if smart_note17 else ""
 
 
 
 
 
 
 
 
3710
  rows17 = ''.join([
3711
  f"<div style='display:flex;justify-content:space-between;padding:4px 8px;"
3712
  f"border-bottom:1px solid #F0F0F0;font-size:13px;'>"
@@ -3747,6 +3795,7 @@ def analyze_full(img, declared_text):
3747
  <div style='font-size:12px;color:{clr17};margin-top:2px;'>HS: {hs17} | ุงู„ุฑุณูˆู…: {duty17}% | ุซู‚ุฉ: {best_conf17:.1%}</div>
3748
  <div style='margin-top:5px;'>{smart_badge17}{agree_badge}</div>
3749
  </div>
 
3750
  <div style='padding:4px 0;'>{rows17}</div>
3751
  <div style='background:{fusion_color};color:white;padding:8px 12px;text-align:center;font-weight:bold;font-size:14px;'>
3752
  {fusion_icon} ุงู„ุญูƒู… ุงู„ู†ู‡ุงุฆูŠ: {fusion_text}
 
240
  try:
241
  df = pd.read_excel(path, engine='openpyxl')
242
  for _, row in df.iterrows():
243
+ try:
244
+ hs = str(int(float(str(row['IDE_HSC_NB1']).replace(',','')))).strip()
245
+ except:
246
+ continue
247
  if hs not in TSC_DATABASE:
248
+ try: avg_p = round(float(str(row['AVR_MNT']).replace(',','')), 3)
249
+ except: avg_p = 0
250
+ try: min_p = round(float(str(row['CAL_MIN_VAL']).replace(',','')), 3)
251
+ except: min_p = 0
252
+ try: max_p = round(float(str(row['CAL_MAX_VAL']).replace(',','')), 3)
253
+ except: max_p = 0
254
+ try: duty = round(float(str(row['GDS_MRG']).replace(',','')), 1)
255
+ except: duty = 0
256
+ unit_name = ''
257
+ if pd.notna(row.get('AVR_UNT_NAM',None)): unit_name = str(row['AVR_UNT_NAM'])
258
+ elif pd.notna(row.get('AVR_UNT',None)): unit_name = str(row['AVR_UNT'])
259
  TSC_DATABASE[hs] = {
260
+ 'desc': str(row['GDS_DS2']).strip()[:120] if pd.notna(row['GDS_DS2']) else '',
261
+ 'avg_price': avg_p,
262
+ 'min_price': min_p,
263
+ 'max_price': max_p,
264
+ 'unit': unit_name,
265
+ 'duty': duty,
266
+ 'nb5': str(row['IDE_HSC_NB5']) if pd.notna(row['IDE_HSC_NB5']) else '',
267
+ 'currency': str(row['GDS_CUR_COD']) if pd.notna(row.get('GDS_CUR_COD',None)) else 'USD',
268
  }
269
  print(f"โœ… TSC loaded: {len(TSC_DATABASE)} HS codes from {path}")
270
  return
 
1228
  def get_hs_info(cargo_key):
1229
  if cargo_key not in CARGO_DATABASE:
1230
  return {'en': cargo_key.upper(), 'ar': cargo_key, 'hs': '999999', 'ch': '99',
1231
+ 'ch_name': '', 'duty': 15, 'tsc_desc': '', 'avg_price': 0,
1232
+ 'min_price': 0, 'max_price': 0, 'unit': '', 'tsc_code': '', 'currency': 'USD'}
1233
  c = CARGO_DATABASE[cargo_key]
1234
  tsc = lookup_hs(c['hs'])
1235
  return {
1236
  'en': cargo_key.upper().replace('_', ' '), 'ar': c['ar'], 'hs': c['hs'], 'ch': c['ch'],
1237
+ 'ch_name': HS_CHAPTERS.get(c['ch'], ''), 'duty': tsc['duty'] if tsc else c['duty'],
1238
  'tsc_desc': tsc['desc'] if tsc else c['ar'],
1239
  'avg_price': tsc['avg_price'] if tsc else 0,
1240
+ 'min_price': tsc['min_price'] if tsc else 0,
1241
+ 'max_price': tsc['max_price'] if tsc else 0,
1242
+ 'unit': tsc['unit'] if tsc else '',
1243
+ 'currency': tsc['currency'] if tsc else 'USD',
1244
+ 'tsc_code': tsc['nb5'] if tsc else '',
1245
  }
1246
 
1247
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
 
3501
 
3502
  # โ•โ• ุฏู…ุฌ ุฐูƒูŠ ู„ู„ูุฆุงุช ุงู„ู…ุชุดุงุจู‡ุฉ โ•โ•
3503
  _SMART_GROUPS = {
3504
+ 'rice': (['seeds','rice','food','canned_food','sugar'], 'ุฑุฒ', '๐ŸŒพ'),
3505
+ 'banana': (['banana','fruit','food'], 'ู…ูˆุฒ', '๐ŸŒ'),
3506
+ 'pharmaceutical': (['pharmaceutical','medicine','medical','pharmacy','drug'], 'ุฃุฏูˆูŠุฉ ุจุดุฑูŠุฉ', '๐Ÿ’Š'),
3507
+ 'tobacco': (['tobacco','cigarette','snacks','smoking'], 'ุณุฌุงุฆุฑ', '๐Ÿšฌ'),
3508
  }
3509
 
3510
  def smart_category(top5):
 
3601
  ar4 = info4.get('ar', best_cat14) or best_cat14
3602
  hs4 = info4.get('hs', 'โ€”') or 'โ€”'
3603
  duty4 = info4.get('duty', 0)
3604
+ avg_p4 = info4.get('avg_price', 0)
3605
+ min_p4 = info4.get('min_price', 0)
3606
+ max_p4 = info4.get('max_price', 0)
3607
+ unit4 = info4.get('unit', '')
3608
+ cur4 = info4.get('currency', 'USD')
3609
  is_d4 = any(d in best_cat14.lower() for d in DANGER_48)
3610
  bg4 = '#FFEBEE' if is_d4 else '#E8F5E9'
3611
  clr4 = '#B71C1C' if is_d4 else '#1B5E20'
3612
  icon4 = '๐Ÿšจ' if is_d4 else 'โœ…'
3613
  smart_badge14 = f"<span style='background:#1565C0;color:white;font-size:11px;padding:2px 7px;border-radius:8px;margin-top:4px;display:inline-block;'>{smart_note14}</span>" if smart_note14 else ""
3614
+ # ุณุนุฑ TSC
3615
+ if avg_p4 > 0:
3616
+ price_str = f"{avg_p4:.2f} {cur4}/{unit4}"
3617
+ if min_p4 > 0 and max_p4 > 0:
3618
+ price_str += f" (ู†ุทุงู‚: {min_p4:.2f}โ€“{max_p4:.2f})"
3619
+ price_row4 = f"<div style='background:#E3F2FD;padding:5px 10px;font-size:12px;color:#0D47A1;border-top:1px solid #E0E0E0;'>๐Ÿ’ฐ ู…ุชูˆุณุท ุงู„ุณุนุฑ: <b>{price_str}</b></div>"
3620
+ else:
3621
+ price_row4 = ""
3622
  rows4 = ''.join([
3623
  f"<div style='display:flex;justify-content:space-between;padding:4px 8px;"
3624
  f"border-bottom:1px solid #F0F0F0;font-size:13px;'>"
 
3637
  <div style='font-size:12px;color:{clr4};margin-top:2px;'>HS: {hs4} | ุงู„ุฑุณูˆู…: {duty4}% | ุซู‚ุฉ: {best_conf14:.1%}</div>
3638
  {smart_badge14}
3639
  </div>
3640
+ {price_row4}
3641
  <div style='padding:4px 0;'>{rows4}</div>
3642
  </div>"""
3643
  except Exception as e:
 
3737
  ar17 = info17.get('ar', best_cat17) or best_cat17
3738
  hs17 = info17.get('hs', 'โ€”') or 'โ€”'
3739
  duty17 = info17.get('duty', 0)
3740
+ avg_p17= info17.get('avg_price', 0)
3741
+ min_p17= info17.get('min_price', 0)
3742
+ max_p17= info17.get('max_price', 0)
3743
+ unit17 = info17.get('unit', '')
3744
+ cur17 = info17.get('currency', 'USD')
3745
  is_d17 = any(d in best_cat17.lower() for d in DANGER_48)
3746
  bg17 = '#FFEBEE' if is_d17 else '#E8F5E9'
3747
  clr17 = '#B71C1C' if is_d17 else '#1B5E20'
3748
  icon17 = '๐Ÿšจ' if is_d17 else 'โœ…'
3749
  smart_badge17 = f"<span style='background:#1565C0;color:white;font-size:11px;padding:2px 7px;border-radius:8px;margin-top:4px;display:inline-block;'>{smart_note17}</span>" if smart_note17 else ""
3750
+ # ุณุนุฑ TSC
3751
+ if avg_p17 > 0:
3752
+ price_str17 = f"{avg_p17:.2f} {cur17}/{unit17}"
3753
+ if min_p17 > 0 and max_p17 > 0:
3754
+ price_str17 += f" (ู†ุทุงู‚: {min_p17:.2f}โ€“{max_p17:.2f})"
3755
+ price_row17 = f"<div style='background:#E3F2FD;padding:5px 10px;font-size:12px;color:#0D47A1;border-top:1px solid #E0E0E0;'>๐Ÿ’ฐ ู…ุชูˆุณุท ุงู„ุณุนุฑ: <b>{price_str17}</b></div>"
3756
+ else:
3757
+ price_row17 = ""
3758
  rows17 = ''.join([
3759
  f"<div style='display:flex;justify-content:space-between;padding:4px 8px;"
3760
  f"border-bottom:1px solid #F0F0F0;font-size:13px;'>"
 
3795
  <div style='font-size:12px;color:{clr17};margin-top:2px;'>HS: {hs17} | ุงู„ุฑุณูˆู…: {duty17}% | ุซู‚ุฉ: {best_conf17:.1%}</div>
3796
  <div style='margin-top:5px;'>{smart_badge17}{agree_badge}</div>
3797
  </div>
3798
+ {price_row17}
3799
  <div style='padding:4px 0;'>{rows17}</div>
3800
  <div style='background:{fusion_color};color:white;padding:8px 12px;text-align:center;font-weight:bold;font-size:14px;'>
3801
  {fusion_icon} ุงู„ุญูƒู… ุงู„ู†ู‡ุงุฆูŠ: {fusion_text}