Files
GNX-WEB/gnx-react/backend/career/models.py
Iliyan Angelov d48c54e2c5 update
2025-10-07 22:10:27 +03:00

167 lines
6.6 KiB
Python

from django.db import models
from django.utils.text import slugify
from django.core.validators import FileExtensionValidator
class JobPosition(models.Model):
"""Model for job positions/openings"""
EMPLOYMENT_TYPE_CHOICES = [
('full-time', 'Full Time'),
('part-time', 'Part Time'),
('contract', 'Contract'),
('internship', 'Internship'),
('remote', 'Remote'),
]
LOCATION_TYPE_CHOICES = [
('remote', 'Remote'),
('on-site', 'On-site'),
('hybrid', 'Hybrid'),
]
STATUS_CHOICES = [
('active', 'Active'),
('closed', 'Closed'),
('draft', 'Draft'),
]
# Basic Information
title = models.CharField(max_length=255, help_text="Job title")
slug = models.SlugField(max_length=255, unique=True, blank=True)
department = models.CharField(max_length=100, blank=True, help_text="Department or category")
# Employment Details
employment_type = models.CharField(
max_length=20,
choices=EMPLOYMENT_TYPE_CHOICES,
default='full-time'
)
location_type = models.CharField(
max_length=20,
choices=LOCATION_TYPE_CHOICES,
default='remote'
)
location = models.CharField(max_length=255, default='Remote', help_text="Work location")
# Position Details
open_positions = models.PositiveIntegerField(default=1, help_text="Number of open positions")
experience_required = models.CharField(max_length=100, blank=True, help_text="e.g., 3+ years")
# Salary Information
salary_min = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
salary_max = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
salary_currency = models.CharField(max_length=10, default='USD')
salary_period = models.CharField(max_length=20, default='per month', help_text="e.g., per month, per year")
salary_additional = models.TextField(blank=True, help_text="Additional salary info like bonuses, benefits")
# Job Description
short_description = models.TextField(blank=True, help_text="Brief description for listing page")
about_role = models.TextField(blank=True, help_text="About this role / Who we are")
requirements = models.JSONField(default=list, blank=True, help_text="List of requirements")
responsibilities = models.JSONField(default=list, blank=True, help_text="List of responsibilities")
qualifications = models.JSONField(default=list, blank=True, help_text="List of qualifications")
bonus_points = models.JSONField(default=list, blank=True, help_text="Nice to have skills")
benefits = models.JSONField(default=list, blank=True, help_text="What you get")
# Dates and Status
start_date = models.CharField(max_length=100, default='ASAP', help_text="Expected start date")
posted_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
deadline = models.DateTimeField(null=True, blank=True, help_text="Application deadline")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
# SEO and Metadata
featured = models.BooleanField(default=False, help_text="Feature this job on homepage")
priority = models.IntegerField(default=0, help_text="Higher number = higher priority in listing")
class Meta:
ordering = ['-priority', '-posted_date']
verbose_name = 'Job Position'
verbose_name_plural = 'Job Positions'
def __str__(self):
return f"{self.title} ({self.open_positions} positions)"
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
# Ensure unique slug
original_slug = self.slug
counter = 1
while JobPosition.objects.filter(slug=self.slug).exists():
self.slug = f"{original_slug}-{counter}"
counter += 1
super().save(*args, **kwargs)
class JobApplication(models.Model):
"""Model for job applications"""
STATUS_CHOICES = [
('new', 'New'),
('reviewing', 'Reviewing'),
('shortlisted', 'Shortlisted'),
('interviewed', 'Interviewed'),
('accepted', 'Accepted'),
('rejected', 'Rejected'),
]
# Related Job
job = models.ForeignKey(JobPosition, on_delete=models.CASCADE, related_name='applications')
# Applicant Information
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
phone = models.CharField(max_length=20, blank=True)
# Professional Information
current_position = models.CharField(max_length=255, blank=True, help_text="Current job title")
current_company = models.CharField(max_length=255, blank=True)
years_of_experience = models.CharField(max_length=50, blank=True)
# Application Details
cover_letter = models.TextField(blank=True, help_text="Cover letter or message")
resume = models.FileField(
upload_to='career/resumes/%Y/%m/',
validators=[FileExtensionValidator(allowed_extensions=['pdf', 'doc', 'docx'])],
help_text="Upload your resume (PDF, DOC, DOCX)"
)
portfolio_url = models.URLField(blank=True, help_text="Link to portfolio or LinkedIn")
# Additional Information
linkedin_url = models.URLField(blank=True)
github_url = models.URLField(blank=True)
website_url = models.URLField(blank=True)
# Availability
available_from = models.DateField(null=True, blank=True, help_text="When can you start?")
notice_period = models.CharField(max_length=100, blank=True, help_text="Notice period if applicable")
# Salary Expectations
expected_salary = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
salary_currency = models.CharField(max_length=10, default='USD')
# Application Metadata
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='new')
applied_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
notes = models.TextField(blank=True, help_text="Internal notes (not visible to applicant)")
# Privacy
consent = models.BooleanField(default=False, help_text="Consent to data processing")
class Meta:
ordering = ['-applied_date']
verbose_name = 'Job Application'
verbose_name_plural = 'Job Applications'
def __str__(self):
return f"{self.first_name} {self.last_name} - {self.job.title}"
@property
def full_name(self):
return f"{self.first_name} {self.last_name}"