ishaq101 commited on
Commit
26ee27b
·
1 Parent(s): f3bdba1

[NOTICKET] Update endpoint delete file, change behavior to marked as is_deleted=True is user delete the file in FE

Browse files
externals/databases/pg_crud.py CHANGED
@@ -184,6 +184,22 @@ async def delete_file_by_filename(
184
  return result.rowcount > 0
185
 
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  @retry_db(retries=2, delay=2)
188
  async def get_file_by_user_id(
189
  db: AsyncSession,
 
184
  return result.rowcount > 0
185
 
186
 
187
+ @retry_db(retries=2, delay=2)
188
+ async def set_file_deleted_by_filename(
189
+ db: AsyncSession,
190
+ filename: str,
191
+ user_id: UUID,
192
+ ) -> bool:
193
+ stmt = (
194
+ update(CVFile)
195
+ .where(CVFile.filename == filename, CVFile.user_id == user_id)
196
+ .values(is_deleted=True)
197
+ )
198
+ result = await db.execute(stmt)
199
+ await db.commit()
200
+ return result.rowcount > 0
201
+
202
+
203
  @retry_db(retries=2, delay=2)
204
  async def get_file_by_user_id(
205
  db: AsyncSession,
externals/databases/pg_models.py CHANGED
@@ -52,6 +52,7 @@ class CVFile(Base):
52
  filename = Column(String, nullable=False)
53
  url = Column(String, nullable=False)
54
  is_extracted = Column(BOOLEAN, nullable=False)
 
55
  uploaded_at = Column(TIMESTAMP(timezone=True), server_default=master_config.JAKARTA_NOW)
56
  date_modified = Column(TIMESTAMP(timezone=True), server_default=master_config.JAKARTA_NOW)
57
 
 
52
  filename = Column(String, nullable=False)
53
  url = Column(String, nullable=False)
54
  is_extracted = Column(BOOLEAN, nullable=False)
55
+ is_deleted = Column(BOOLEAN, nullable=False)
56
  uploaded_at = Column(TIMESTAMP(timezone=True), server_default=master_config.JAKARTA_NOW)
57
  date_modified = Column(TIMESTAMP(timezone=True), server_default=master_config.JAKARTA_NOW)
58
 
externals/storages/azure_blob.py CHANGED
@@ -88,6 +88,10 @@ async def delete_blob_by_filename(filename: str, tenant_id: str, user_id: str) -
88
  blob_client = container.get_blob_client(blob_path)
89
 
90
  try:
 
 
 
 
91
  await blob_client.delete_blob()
92
  logger.info(
93
  "azure.blob.delete.success",
 
88
  blob_client = container.get_blob_client(blob_path)
89
 
90
  try:
91
+ logger.info(
92
+ "azure.blob.delete.requested",
93
+ extra={"cv_filename": filename},
94
+ )
95
  await blob_client.delete_blob()
96
  logger.info(
97
  "azure.blob.delete.success",
interfaces/api/file.py CHANGED
@@ -97,13 +97,9 @@ async def delete_knowledge_file(
97
  user=current_user,
98
  )
99
 
100
- await knowledge_service.delete.delete(filename)
101
 
102
- return {
103
- "message": "File deleted successfully",
104
- "filename": filename,
105
- "deleted_by": current_user.email,
106
- }
107
 
108
 
109
 
 
97
  user=current_user,
98
  )
99
 
100
+ status = await knowledge_service.delete.set_deleted(filename)
101
 
102
+ return status
 
 
 
 
103
 
104
 
105
 
services/knowledge/delete_file.py CHANGED
@@ -4,6 +4,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
4
  from externals.databases.pg_crud import (
5
  get_file_by_filename,
6
  delete_file_by_filename,
 
7
  )
8
  from externals.storages.azure_blob import delete_blob_by_filename
9
  from utils.logger import get_logger
@@ -17,42 +18,119 @@ class KnowledgeDeleteService:
17
  self.user = user
18
 
19
  async def delete(self, filename: str) -> None:
20
- logger.info(
21
- "knowledge.delete.requested",
22
- extra={
23
- "cv_filename": filename,
24
- "user_id": str(self.user.user_id),
25
- "tenant_id": str(self.user.tenant_id),
26
- },
27
- )
28
-
29
- # 1️⃣ Check DB record
30
- cv_file = await get_file_by_filename(self.db,
31
- filename=filename,
32
- user_id=self.user.user_id)
33
- if not cv_file:
34
- raise HTTPException(
35
- status_code=status.HTTP_404_NOT_FOUND,
36
- detail=f"File '{filename}' not found",
37
  )
38
 
39
- # 2️⃣ Delete blob
40
- blob_deleted = await delete_blob_by_filename(filename=filename,
41
- tenant_id=self.user.tenant_id,
42
- user_id=self.user.user_id)
43
- if not blob_deleted:
44
- raise HTTPException(
45
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
46
- detail="Failed to delete blob file",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  )
48
 
49
- # 3️⃣ Delete DB record
50
- await delete_file_by_filename(self.db, filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
- logger.info(
53
- "knowledge.delete.success",
54
- extra={
55
- "cv_filename": filename,
56
- "user_id": str(self.user.user_id),
57
- },
58
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from externals.databases.pg_crud import (
5
  get_file_by_filename,
6
  delete_file_by_filename,
7
+ set_file_deleted_by_filename,
8
  )
9
  from externals.storages.azure_blob import delete_blob_by_filename
10
  from utils.logger import get_logger
 
18
  self.user = user
19
 
20
  async def delete(self, filename: str) -> None:
21
+ try:
22
+ logger.info(
23
+ "knowledge.delete.requested",
24
+ extra={
25
+ "cv_filename": filename,
26
+ "user_id": str(self.user.user_id),
27
+ "tenant_id": str(self.user.tenant_id),
28
+ },
 
 
 
 
 
 
 
 
 
29
  )
30
 
31
+ # 1️⃣ Check DB record
32
+ cv_file = await get_file_by_filename(self.db,
33
+ filename=filename,
34
+ user_id=self.user.user_id)
35
+ if not cv_file:
36
+ raise HTTPException(
37
+ status_code=status.HTTP_404_NOT_FOUND,
38
+ detail=f"File '{filename}' not found",
39
+ )
40
+
41
+ # 2️⃣ Delete blob
42
+ blob_deleted = await delete_blob_by_filename(filename=filename,
43
+ tenant_id=self.user.tenant_id,
44
+ user_id=self.user.user_id)
45
+ if not blob_deleted:
46
+ raise HTTPException(
47
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
48
+ detail="Failed to delete blob file",
49
+ )
50
+
51
+ # 3️⃣ Delete DB record
52
+ await delete_file_by_filename(self.db, filename)
53
+
54
+ logger.info(
55
+ "knowledge.delete.success",
56
+ extra={
57
+ "cv_filename": filename,
58
+ "user_id": str(self.user.user_id),
59
+ },
60
+ )
61
+ return {"status": "success",
62
+ "message": f"file '{filename}' has been deleted",
63
+ "data": {
64
+ "cv_filename": filename,
65
+ "user_id": str(self.user.user_id)}
66
+ }
67
+
68
+ except Exception as e:
69
+ logger.error(
70
+ "knowledge.delete.failed",
71
+ extra={
72
+ "cv_filename": filename,
73
+ "user_id": str(self.user.user_id),
74
+ "error": str(e),
75
+ },
76
+ )
77
+
78
+ raise HTTPException(status_code=500, detail=f"Failed to delete file '{filename}': {str(e)}")
79
+
80
+ async def set_deleted(self, filename: str) -> dict:
81
+ try:
82
+ logger.info(
83
+ "knowledge.set_deleted.requested",
84
+ extra={
85
+ "cv_filename": filename,
86
+ "user_id": str(self.user.user_id),
87
+ "tenant_id": str(self.user.tenant_id),
88
+ },
89
  )
90
 
91
+ # 1️⃣ Check DB record
92
+ cv_file = await get_file_by_filename(self.db,
93
+ filename=filename,
94
+ user_id=self.user.user_id)
95
+ if not cv_file:
96
+ raise HTTPException(
97
+ status_code=status.HTTP_404_NOT_FOUND,
98
+ detail=f"File '{filename}' not found",
99
+ )
100
+
101
+ # 2️⃣ Mark as deleted
102
+ updated = await set_file_deleted_by_filename(self.db,
103
+ filename=filename,
104
+ user_id=self.user.user_id)
105
+ if not updated:
106
+ raise HTTPException(
107
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
108
+ detail="Failed to mark file as deleted",
109
+ )
110
 
111
+ logger.info(
112
+ "knowledge.set_deleted.success",
113
+ extra={
114
+ "cv_filename": filename,
115
+ "user_id": str(self.user.user_id),
116
+ },
117
+ )
118
+ return {
119
+ "status": "success",
120
+ "message": f"File '{filename}' marked as deleted",
121
+ "data": {
122
+ "cv_filename": filename,
123
+ "user_id": str(self.user.user_id),
124
+ },
125
+ }
126
+
127
+ except Exception as e:
128
+ logger.error(
129
+ "knowledge.set_deleted.failed",
130
+ extra={
131
+ "cv_filename": filename,
132
+ "user_id": str(self.user.user_id),
133
+ "error": str(e),
134
+ },
135
+ )
136
+ raise HTTPException(status_code=500, detail=f"Failed to mark file '{filename}' as deleted: {str(e)}")