Skip to content

Commit 294d52a

Browse files
authored
Merge pull request #420 from rrvrs/issue-379
console errors fix
2 parents ec48093 + cebc2b3 commit 294d52a

File tree

12 files changed

+270
-82
lines changed

12 files changed

+270
-82
lines changed

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ help:
99
@echo "Available targets:"
1010
@echo " setup Run the setup script to configure the project"
1111
@echo " run-dev Setup and start the development server (with graceful shutdown)"
12-
@echo " run-prod Build the project for production"
12+
@echo " build-prod Build the project for production"
13+
@echo " start-prod Start the production server (after building)"
14+
@echo " run-prod Build and start the production server"
1315
@echo " clean Clean up generated artifacts"
1416

1517
setup:
@@ -20,10 +22,18 @@ run-dev:
2022
@echo "🚀 Starting development server…"
2123
@bash -c 'trap "echo "\n🛑 Development server stopped"; exit 0" SIGINT; npm run dev'
2224

23-
run-prod:
25+
build-prod:
2426
@echo "📦 Building for production…"
2527
@npm run build
2628

29+
start-prod:
30+
@echo "🚀 Starting production server…"
31+
@bash -c 'trap "echo "\n🛑 Production server stopped"; exit 0" SIGINT; npm run start'
32+
33+
run-prod: build-prod
34+
@echo "🚀 Starting production server…"
35+
@bash -c 'trap "echo "\n🛑 Production server stopped"; exit 0" SIGINT; npm run start'
36+
2737
clean:
2838
@echo "🧹 Cleaning artifacts…"
2939
# Add commands to clean build and temp files, e.g.:

apps/backend/app/api/router/v1/resume.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
ScoreImprovementService,
2222
ResumeNotFoundError,
2323
ResumeParsingError,
24+
ResumeValidationError,
2425
JobNotFoundError,
26+
JobParsingError,
27+
ResumeKeywordExtractionError,
28+
JobKeywordExtractionError,
2529
)
2630
from app.schemas.pydantic import ResumeImprovementRequest
2731

@@ -72,6 +76,12 @@ async def upload_resume(
7276
filename=file.filename,
7377
content_type="md",
7478
)
79+
except ResumeValidationError as e:
80+
logger.warning(f"Resume validation failed: {str(e)}")
81+
raise HTTPException(
82+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
83+
detail=str(e),
84+
)
7585
except Exception as e:
7686
logger.error(
7787
f"Error processing file: {str(e)} - traceback: {traceback.format_exc()}"
@@ -163,6 +173,24 @@ async def score_and_improve(
163173
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
164174
detail=str(e),
165175
)
176+
except JobParsingError as e:
177+
logger.error(str(e))
178+
raise HTTPException(
179+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
180+
detail=str(e),
181+
)
182+
except ResumeKeywordExtractionError as e:
183+
logger.warning(str(e))
184+
raise HTTPException(
185+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
186+
detail=str(e),
187+
)
188+
except JobKeywordExtractionError as e:
189+
logger.warning(str(e))
190+
raise HTTPException(
191+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
192+
detail=str(e),
193+
)
166194
except Exception as e:
167195
logger.error(f"Error: {str(e)} - traceback: {traceback.format_exc()}")
168196
raise HTTPException(

apps/backend/app/schemas/json/resume_preview.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"linkedin": "string | null",
1010
"github": "string | null",
1111
},
12-
"summary": "string",
12+
"summary": "string | null",
1313
"experience": [
1414
{
1515
"id": 0,
@@ -25,8 +25,8 @@
2525
"id": 0,
2626
"institution": "string",
2727
"degree": "string",
28-
"years": "string",
29-
"description": "string",
28+
"years": "string | null",
29+
"description": "string | null",
3030
}
3131
],
3232
"skills": ["string"],

apps/backend/app/schemas/json/structured_resume.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,19 @@
3333
"Skills": [{"category": "string", "skillName": "string"}],
3434
"Research Work": [
3535
{
36-
"title": "string",
37-
"publication": "string",
38-
"date": "YYYY-MM-DD",
39-
"link": "string",
40-
"description": "string",
36+
"title": "string | null",
37+
"publication": "string | null",
38+
"date": "YYYY-MM-DD | null",
39+
"link": "string | null",
40+
"description": "string | null",
4141
}
4242
],
4343
"Achievements": ["string", "..."],
4444
"Education": [
4545
{
4646
"institution": "string",
4747
"degree": "string",
48-
"fieldOfStudy": "string",
48+
"fieldOfStudy": "string | null",
4949
"startDate": "YYYY-MM-DD",
5050
"endDate": "YYYY-MM-DD",
5151
"grade": "string",

apps/backend/app/schemas/pydantic/resume_preview.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ class EducationItem(BaseModel):
2626
id: int
2727
institution: str
2828
degree: str
29-
years: str
29+
years: Optional[str] = None
3030
description: Optional[str] = None
3131

3232

3333
class ResumePreviewerModel(BaseModel):
3434
personalInfo: PersonalInfo
35-
summary: str
35+
summary: Optional[str] = None
3636
experience: List[ExperienceItem]
3737
education: List[EducationItem]
3838
skills: List[str]

apps/backend/app/schemas/pydantic/structured_job.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class RemoteStatusEnum(str, enum.Enum):
3636
ON_SITE = "On-site"
3737
REMOTE = "Remote"
3838
NOT_SPECIFIED = "Not Specified"
39+
MULTIPLE_LOCATIONS = "Multiple Locations"
3940

4041
@classmethod
4142
def _missing_(cls, value: object):

apps/backend/app/schemas/pydantic/structured_resume.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ class Skill(BaseModel):
4444

4545

4646
class ResearchWork(BaseModel):
47-
title: str
48-
publication: str
49-
date: str
47+
title: Optional[str] = None
48+
publication: Optional[str] = None
49+
date: Optional[str] = None
5050
link: Optional[str] = None
5151
description: Optional[str] = None
5252

5353

5454
class Education(BaseModel):
5555
institution: str
5656
degree: str
57-
field_of_study: str = Field(..., alias="fieldOfStudy")
57+
field_of_study: Optional[str] = Field(None, alias="fieldOfStudy")
5858
start_date: str = Field(..., alias="startDate")
5959
end_date: str = Field(..., alias="endDate")
6060
grade: Optional[str] = None

apps/backend/app/services/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
from .exceptions import (
55
ResumeNotFoundError,
66
ResumeParsingError,
7+
ResumeValidationError,
78
JobNotFoundError,
89
JobParsingError,
10+
ResumeKeywordExtractionError,
11+
JobKeywordExtractionError,
912
)
1013

1114
__all__ = [
@@ -15,5 +18,8 @@
1518
"JobNotFoundError",
1619
"ResumeParsingError",
1720
"ResumeNotFoundError",
21+
"ResumeValidationError",
22+
"ResumeKeywordExtractionError",
23+
"JobKeywordExtractionError",
1824
"ScoreImprovementService",
1925
]

apps/backend/app/services/exceptions.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,29 @@ def __init__(self, job_id: Optional[str] = None, message: Optional[str] = None):
2929
self.job_id = job_id
3030

3131

32-
class EmbeddingError(Exception):
32+
class ResumeValidationError(Exception):
3333
"""
34-
Exception raised when there is an error in embedding.
34+
Exception raised when structured resume validation fails.
3535
"""
3636

37-
def __init__(self, message: str = None):
37+
def __init__(
38+
self,
39+
resume_id: Optional[str] = None,
40+
validation_error: Optional[str] = None,
41+
message: Optional[str] = None,
42+
):
43+
if message:
44+
# we can use custom message if provided
45+
pass
46+
elif validation_error:
47+
message = f"Resume parsing failed: {validation_error}. Please ensure your resume contains all required information with proper formatting."
48+
elif resume_id:
49+
message = f"Resume with ID {resume_id} failed validation during structured parsing."
50+
else:
51+
message = "Resume validation failed during structured parsing."
3852
super().__init__(message)
39-
self.message = message
53+
self.resume_id = resume_id
54+
self.validation_error = validation_error
4055

4156

4257
class ResumeParsingError(Exception):
@@ -64,4 +79,32 @@ def __init__(self, job_id: Optional[str] = None, message: Optional[str] = None):
6479
elif not message:
6580
message = "Parsed job not found."
6681
super().__init__(message)
67-
self.resume_id = job_id
82+
self.job_id = job_id
83+
84+
85+
class ResumeKeywordExtractionError(Exception):
86+
"""
87+
Exception raised when keyword extraction from resume failed or no keywords were extracted.
88+
"""
89+
90+
def __init__(self, resume_id: Optional[str] = None, message: Optional[str] = None):
91+
if resume_id and not message:
92+
message = f"Keyword extraction failed for resume with ID {resume_id}. Cannot proceed with resume improvement without extracted keywords."
93+
elif not message:
94+
message = "Resume keyword extraction failed. Cannot improve resume without keywords."
95+
super().__init__(message)
96+
self.resume_id = resume_id
97+
98+
99+
class JobKeywordExtractionError(Exception):
100+
"""
101+
Exception raised when keyword extraction from job failed or no keywords were extracted.
102+
"""
103+
104+
def __init__(self, job_id: Optional[str] = None, message: Optional[str] = None):
105+
if job_id and not message:
106+
message = f"Keyword extraction failed for job with ID {job_id}. Cannot proceed with resume improvement without job keywords."
107+
elif not message:
108+
message = "Job keyword extraction failed. Cannot improve resume without job requirements."
109+
super().__init__(message)
110+
self.job_id = job_id

0 commit comments

Comments
 (0)