main.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import os
  2. import uuid
  3. from datetime import datetime
  4. from fastapi import FastAPI, UploadFile, File, Header, HTTPException, status, Form
  5. from fastapi.middleware.cors import CORSMiddleware
  6. from typing import Optional, List
  7. from backend.services.openai_service import extract_receipt_data
  8. from backend.schemas import ExtractionResponse, ClaimRecord, UserAccount, ClaimSubmission
  9. from dotenv import load_dotenv
  10. load_dotenv()
  11. app = FastAPI(title="AI-Assisted Data Entry API")
  12. # Configure CORS
  13. app.add_middleware(
  14. CORSMiddleware,
  15. allow_origins=["*"], # Adjust as needed for Angular frontend
  16. allow_credentials=True,
  17. allow_methods=["*"],
  18. allow_headers=["*"],
  19. )
  20. # In-memory database
  21. CLAIMS_DB: List[ClaimRecord] = []
  22. USERS_DB: List[UserAccount] = [
  23. UserAccount(
  24. id="demo-user-123",
  25. name="Demo User",
  26. department="Operations",
  27. medical_allowance=5000.0
  28. )
  29. ]
  30. @app.get("/health")
  31. async def health_check():
  32. return {"status": "healthy"}
  33. @app.get("/api/v1/users", response_model=List[UserAccount])
  34. async def get_users():
  35. return USERS_DB
  36. @app.post("/api/v1/users", response_model=UserAccount)
  37. async def create_user(user: UserAccount):
  38. USERS_DB.append(user)
  39. return user
  40. @app.post("/api/v1/extract", response_model=ExtractionResponse)
  41. async def extract_receipt(
  42. file: UploadFile = File(...),
  43. user_name: str = Form("Demo User"),
  44. department: str = Form("Operations")
  45. ):
  46. if not file.content_type.startswith("image/"):
  47. raise HTTPException(
  48. status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
  49. detail="File provided is not an image."
  50. )
  51. try:
  52. content = await file.read()
  53. extraction_result = await extract_receipt_data(content, user_name, department)
  54. if extraction_result is None:
  55. raise HTTPException(
  56. status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
  57. detail="Could not extract data from the provided image."
  58. )
  59. return extraction_result
  60. except Exception as e:
  61. raise HTTPException(
  62. status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
  63. detail=f"An error occurred during extraction: {str(e)}"
  64. )
  65. @app.post("/api/v1/claims", response_model=ClaimRecord)
  66. async def submit_claim(
  67. submission_data: ClaimSubmission,
  68. user_id: str = Header(...)
  69. ):
  70. # 1. Find User
  71. user = next((u for u in USERS_DB if u.id == user_id), None)
  72. if not user:
  73. raise HTTPException(status_code=404, detail="User not found")
  74. # 2. Financial Guard Logic
  75. spent_amount = submission_data.amount_spent
  76. remaining = user.medical_allowance
  77. amount_claimed = min(spent_amount, remaining)
  78. # 3. Update User Balance
  79. user.medical_allowance -= amount_claimed
  80. # 4. Save Claim
  81. claim = ClaimRecord(
  82. id=str(uuid.uuid4()),
  83. timestamp=datetime.now().isoformat(),
  84. submitted_by=user.name,
  85. department=user.department,
  86. amount_spent=spent_amount,
  87. amount_claimed=amount_claimed,
  88. provider_name=submission_data.provider_name,
  89. visit_date=submission_data.visit_date,
  90. treatment_type=submission_data.treatment_type,
  91. cost_center=submission_data.cost_center,
  92. declaration_signed=submission_data.declaration_signed,
  93. extraction_data=submission_data.extraction_data
  94. )
  95. CLAIMS_DB.append(claim)
  96. return claim
  97. @app.delete("/api/v1/claims/{claim_id}")
  98. async def delete_claim(claim_id: str):
  99. global CLAIMS_DB, USERS_DB
  100. # 1. Find the claim
  101. claim_index = next((i for i, c in enumerate(CLAIMS_DB) if c.id == claim_id), -1)
  102. if claim_index == -1:
  103. raise HTTPException(status_code=404, detail="Claim not found")
  104. deleted_claim = CLAIMS_DB[claim_index]
  105. # 2. Refund the user's allowance if user exists
  106. user = next((u for u in USERS_DB if u.name == deleted_claim.submitted_by), None)
  107. if user:
  108. user.medical_allowance += deleted_claim.amount_claimed
  109. # 3. Remove from list
  110. CLAIMS_DB.pop(claim_index)
  111. return {"status": "success", "message": "Claim deleted and allowance refunded"}
  112. @app.get("/api/v1/claims", response_model=List[ClaimRecord])
  113. async def get_claims():
  114. return CLAIMS_DB
  115. if __name__ == "__main__":
  116. import uvicorn
  117. uvicorn.run(app, host="0.0.0.0", port=8000)