Álvaro Valenzuela Valdes commited on
Commit
b294142
·
1 Parent(s): 604982f

Fix Market Monitor timezone issues and DBManager styling typo (cleaned)

Browse files
backend/app/routers/oc.py CHANGED
@@ -19,8 +19,9 @@ async def list_purchase_orders(
19
  List purchase orders for a specific date (ddmmaaaa).
20
  """
21
  if not date:
22
- from datetime import datetime
23
- date = datetime.now().strftime("%d%m%Y")
 
24
 
25
  # Try to fetch current OC data from the live API
26
  ocs = await get_ocs_by_date(date, status)
 
19
  List purchase orders for a specific date (ddmmaaaa).
20
  """
21
  if not date:
22
+ from datetime import datetime, timedelta, timezone
23
+ chile_tz = timezone(timedelta(hours=-4))
24
+ date = datetime.now(chile_tz).strftime("%d%m%Y")
25
 
26
  # Try to fetch current OC data from the live API
27
  ocs = await get_ocs_by_date(date, status)
backend/app/services/mercado_publico.py CHANGED
@@ -257,7 +257,8 @@ async def get_tenders_by_filters(
257
  else:
258
  # Default to today if no date is provided for specific filters
259
  if status or org_code or provider_code:
260
- params["fecha"] = datetime.now().strftime("%d%m%Y")
 
261
 
262
  if status:
263
  # Map friendly status to MP codes
@@ -288,7 +289,8 @@ async def fetch_tenders(
288
  date: Optional[str] = None,
289
  type_code: Optional[str] = None
290
  ) -> List[Tender]:
291
- search_date = normalize_mp_date(date if date else datetime.now().strftime("%Y-%m-%d"))
 
292
 
293
  if not date:
294
  tenders = await get_active_tenders()
 
257
  else:
258
  # Default to today if no date is provided for specific filters
259
  if status or org_code or provider_code:
260
+ chile_tz = timezone(timedelta(hours=-4))
261
+ params["fecha"] = datetime.now(chile_tz).strftime("%d%m%Y")
262
 
263
  if status:
264
  # Map friendly status to MP codes
 
289
  date: Optional[str] = None,
290
  type_code: Optional[str] = None
291
  ) -> List[Tender]:
292
+ chile_tz = timezone(timedelta(hours=-4))
293
+ search_date = normalize_mp_date(date if date else datetime.now(chile_tz).strftime("%Y-%m-%d"))
294
 
295
  if not date:
296
  tenders = await get_active_tenders()
backend/app/services/sync.py CHANGED
@@ -1,5 +1,5 @@
1
  from sqlalchemy.orm import Session
2
- from datetime import datetime
3
  from app.models.tender import TenderModel
4
  from app.models.oc import OCModel
5
  from app.services.mercado_publico import fetch_tenders, get_tender_by_code
@@ -91,7 +91,8 @@ async def sync_purchase_orders_to_db(db: Session, date: str = None, status: str
91
  Fetches purchase orders from Mercado Público and saves them in the local database.
92
  """
93
  if not date:
94
- date = datetime.now().strftime("%d%m%Y")
 
95
 
96
  try:
97
  api_orders = await get_ocs_by_date(date, status)
@@ -147,7 +148,8 @@ def clean_expired_tenders(db: Session):
147
  """
148
  Removes tenders where closing_date is in the past.
149
  """
150
- now = datetime.now()
 
151
  expired = db.query(TenderModel).filter(TenderModel.closing_date < now).delete()
152
  db.commit()
153
  print(f"[Sync] Cleaned {expired} expired tenders.")
 
1
  from sqlalchemy.orm import Session
2
+ from datetime import datetime, timedelta, timezone
3
  from app.models.tender import TenderModel
4
  from app.models.oc import OCModel
5
  from app.services.mercado_publico import fetch_tenders, get_tender_by_code
 
91
  Fetches purchase orders from Mercado Público and saves them in the local database.
92
  """
93
  if not date:
94
+ chile_tz = timezone(timedelta(hours=-4))
95
+ date = datetime.now(chile_tz).strftime("%d%m%Y")
96
 
97
  try:
98
  api_orders = await get_ocs_by_date(date, status)
 
148
  """
149
  Removes tenders where closing_date is in the past.
150
  """
151
+ chile_tz = timezone(timedelta(hours=-4))
152
+ now = datetime.now(chile_tz)
153
  expired = db.query(TenderModel).filter(TenderModel.closing_date < now).delete()
154
  db.commit()
155
  print(f"[Sync] Cleaned {expired} expired tenders.")
frontend/components/DBManager.tsx CHANGED
@@ -31,9 +31,9 @@ export default function DBManager({ onFilterClick, lang }: Props) {
31
  setMessage(null);
32
  try {
33
  const result = await syncDatabase();
34
- setMessage({
35
- type: 'success',
36
- text: `Sync complete! New: ${result.tenders?.new || 0} tenders, ${result.purchase_orders?.new || 0} OCs.`
37
  });
38
  await loadStats();
39
  } catch (e) {
@@ -45,7 +45,7 @@ export default function DBManager({ onFilterClick, lang }: Props) {
45
 
46
  const handleClear = async () => {
47
  if (!confirm("Are you sure you want to delete ALL local tenders and purchase orders? This cannot be undone.")) return;
48
-
49
  setIsActionInProgress(true);
50
  setMessage(null);
51
  try {
@@ -74,7 +74,7 @@ export default function DBManager({ onFilterClick, lang }: Props) {
74
  <h2 className="text-3xl font-black text-white tracking-tight">{t.databaseTitle}</h2>
75
  <p className="text-slate-400 mt-1">{t.databaseDesc}</p>
76
  </div>
77
-
78
  <div className="flex items-center gap-3">
79
  <button
80
  onClick={handleSync}
@@ -131,8 +131,8 @@ export default function DBManager({ onFilterClick, lang }: Props) {
131
  </h3>
132
  <div className="space-y-4">
133
  {stats?.top_buyers?.map((buyer: any, idx: number) => (
134
- <button
135
- key={idx}
136
  onClick={() => onFilterClick?.("buyer", buyer.name)}
137
  className="w-full flex items-center justify-between p-4 rounded-2xl bg-white/[0.03] border border-white/5 hover:bg-white/[0.08] hover:border-cyan/30 transition-all group/row cursor-pointer text-left"
138
  >
@@ -156,14 +156,14 @@ export default function DBManager({ onFilterClick, lang }: Props) {
156
  <span>💡</span> Persistence Insights
157
  </h3>
158
  <div className="space-y-6">
159
- <div className="p-4 rounded-2xl bg-blue-500/5 border border-blue-500/10">
160
- <p className="text-xs text-blue-400 font-bold mb-1">Local Mode Active</p>
161
- <p className="text-xs text-slate-400 leading-relaxed">System is prioritizing local database for faster search. Global sync updates the local cache with the latest Mercado Público data.</p>
162
- </div>
163
- <div className="p-4 rounded-2xl bg-purple-500/5 border border-purple-500/10">
164
- <p className="text-xs text-purple-400 font-bold mb-1">Integrity Check</p>
165
- <p className="text-xs text-slate-400 leading-relaxed">All nested data (attachments, items, criteria) is successfully serialized as JSON in the SQLite storage.</p>
166
- </div>
167
  </div>
168
  </div>
169
  </div>
 
31
  setMessage(null);
32
  try {
33
  const result = await syncDatabase();
34
+ setMessage({
35
+ type: 'success',
36
+ text: `Sync complete! New: ${result.tenders?.new || 0} tenders, ${result.purchase_orders?.new || 0} OCs.`
37
  });
38
  await loadStats();
39
  } catch (e) {
 
45
 
46
  const handleClear = async () => {
47
  if (!confirm("Are you sure you want to delete ALL local tenders and purchase orders? This cannot be undone.")) return;
48
+
49
  setIsActionInProgress(true);
50
  setMessage(null);
51
  try {
 
74
  <h2 className="text-3xl font-black text-white tracking-tight">{t.databaseTitle}</h2>
75
  <p className="text-slate-400 mt-1">{t.databaseDesc}</p>
76
  </div>
77
+
78
  <div className="flex items-center gap-3">
79
  <button
80
  onClick={handleSync}
 
131
  </h3>
132
  <div className="space-y-4">
133
  {stats?.top_buyers?.map((buyer: any, idx: number) => (
134
+ <button
135
+ key={idx}
136
  onClick={() => onFilterClick?.("buyer", buyer.name)}
137
  className="w-full flex items-center justify-between p-4 rounded-2xl bg-white/[0.03] border border-white/5 hover:bg-white/[0.08] hover:border-cyan/30 transition-all group/row cursor-pointer text-left"
138
  >
 
156
  <span>💡</span> Persistence Insights
157
  </h3>
158
  <div className="space-y-6">
159
+ <div className="p-4 rounded-2xl bg-blue-500/5 border border-blue-500/10">
160
+ <p className="text-xs text-blue-400 font-bold mb-1">Local Mode Active</p>
161
+ <p className="text-xs text-slate-400 leading-relaxed">System is prioritizing local database for faster search. Global sync updates the local cache with the latest Mercado Público data.</p>
162
+ </div>
163
+ <div className="p-4 rounded-2xl bg-purple-500/5 border border-purple-500/10">
164
+ <p className="text-xs text-purple-400 font-bold mb-1">Integrity Check</p>
165
+ <p className="text-xs text-slate-400 leading-relaxed">All nested data (attachments, items, criteria) is successfully serialized as JSON in the SQLite storage.</p>
166
+ </div>
167
  </div>
168
  </div>
169
  </div>