krishnadhulipalla commited on
Commit
f3420b7
·
verified ·
1 Parent(s): 53b8def

Update backend/app/data/store.py

Browse files
Files changed (1) hide show
  1. backend/app/data/store.py +33 -29
backend/app/data/store.py CHANGED
@@ -1,13 +1,22 @@
1
- # same content as your current store.py, just moved here
2
  from __future__ import annotations
3
  import json, sqlite3
4
  from datetime import datetime, timezone, timedelta
5
  from typing import Dict, Any, List, Optional
6
  from pathlib import Path
7
- from ..data.geo import haversine_km
8
 
9
- Path("data").mkdir(exist_ok=True)
10
- _CONN = sqlite3.connect("data/pulsemaps_reports.db", check_same_thread=False)
 
 
 
 
 
 
 
 
 
 
11
  _CONN.execute("""
12
  CREATE TABLE IF NOT EXISTS reports (
13
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -24,9 +33,17 @@ def _row_to_feature(row: tuple) -> Dict[str, Any]:
24
  _id, lat, lon, text, props_json, created_at = row
25
  props = {"type": "user_report", "text": text, "reported_at": created_at}
26
  if props_json:
27
- try: props.update(json.loads(props_json))
28
- except Exception: props["raw_props"] = props_json
29
- return {"type": "Feature", "geometry": {"type": "Point", "coordinates": [lon, lat]}, "properties": props}
 
 
 
 
 
 
 
 
30
 
31
  def add_report(lat: float, lon: float, text: str = "User report", props: dict | None = None):
32
  created_at = datetime.now(timezone.utc).isoformat()
@@ -37,9 +54,8 @@ def add_report(lat: float, lon: float, text: str = "User report", props: dict |
37
  (float(lat), float(lon), text, props_json, created_at)
38
  )
39
  _CONN.commit()
40
- rid = str(cur.lastrowid) # ✅ new id
41
 
42
- # include rid in the immediate response so the UI can show counts instantly
43
  out_props = {"type": "user_report", "text": text, "reported_at": created_at, **props}
44
  out_props.setdefault("rid", rid)
45
  out_props.setdefault("id", rid)
@@ -55,7 +71,13 @@ def get_feature_collection() -> Dict[str, Any]:
55
  feats = [_row_to_feature(r) for r in cur.fetchall()]
56
  return {"type": "FeatureCollection", "features": feats}
57
 
58
- def find_reports_near(lat: float, lon: float, radius_km: float = 10.0, limit: int = 20, max_age_hours: Optional[int] = None) -> List[Dict[str, Any]]:
 
 
 
 
 
 
59
  params: list[Any] = []
60
  sql = "SELECT id, lat, lon, text, props_json, created_at FROM reports"
61
  if max_age_hours is not None:
@@ -76,25 +98,7 @@ def find_reports_near(lat: float, lon: float, radius_km: float = 10.0, limit: in
76
  out = [_row_to_feature(r) for _, r in cand[:max(1, limit)]]
77
  return out
78
 
79
- def clear_reports() -> dict[str, any]:
80
  _CONN.execute("DELETE FROM reports")
81
  _CONN.commit()
82
  return {"ok": True, "message": "All reports cleared."}
83
-
84
- def _row_to_feature(row: tuple) -> Dict[str, Any]:
85
- _id, lat, lon, text, props_json, created_at = row
86
- props = {"type": "user_report", "text": text, "reported_at": created_at}
87
- if props_json:
88
- try:
89
- props.update(json.loads(props_json))
90
- except Exception:
91
- props["raw_props"] = props_json
92
- # ✅ ensure a stable id is present on every returned feature
93
- props.setdefault("rid", str(_id))
94
- props.setdefault("id", str(_id)) # optional mirror
95
- return {
96
- "type": "Feature",
97
- "geometry": {"type": "Point", "coordinates": [lon, lat]},
98
- "properties": props,
99
- }
100
-
 
1
+ # backend/app/data/store.py
2
  from __future__ import annotations
3
  import json, sqlite3
4
  from datetime import datetime, timezone, timedelta
5
  from typing import Dict, Any, List, Optional
6
  from pathlib import Path
 
7
 
8
+ from ..config.settings import settings
9
+ from .geo import haversine_km
10
+
11
+ DB_PATH: Path = settings.REPORTS_DB
12
+ # Ensure parent exists & fail early if unwritable
13
+ DB_PATH.parent.mkdir(parents=True, exist_ok=True)
14
+ try:
15
+ DB_PATH.touch(exist_ok=True)
16
+ except Exception as e:
17
+ raise RuntimeError(f"Cannot create DB file at {DB_PATH}: {e}")
18
+
19
+ _CONN = sqlite3.connect(str(DB_PATH), check_same_thread=False)
20
  _CONN.execute("""
21
  CREATE TABLE IF NOT EXISTS reports (
22
  id INTEGER PRIMARY KEY AUTOINCREMENT,
 
33
  _id, lat, lon, text, props_json, created_at = row
34
  props = {"type": "user_report", "text": text, "reported_at": created_at}
35
  if props_json:
36
+ try:
37
+ props.update(json.loads(props_json))
38
+ except Exception:
39
+ props["raw_props"] = props_json
40
+ props.setdefault("rid", str(_id))
41
+ props.setdefault("id", str(_id))
42
+ return {
43
+ "type": "Feature",
44
+ "geometry": {"type": "Point", "coordinates": [lon, lat]},
45
+ "properties": props,
46
+ }
47
 
48
  def add_report(lat: float, lon: float, text: str = "User report", props: dict | None = None):
49
  created_at = datetime.now(timezone.utc).isoformat()
 
54
  (float(lat), float(lon), text, props_json, created_at)
55
  )
56
  _CONN.commit()
57
+ rid = str(cur.lastrowid)
58
 
 
59
  out_props = {"type": "user_report", "text": text, "reported_at": created_at, **props}
60
  out_props.setdefault("rid", rid)
61
  out_props.setdefault("id", rid)
 
71
  feats = [_row_to_feature(r) for r in cur.fetchall()]
72
  return {"type": "FeatureCollection", "features": feats}
73
 
74
+ def find_reports_near(
75
+ lat: float,
76
+ lon: float,
77
+ radius_km: float = 10.0,
78
+ limit: int = 20,
79
+ max_age_hours: Optional[int] = None,
80
+ ) -> List[Dict[str, Any]]:
81
  params: list[Any] = []
82
  sql = "SELECT id, lat, lon, text, props_json, created_at FROM reports"
83
  if max_age_hours is not None:
 
98
  out = [_row_to_feature(r) for _, r in cand[:max(1, limit)]]
99
  return out
100
 
101
+ def clear_reports() -> dict[str, Any]:
102
  _CONN.execute("DELETE FROM reports")
103
  _CONN.commit()
104
  return {"ok": True, "message": "All reports cleared."}