MakPr016 commited on
Commit
81931f5
·
1 Parent(s): 0fc22ba
Files changed (4) hide show
  1. __pycache__/models.cpython-310.pyc +0 -0
  2. main.py +79 -6
  3. models.py +1 -0
  4. requirements.txt +2 -1
__pycache__/models.cpython-310.pyc CHANGED
Binary files a/__pycache__/models.cpython-310.pyc and b/__pycache__/models.cpython-310.pyc differ
 
main.py CHANGED
@@ -1,6 +1,7 @@
1
  import os
2
  import uvicorn
3
- from fastapi import FastAPI, HTTPException
 
4
  from fastapi.middleware.cors import CORSMiddleware
5
  from supabase import create_client, Client
6
  from dotenv import load_dotenv
@@ -22,8 +23,62 @@ app.add_middleware(
22
  allow_headers=["*"],
23
  )
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  @app.get("/api/analyze/{rfq_id}", response_model=AnalysisResponse)
26
- async def analyze_rfq(rfq_id: str):
27
  items_res = supabase.table('rfq_line_items').select("*").eq('rfq_id', rfq_id).execute()
28
  if not items_res.data:
29
  raise HTTPException(status_code=404, detail="RFQ Items not found")
@@ -34,21 +89,33 @@ async def analyze_rfq(rfq_id: str):
34
  ]
35
 
36
  quotes_res = supabase.table('quotations').select(
37
- "id, vendor_id, vendors(vendor_name, rating, is_verified)"
38
  ).eq('rfq_id', rfq_id).execute()
39
 
40
  quote_ids = [q['id'] for q in quotes_res.data]
41
  if not quote_ids:
42
- return AnalysisResponse(rfq_id=rfq_id, strategies={}, recommended_strategy="None")
 
 
 
 
 
43
 
44
  q_items_res = supabase.table('quotation_items').select(
45
  "rfq_item_id, unit_price, delivery_time_days, quotation_id, brand, manufacturer"
46
  ).in_('quotation_id', quote_ids).execute()
47
 
48
- vendor_map = {}
 
49
 
50
  for q in quotes_res.data:
51
  v_id = q['vendor_id']
 
 
 
 
 
 
52
  if v_id not in vendor_map:
53
  vendor_data = q['vendors']
54
  vendor_map[v_id] = VendorOffer(
@@ -65,9 +132,14 @@ async def analyze_rfq(rfq_id: str):
65
  q_id = qi['quotation_id']
66
  if q_id in q_to_v:
67
  v_id = q_to_v[q_id]
 
 
 
 
 
68
  vendor_map[v_id].offers.append(QuoteOffer(
69
  rfq_item_id=qi['rfq_item_id'],
70
- unit_price=qi['unit_price'],
71
  delivery_days=qi.get('delivery_time_days', 7),
72
  brand=qi.get('brand'),
73
  manufacturer=qi.get('manufacturer')
@@ -87,6 +159,7 @@ async def analyze_rfq(rfq_id: str):
87
 
88
  return AnalysisResponse(
89
  rfq_id=rfq_id,
 
90
  strategies=results,
91
  recommended_strategy=rec
92
  )
 
1
  import os
2
  import uvicorn
3
+ import requests
4
+ from fastapi import FastAPI, HTTPException, Query
5
  from fastapi.middleware.cors import CORSMiddleware
6
  from supabase import create_client, Client
7
  from dotenv import load_dotenv
 
23
  allow_headers=["*"],
24
  )
25
 
26
+ # Fallback rates in case API fails
27
+ EXCHANGE_RATES = {
28
+ "USD": 1.0,
29
+ "EUR": 1.08,
30
+ "GBP": 1.25,
31
+ "INR": 0.012,
32
+ "SEK": 0.095,
33
+ "JPY": 0.0067,
34
+ "CAD": 0.74,
35
+ "AUD": 0.65,
36
+ "CNY": 0.14,
37
+ "AED": 0.27
38
+ }
39
+
40
+ def fetch_live_rates():
41
+ global EXCHANGE_RATES
42
+ try:
43
+ # Using a free standard API for USD base rates
44
+ response = requests.get("https://api.exchangerate-api.com/v4/latest/USD")
45
+ data = response.json()
46
+ if "rates" in data:
47
+ EXCHANGE_RATES = data["rates"]
48
+ # Ensure USD is 1.0
49
+ EXCHANGE_RATES["USD"] = 1.0
50
+ print("Successfully fetched live exchange rates.")
51
+ except Exception as e:
52
+ print(f"Failed to fetch live rates, using fallback. Error: {e}")
53
+
54
+ @app.on_event("startup")
55
+ async def startup_event():
56
+ fetch_live_rates()
57
+
58
+ def get_exchange_rate(currency_code: str) -> float:
59
+ return EXCHANGE_RATES.get(currency_code.upper(), 1.0)
60
+
61
+ def convert_price(price: float, from_curr: str, to_curr: str) -> float:
62
+ # If currencies are the same, return original price
63
+ if from_curr.upper() == to_curr.upper():
64
+ return price
65
+
66
+ # Logic: Convert 'from' to USD, then USD to 'to'
67
+ # API returns rates where 1 USD = X Currency
68
+ # Price in USD = Price / Rate(from)
69
+ # Price in Target = Price in USD * Rate(to)
70
+
71
+ rate_from = get_exchange_rate(from_curr)
72
+ rate_to = get_exchange_rate(to_curr)
73
+
74
+ if rate_from == 0:
75
+ return price
76
+
77
+ price_in_usd = price / rate_from
78
+ return price_in_usd * rate_to
79
+
80
  @app.get("/api/analyze/{rfq_id}", response_model=AnalysisResponse)
81
+ async def analyze_rfq(rfq_id: str, target_currency: str = Query("USD")):
82
  items_res = supabase.table('rfq_line_items').select("*").eq('rfq_id', rfq_id).execute()
83
  if not items_res.data:
84
  raise HTTPException(status_code=404, detail="RFQ Items not found")
 
89
  ]
90
 
91
  quotes_res = supabase.table('quotations').select(
92
+ "id, vendor_id, metadata, vendors(vendor_name, rating, is_verified)"
93
  ).eq('rfq_id', rfq_id).execute()
94
 
95
  quote_ids = [q['id'] for q in quotes_res.data]
96
  if not quote_ids:
97
+ return AnalysisResponse(
98
+ rfq_id=rfq_id,
99
+ currency=target_currency,
100
+ strategies={},
101
+ recommended_strategy="None"
102
+ )
103
 
104
  q_items_res = supabase.table('quotation_items').select(
105
  "rfq_item_id, unit_price, delivery_time_days, quotation_id, brand, manufacturer"
106
  ).in_('quotation_id', quote_ids).execute()
107
 
108
+ vendor_map = {}
109
+ quote_currency_map = {}
110
 
111
  for q in quotes_res.data:
112
  v_id = q['vendor_id']
113
+
114
+ meta = q.get('metadata') or {}
115
+ logistics = meta.get('logistics') or {}
116
+ currency = logistics.get('currency', 'USD')
117
+ quote_currency_map[q['id']] = currency
118
+
119
  if v_id not in vendor_map:
120
  vendor_data = q['vendors']
121
  vendor_map[v_id] = VendorOffer(
 
132
  q_id = qi['quotation_id']
133
  if q_id in q_to_v:
134
  v_id = q_to_v[q_id]
135
+
136
+ source_curr = quote_currency_map.get(q_id, "USD")
137
+ original_price = qi['unit_price']
138
+ converted_price = convert_price(original_price, source_curr, target_currency)
139
+
140
  vendor_map[v_id].offers.append(QuoteOffer(
141
  rfq_item_id=qi['rfq_item_id'],
142
+ unit_price=converted_price,
143
  delivery_days=qi.get('delivery_time_days', 7),
144
  brand=qi.get('brand'),
145
  manufacturer=qi.get('manufacturer')
 
159
 
160
  return AnalysisResponse(
161
  rfq_id=rfq_id,
162
+ currency=target_currency,
163
  strategies=results,
164
  recommended_strategy=rec
165
  )
models.py CHANGED
@@ -21,6 +21,7 @@ class StrategyResult(BaseModel):
21
 
22
  class AnalysisResponse(BaseModel):
23
  rfq_id: str
 
24
  strategies: Dict[str, StrategyResult]
25
  recommended_strategy: str
26
 
 
21
 
22
  class AnalysisResponse(BaseModel):
23
  rfq_id: str
24
+ currency: str
25
  strategies: Dict[str, StrategyResult]
26
  recommended_strategy: str
27
 
requirements.txt CHANGED
@@ -4,4 +4,5 @@ supabase
4
  pandas
5
  numpy
6
  pydantic
7
- python-dotenv
 
 
4
  pandas
5
  numpy
6
  pydantic
7
+ python-dotenv
8
+ requests