Spaces:
Sleeping
Sleeping
| """ | |
| Document model for mobile app. | |
| No S3 keys - documents are stored locally on device. | |
| Backend stores metadata + extracted text for AI processing. | |
| """ | |
| from datetime import datetime | |
| from bson import ObjectId | |
| from typing import List, Optional | |
| from models import mongo | |
| class Document: | |
| """Document model for mobile app - local storage focus.""" | |
| collection_name = 'documents' | |
| def create( | |
| user_id: str, | |
| name: str, | |
| doc_type: str, | |
| original_filename: str, | |
| file_size: int, | |
| mime_type: str, | |
| has_expiry: bool = False, | |
| expiry_date: datetime = None, | |
| extracted_text: str = None, | |
| extracted_data: dict = None | |
| ) -> dict: | |
| """ | |
| Create a new document metadata entry. | |
| No S3 key - documents stored locally on mobile device. | |
| """ | |
| document = { | |
| 'user_id': ObjectId(user_id), | |
| 'name': name, | |
| 'type': doc_type, | |
| 'original_filename': original_filename, | |
| 'file_size': file_size, | |
| 'mime_type': mime_type, | |
| 'has_expiry': has_expiry, | |
| 'expiry_date': expiry_date, | |
| 'extracted_text': extracted_text, | |
| 'extracted_data': extracted_data or {}, # Key-value pairs extracted from document | |
| 'processing_status': 'completed' if extracted_text else 'pending', | |
| 'created_at': datetime.utcnow(), | |
| 'updated_at': datetime.utcnow(), | |
| } | |
| result = mongo.db.documents.insert_one(document) | |
| document['_id'] = result.inserted_id | |
| return document | |
| def find_by_id(document_id: str) -> dict | None: | |
| """Find a document by ID.""" | |
| try: | |
| return mongo.db.documents.find_one({'_id': ObjectId(document_id)}) | |
| except Exception: | |
| return None | |
| def find_by_user(user_id: str, limit: int = 100) -> List[dict]: | |
| """Find all documents for a user.""" | |
| return list(mongo.db.documents.find( | |
| {'user_id': ObjectId(user_id)} | |
| ).sort('created_at', -1).limit(limit)) | |
| def find_expiring(user_id: str = None, days: int = 7) -> List[dict]: | |
| """Find documents expiring within specified days.""" | |
| from datetime import timedelta | |
| now = datetime.utcnow() | |
| expiry_threshold = now + timedelta(days=days) | |
| query = { | |
| 'has_expiry': True, | |
| 'expiry_date': { | |
| '$gte': now, | |
| '$lte': expiry_threshold | |
| } | |
| } | |
| if user_id: | |
| query['user_id'] = ObjectId(user_id) | |
| return list(mongo.db.documents.find(query).sort('expiry_date', 1)) | |
| def find_expired(user_id: str = None) -> List[dict]: | |
| """Find documents that have already expired.""" | |
| now = datetime.utcnow() | |
| query = { | |
| 'has_expiry': True, | |
| 'expiry_date': {'$lt': now} | |
| } | |
| if user_id: | |
| query['user_id'] = ObjectId(user_id) | |
| return list(mongo.db.documents.find(query).sort('expiry_date', 1)) | |
| def count_by_user(user_id: str) -> int: | |
| """Count documents for a user.""" | |
| return mongo.db.documents.count_documents({'user_id': ObjectId(user_id)}) | |
| def count_with_expiry(user_id: str) -> int: | |
| """Count documents with expiry dates for a user.""" | |
| return mongo.db.documents.count_documents({ | |
| 'user_id': ObjectId(user_id), | |
| 'has_expiry': True | |
| }) | |
| def delete(document_id: str, user_id: str) -> bool: | |
| """Delete a document (only if user owns it).""" | |
| result = mongo.db.documents.delete_one({ | |
| '_id': ObjectId(document_id), | |
| 'user_id': ObjectId(user_id) | |
| }) | |
| return result.deleted_count > 0 | |
| def update(document_id: str, user_id: str, fields: dict) -> bool: | |
| """Update document fields.""" | |
| fields['updated_at'] = datetime.utcnow() | |
| fields.pop('user_id', None) | |
| result = mongo.db.documents.update_one( | |
| {'_id': ObjectId(document_id), 'user_id': ObjectId(user_id)}, | |
| {'$set': fields} | |
| ) | |
| return result.modified_count > 0 | |
| def update_extracted_data(document_id: str, extracted_data: dict) -> bool: | |
| """Update extracted key-value data for a document.""" | |
| result = mongo.db.documents.update_one( | |
| {'_id': ObjectId(document_id)}, | |
| {'$set': { | |
| 'extracted_data': extracted_data, | |
| 'processing_status': 'completed', | |
| 'updated_at': datetime.utcnow() | |
| }} | |
| ) | |
| return result.modified_count > 0 | |
| def get_recent(user_id: str, limit: int = 5) -> List[dict]: | |
| """Get recent documents for a user.""" | |
| return list(mongo.db.documents.find( | |
| {'user_id': ObjectId(user_id)} | |
| ).sort('created_at', -1).limit(limit)) | |
| def to_dict(doc: dict) -> dict: | |
| """Convert document to dictionary for API response.""" | |
| if not doc: | |
| return None | |
| return { | |
| 'id': str(doc['_id']), | |
| 'name': doc.get('name'), | |
| 'type': doc.get('type'), | |
| 'originalFilename': doc.get('original_filename'), | |
| 'fileSize': doc.get('file_size'), | |
| 'mimeType': doc.get('mime_type'), | |
| 'hasExpiry': doc.get('has_expiry', False), | |
| 'expiryDate': (doc.get('expiry_date').isoformat() + 'Z') if doc.get('expiry_date') else None, | |
| 'extractedData': doc.get('extracted_data', {}), | |
| 'processingStatus': doc.get('processing_status', 'completed'), | |
| 'uploadDate': (doc.get('created_at').isoformat() + 'Z') if doc.get('created_at') else None, | |
| 'createdAt': (doc.get('created_at').isoformat() + 'Z') if doc.get('created_at') else None, | |
| 'updatedAt': (doc.get('updated_at').isoformat() + 'Z') if doc.get('updated_at') else None, | |
| } | |