Skip to content

Commit e974bb1

Browse files
committed
feat: handle updated attachment for already sent notices
1 parent ff07a80 commit e974bb1

File tree

2 files changed

+61
-22
lines changed

2 files changed

+61
-22
lines changed

mftp/db.py

+51-17
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from pymongo import MongoClient
44
from pymongo.database import Database
55
from pymongo.collection import Collection
6-
from typing import Any, Dict, List, Optional
76
from pymongo.errors import ConnectionFailure
7+
from typing import Any, Dict, List, Optional, Tuple
88

99

1010
class NoticeDB:
@@ -87,21 +87,46 @@ def delete_successful_ntfy_subscribers(self, notice_uid: str) -> None:
8787

8888
# Update the document to set the subscribers list to an empty list
8989
collection.delete_one({"uid": uid})
90-
91-
def find_new_notices(self, uid_list: List[str]) -> List[str]:
92-
"""Find and return the list of UIDs that have not been sent."""
93-
# Query for UIDs that exist in the database
94-
query = {"UID": {"$in": uid_list}}
95-
sent_notices = self.__find_many(query, {"UID": 1})
96-
97-
# Extract UIDs that are already sent
98-
sent_uids = set()
99-
if sent_notices:
100-
sent_uids = {notice["UID"] for notice in sent_notices}
101-
102-
# Return UIDs that are not sent
103-
return [uid for uid in uid_list if uid not in sent_uids]
10490

91+
def find_to_send_notices(self, latest_X_notices: List[Dict[str, str]]) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]:
92+
"""Find new and modified notices compared to existing records in the database."""
93+
# Check if latest_X_notices is empty
94+
if not latest_X_notices:
95+
return [], []
96+
97+
# Prepare a query to match all notices
98+
latest_X_uids = [notice['UID'] for notice in latest_X_notices]
99+
query = {"UID": {"$in": latest_X_uids}}
100+
101+
# Find all existing notices that match any of the criteria
102+
existing_notices = self.__find_many(query)
103+
if not existing_notices:
104+
return latest_X_notices, []
105+
106+
# Create a mapping of existing notices by UID
107+
existing_notices_map = {notice['UID']: notice for notice in existing_notices}
108+
109+
new_notices, modified_notices = [], []
110+
for latest_notice in latest_X_notices:
111+
uid = latest_notice.get('UID')
112+
113+
if uid not in existing_notices_map:
114+
# New notice
115+
new_notices.append(latest_notice)
116+
else:
117+
# Check if the notice is modified
118+
existing_notice = existing_notices_map[uid]
119+
is_modified = any(
120+
existing_notice.get(key) != value
121+
for key, value in latest_notice.items()
122+
if key != 'BodyData'
123+
)
124+
125+
if is_modified:
126+
modified_notices.append(latest_notice)
127+
128+
return new_notices, modified_notices
129+
105130
def save_notice(self, document: Dict) -> str:
106131
return self.__insert_one(document)
107132

@@ -115,8 +140,17 @@ def __get_collection(self) -> Collection:
115140
def __insert_one(self, document: Dict) -> str:
116141
"""Insert single document and return inserted ID."""
117142
collection = self.__get_collection()
118-
result = collection.insert_one(document)
119-
return str(result.inserted_id)
143+
144+
uid = document.get('UID')
145+
# Use replace_one with upsert=True to overwrite or insert
146+
result = collection.replace_one(
147+
{"UID": uid}, # Match criteria
148+
document, # New document to replace with
149+
upsert=True # Insert if not exists
150+
)
151+
152+
# Return the ID of the document
153+
return str(result.upserted_id if result.upserted_id else uid)
120154

121155
# Read operations
122156
def __find_many(self, query: Optional[Dict] = None, projection: Optional[Dict] = None) -> Optional[List]:

mftp/notice.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def fetch(headers, session, ssoToken, notice_db):
2525
logging.error(f" Failed to extract data from Noticeboard ~ {str(e)}")
2626
return []
2727

28-
latest_notices = []
28+
latest_X_notices = []
2929
for i, row in enumerate(root.findall('row')):
3030
if i >= LAST_NOTICES_CHECK_COUNT:
3131
break
@@ -57,18 +57,23 @@ def fetch(headers, session, ssoToken, notice_db):
5757
logging.error(f" Failed to parse mail attachment ~ {str(e)}")
5858
break
5959

60-
latest_notices.append(notice)
60+
latest_X_notices.append(notice)
6161

6262
# This is done to reduce DB queries
6363
# Get all first X notices from ERP in latest_notices
6464
# Check if these notices exist in the DB using their UIDs in a single query
6565
# Get new notice uids, filter out new notices from latest_notices based on uids
66-
new_notice_uids = notice_db.find_new_notices([notice['UID'] for notice in latest_notices])
67-
new_notices = [notice for notice in latest_notices if notice['UID'] in new_notice_uids]
66+
new_notices, modified_notices = notice_db.find_to_send_notices(latest_X_notices)
67+
68+
# Log new notices
6869
for notice in new_notices:
6970
logging.info(f" [NEW NOTICE]: #{notice['UID'].split('_')[0]} | {notice['Type']} | {notice['Subject']} | {notice['Company']} | {notice['Time']}")
7071

71-
return new_notices
72+
# Log modified notices
73+
for notice in modified_notices:
74+
logging.info(f" [MODIFIED NOTICE]: #{notice['UID'].split('_')[0]} | {notice['Type']} | {notice['Subject']} | {notice['Company']} | {notice['Time']}")
75+
76+
return new_notices + modified_notices
7277

7378

7479
def parse_body_data(session, year, id_):

0 commit comments

Comments
 (0)