This commit is contained in:
Iliyan Angelov
2025-11-24 08:18:18 +02:00
parent 366f28677a
commit 136f75a859
133 changed files with 14977 additions and 3350 deletions

View File

@@ -1,11 +1,49 @@
from django.core.mail import EmailMultiAlternatives
from django.core.mail import EmailMultiAlternatives, get_connection
from django.template.loader import render_to_string
from django.conf import settings
import logging
import time
logger = logging.getLogger(__name__)
def _send_email_with_retry(email_message, max_retries: int = 3, delay: float = 1.0) -> bool:
"""
Send email with retry logic for production reliability.
Uses Django settings from .env file.
Args:
email_message: EmailMultiAlternatives instance
max_retries: Maximum number of retry attempts
delay: Delay between retries in seconds
Returns:
bool: True if email was sent successfully, False otherwise
"""
for attempt in range(max_retries + 1):
try:
# Test connection before sending (uses EMAIL_BACKEND from settings)
connection = get_connection()
connection.open()
connection.close()
# Send the email (uses EMAIL_BACKEND and credentials from settings)
email_message.send()
return True
except Exception as e:
logger.warning(f"Email send attempt {attempt + 1} failed: {str(e)}")
if attempt < max_retries:
time.sleep(delay * (2 ** attempt)) # Exponential backoff
continue
else:
logger.error(f"Failed to send email after {max_retries + 1} attempts: {str(e)}")
return False
return False
class CareerEmailService:
"""Service for handling career-related emails"""
@@ -24,26 +62,31 @@ class CareerEmailService:
'job_title': application.job.title,
'job_location': application.job.location,
'application_date': application.applied_date,
'logo_url': f'{settings.SITE_URL}/images/logo.png',
'site_url': settings.SITE_URL,
}
# Render email templates
text_content = render_to_string('career/application_confirmation.txt', context)
html_content = render_to_string('career/application_confirmation.html', context)
# Create email
# Create email (uses DEFAULT_FROM_EMAIL from settings)
email = EmailMultiAlternatives(
subject=subject,
body=text_content,
from_email=from_email,
from_email=from_email, # Uses settings.DEFAULT_FROM_EMAIL
to=to_email
)
email.attach_alternative(html_content, "text/html")
# Send email
email.send(fail_silently=False)
# Send email with retry logic (uses EMAIL_BACKEND and credentials from settings)
success = _send_email_with_retry(email)
logger.info(f"Confirmation email sent to {application.email}")
return True
if success:
logger.info(f"Confirmation email sent to {application.email}")
else:
logger.error(f"Failed to send confirmation email to {application.email} after retries")
return success
except Exception as e:
logger.error(f"Failed to send confirmation email: {str(e)}", exc_info=True)
@@ -78,18 +121,20 @@ class CareerEmailService:
'notice_period': application.notice_period,
'application_date': application.applied_date,
'resume_url': application.resume.url if application.resume else None,
'logo_url': f'{settings.SITE_URL}/images/logo.png',
'site_url': settings.SITE_URL,
}
# Render email templates
text_content = render_to_string('career/application_notification.txt', context)
html_content = render_to_string('career/application_notification.html', context)
# Create email
# Create email (uses DEFAULT_FROM_EMAIL and COMPANY_EMAIL from settings)
email = EmailMultiAlternatives(
subject=subject,
body=text_content,
from_email=from_email,
to=to_email,
from_email=from_email, # Uses settings.DEFAULT_FROM_EMAIL
to=to_email, # Uses settings.COMPANY_EMAIL
reply_to=[application.email]
)
email.attach_alternative(html_content, "text/html")
@@ -98,11 +143,14 @@ class CareerEmailService:
if application.resume:
email.attach_file(application.resume.path)
# Send email
email.send(fail_silently=False)
# Send email with retry logic (uses EMAIL_BACKEND and credentials from settings)
success = _send_email_with_retry(email)
logger.info(f"Admin notification email sent for application from {application.email}")
return True
if success:
logger.info(f"Admin notification email sent for application from {application.email}")
else:
logger.error(f"Failed to send admin notification email for application from {application.email} after retries")
return success
except Exception as e:
logger.error(f"Failed to send admin notification email: {str(e)}", exc_info=True)

View File

@@ -0,0 +1,676 @@
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils import timezone
from datetime import timedelta
from career.models import JobPosition
class Command(BaseCommand):
help = 'Populate database with European job positions only'
def add_arguments(self, parser):
parser.add_argument(
'--delete-old',
action='store_true',
help='Delete all existing job positions before populating',
)
def handle(self, *args, **kwargs):
delete_old = kwargs.get('delete_old', False)
self.stdout.write(self.style.SUCCESS('Starting to populate European job positions...'))
with transaction.atomic():
# Delete old data if requested
if delete_old:
self.delete_old_data()
# Create European Job Positions
self.create_european_jobs()
self.stdout.write(self.style.SUCCESS('\n✓ Successfully populated European job positions!'))
self.stdout.write(f' - Total positions: {JobPosition.objects.count()}')
def delete_old_data(self):
"""Delete all existing job positions"""
self.stdout.write(self.style.WARNING('Deleting old job positions...'))
jobs_count = JobPosition.objects.count()
JobPosition.objects.all().delete()
self.stdout.write(f' ✓ Deleted {jobs_count} job positions')
self.stdout.write(self.style.SUCCESS('Old data deleted successfully!'))
def create_european_jobs(self):
"""Create European job positions"""
self.stdout.write('Creating European job positions...')
jobs_data = [
{
'title': 'Senior Full Stack Developer',
'department': 'Engineering',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'London, UK',
'open_positions': 2,
'experience_required': '5+ years',
'salary_min': 60000,
'salary_max': 85000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Annual bonus + Stock options + Private health insurance',
'short_description': 'Build scalable applications with cutting-edge technologies in our London office.',
'about_role': 'We are seeking an experienced Full Stack Developer to join our engineering team in London. You will be responsible for developing and maintaining our web applications using modern technologies and best practices. This is an exciting opportunity to work with a talented team on innovative projects.',
'requirements': [
'5+ years of full-stack development experience',
'Strong proficiency in React, Next.js, and TypeScript',
'Experience with Python/Django or Node.js',
'Solid understanding of RESTful APIs and GraphQL',
'Experience with PostgreSQL and Redis',
'Familiarity with AWS cloud services',
'Right to work in the UK',
],
'responsibilities': [
'Develop and maintain web applications',
'Write clean, maintainable, and efficient code',
'Participate in code reviews and pair programming',
'Collaborate with cross-functional teams',
'Optimize applications for performance and scalability',
'Mentor junior developers',
'Contribute to technical decision-making',
],
'qualifications': [
'Bachelor\'s degree in Computer Science or related field',
'Strong problem-solving and analytical skills',
'Experience with version control (Git)',
'Good understanding of software development lifecycle',
'Excellent communication skills in English',
],
'bonus_points': [
'Experience with Docker and Kubernetes',
'Knowledge of CI/CD pipelines (GitLab CI, GitHub Actions)',
'Contributions to open-source projects',
'Experience with microservices architecture',
'Knowledge of test-driven development',
],
'benefits': [
'Competitive salary with stock options',
'Hybrid work model (3 days office, 2 days remote)',
'Latest MacBook Pro or custom PC',
'Learning and development budget (€2,000/year)',
'Private health insurance (Bupa)',
'Gym membership',
'25 days annual leave + bank holidays',
'Pension contribution matching',
],
'start_date': 'Within 1 month',
'status': 'active',
'featured': True,
'priority': 10,
},
{
'title': 'Frontend Developer',
'department': 'Engineering',
'employment_type': 'full-time',
'location_type': 'remote',
'location': 'Remote (Europe)',
'open_positions': 3,
'experience_required': '3+ years',
'salary_min': 45000,
'salary_max': 65000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Performance bonus + Remote work allowance',
'short_description': 'Create beautiful and performant user interfaces for our web applications.',
'about_role': 'We are looking for a talented Frontend Developer to join our distributed team across Europe. You will work on building modern, responsive web applications using React and Next.js. This is a fully remote position, but we have offices in major European cities if you prefer hybrid work.',
'requirements': [
'3+ years of frontend development experience',
'Strong proficiency in React, Next.js, and TypeScript',
'Experience with CSS-in-JS or Tailwind CSS',
'Understanding of responsive design principles',
'Experience with state management (Redux, Zustand)',
'Knowledge of modern JavaScript (ES6+)',
'Must be based in Europe',
],
'responsibilities': [
'Develop responsive and accessible user interfaces',
'Implement design systems and component libraries',
'Optimize applications for performance',
'Write unit and integration tests',
'Collaborate with designers and backend developers',
'Participate in code reviews',
],
'qualifications': [
'Portfolio demonstrating strong frontend skills',
'Experience with version control (Git)',
'Understanding of web accessibility standards (WCAG)',
'Good communication skills in English',
],
'bonus_points': [
'Experience with Storybook',
'Knowledge of animation libraries (Framer Motion)',
'Experience with GraphQL',
'Understanding of SEO best practices',
'Experience with testing frameworks (Jest, React Testing Library)',
],
'benefits': [
'Fully remote work (within Europe)',
'Competitive salary package',
'Remote work allowance (€500/month)',
'Learning and development budget',
'Latest MacBook Pro',
'Health insurance contribution',
'Flexible working hours',
'30 days annual leave',
],
'start_date': 'ASAP',
'status': 'active',
'featured': True,
'priority': 9,
},
{
'title': 'Backend Developer (Python/Django)',
'department': 'Engineering',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Berlin, Germany',
'open_positions': 2,
'experience_required': '4+ years',
'salary_min': 55000,
'salary_max': 75000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ 13th month salary + Annual bonus',
'short_description': 'Build robust backend systems and APIs using Python and Django.',
'about_role': 'We are seeking a Backend Developer to join our engineering team in Berlin. You will work on developing scalable backend systems, RESTful APIs, and microservices using Python and Django. This is an excellent opportunity to work with modern technologies in a dynamic startup environment.',
'requirements': [
'4+ years of backend development experience',
'Strong proficiency in Python and Django',
'Experience with PostgreSQL and database optimization',
'Understanding of RESTful API design',
'Experience with Redis for caching',
'Knowledge of Docker and containerization',
'Right to work in Germany',
],
'responsibilities': [
'Design and develop backend APIs',
'Optimize database queries and performance',
'Implement authentication and authorization',
'Write comprehensive tests',
'Participate in architecture decisions',
'Collaborate with frontend and DevOps teams',
],
'qualifications': [
'Bachelor\'s degree in Computer Science or related field',
'Strong problem-solving skills',
'Experience with Git and version control',
'Good understanding of software engineering principles',
'Good communication skills in English (German is a plus)',
],
'bonus_points': [
'Experience with Celery and async task processing',
'Knowledge of GraphQL',
'Experience with AWS services',
'Understanding of microservices architecture',
'Experience with Elasticsearch',
],
'benefits': [
'Competitive salary with 13th month',
'Hybrid work model',
'Latest development equipment',
'Learning budget (€1,500/year)',
'Public transport ticket (BVG)',
'Health insurance contribution',
'30 days annual leave',
'German language courses',
],
'start_date': 'Within 1 month',
'status': 'active',
'featured': False,
'priority': 8,
},
{
'title': 'DevOps Engineer',
'department': 'Engineering',
'employment_type': 'full-time',
'location_type': 'remote',
'location': 'Remote (Europe)',
'open_positions': 1,
'experience_required': '4+ years',
'salary_min': 60000,
'salary_max': 80000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Annual bonus + Equipment budget',
'short_description': 'Build and maintain our cloud infrastructure and CI/CD pipelines.',
'about_role': 'We are looking for a DevOps Engineer to join our infrastructure team. You will be responsible for managing our cloud infrastructure, implementing CI/CD pipelines, and ensuring high availability of our services. This is a fully remote position open to candidates across Europe.',
'requirements': [
'4+ years of DevOps or infrastructure experience',
'Strong experience with AWS cloud services',
'Proficiency with Docker and Kubernetes',
'Experience with CI/CD tools (GitLab CI, GitHub Actions)',
'Knowledge of Infrastructure as Code (Terraform, CloudFormation)',
'Experience with monitoring tools (Prometheus, Grafana)',
'Must be based in Europe',
],
'responsibilities': [
'Manage and optimize cloud infrastructure',
'Design and implement CI/CD pipelines',
'Monitor system performance and availability',
'Implement security best practices',
'Automate deployment and scaling processes',
'Troubleshoot infrastructure issues',
],
'qualifications': [
'Strong Linux/Unix administration skills',
'Experience with scripting (Bash, Python)',
'Understanding of networking and security',
'Good problem-solving abilities',
'Excellent communication skills in English',
],
'bonus_points': [
'Experience with GitOps (ArgoCD, Flux)',
'Knowledge of service mesh (Istio)',
'Experience with multi-cloud environments',
'Certifications (AWS, Kubernetes)',
'Experience with observability tools (Datadog, New Relic)',
],
'benefits': [
'Fully remote work',
'Competitive salary package',
'Equipment budget (€3,000)',
'Learning and certification budget',
'Health insurance contribution',
'Flexible working hours',
'30 days annual leave',
],
'start_date': 'ASAP',
'status': 'active',
'featured': True,
'priority': 9,
},
{
'title': 'UI/UX Designer',
'department': 'Design',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Amsterdam, Netherlands',
'open_positions': 1,
'experience_required': '3+ years',
'salary_min': 45000,
'salary_max': 60000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ 8% holiday allowance + Annual bonus',
'short_description': 'Create beautiful and intuitive user experiences for our products.',
'about_role': 'We are looking for a talented UI/UX Designer to join our design team in Amsterdam. You will work closely with product managers and engineers to design user-friendly interfaces for our web and mobile applications. This role offers the opportunity to shape the user experience of our products.',
'requirements': [
'3+ years of UI/UX design experience',
'Strong portfolio showcasing web and mobile projects',
'Proficiency in Figma or Sketch',
'Understanding of user-centered design principles',
'Experience with user research and usability testing',
'Fluent English (Dutch is a plus)',
'Right to work in the Netherlands',
],
'responsibilities': [
'Create wireframes, prototypes, and high-fidelity designs',
'Conduct user research and usability testing',
'Collaborate with developers to implement designs',
'Maintain and evolve design systems',
'Present design concepts to stakeholders',
'Iterate on designs based on user feedback',
],
'qualifications': [
'Portfolio demonstrating strong UI/UX design skills',
'Experience with design systems',
'Knowledge of HTML/CSS basics',
'Understanding of accessibility standards (WCAG)',
'Strong communication and presentation skills',
],
'bonus_points': [
'Experience with motion design and animation',
'Knowledge of front-end development',
'Illustration skills',
'Experience with design tokens',
'Experience with user analytics tools',
],
'benefits': [
'Hybrid work model',
'Competitive salary with 8% holiday allowance',
'Latest design tools and software',
'Learning and development budget',
'Health insurance contribution',
'Public transport card',
'25 days annual leave',
'Pension contribution',
],
'start_date': 'ASAP',
'status': 'active',
'featured': False,
'priority': 7,
},
{
'title': 'Product Manager',
'department': 'Product',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Paris, France',
'open_positions': 1,
'experience_required': '5+ years',
'salary_min': 65000,
'salary_max': 85000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Annual bonus + Stock options',
'short_description': 'Lead product strategy and development for our flagship products.',
'about_role': 'We are looking for an experienced Product Manager to drive the vision and execution of our products from our Paris office. You will work closely with engineering, design, and marketing teams to deliver exceptional products that delight our customers. This role requires strong leadership and strategic thinking.',
'requirements': [
'5+ years of product management experience',
'Proven track record of successful product launches',
'Strong understanding of agile methodologies',
'Excellent communication and leadership skills',
'Data-driven decision-making approach',
'Experience with product analytics tools',
'Right to work in France',
],
'responsibilities': [
'Define product vision and strategy',
'Create and maintain product roadmap',
'Gather and prioritize requirements',
'Work with engineering team on implementation',
'Conduct market research and competitive analysis',
'Analyze product metrics and user feedback',
'Coordinate with stakeholders across the organization',
],
'qualifications': [
'Bachelor\'s degree (MBA preferred)',
'Strong analytical and problem-solving skills',
'Experience with product management tools (Jira, Productboard)',
'Understanding of UX principles',
'Fluent English (French is a plus)',
],
'bonus_points': [
'Technical background',
'Experience in SaaS products',
'Knowledge of growth strategies',
'Experience with A/B testing',
'Understanding of API design',
],
'benefits': [
'Competitive salary with equity',
'Hybrid work model',
'Professional development budget',
'Health and wellness benefits',
'Public transport pass',
'Lunch vouchers',
'30 days annual leave + RTT',
'Team offsites and events',
],
'start_date': 'Within 1 month',
'status': 'active',
'featured': True,
'priority': 8,
},
{
'title': 'Data Engineer',
'department': 'Data',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Barcelona, Spain',
'open_positions': 1,
'experience_required': '4+ years',
'salary_min': 50000,
'salary_max': 70000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Annual bonus + Flexible benefits',
'short_description': 'Build and maintain data pipelines and infrastructure.',
'about_role': 'We are seeking a Data Engineer to join our data team in Barcelona. You will be responsible for designing, building, and maintaining data pipelines, data warehouses, and ETL processes. This role offers the opportunity to work with large-scale data systems and modern data technologies.',
'requirements': [
'4+ years of data engineering experience',
'Strong proficiency in Python',
'Experience with SQL and database design',
'Knowledge of data pipeline tools (Airflow, Luigi)',
'Experience with cloud data warehouses (Snowflake, BigQuery, Redshift)',
'Understanding of ETL/ELT processes',
'Right to work in Spain',
],
'responsibilities': [
'Design and build data pipelines',
'Maintain data warehouse infrastructure',
'Optimize data processing performance',
'Ensure data quality and reliability',
'Collaborate with data analysts and scientists',
'Document data processes and architecture',
],
'qualifications': [
'Bachelor\'s degree in Computer Science or related field',
'Strong problem-solving skills',
'Experience with version control (Git)',
'Understanding of data modeling concepts',
'Good communication skills in English (Spanish is a plus)',
],
'bonus_points': [
'Experience with Apache Spark',
'Knowledge of real-time data processing (Kafka)',
'Experience with dbt',
'Understanding of data governance',
'Experience with machine learning pipelines',
],
'benefits': [
'Hybrid work model',
'Competitive salary package',
'Learning and development budget',
'Health insurance',
'Flexible working hours',
'Public transport card',
'23 days annual leave + local holidays',
'Flexible benefits package',
],
'start_date': 'ASAP',
'status': 'active',
'featured': False,
'priority': 7,
},
{
'title': 'QA Engineer',
'department': 'Engineering',
'employment_type': 'full-time',
'location_type': 'remote',
'location': 'Remote (Europe)',
'open_positions': 2,
'experience_required': '3+ years',
'salary_min': 40000,
'salary_max': 55000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Performance bonus',
'short_description': 'Ensure quality and reliability of our software products.',
'about_role': 'We are looking for QA Engineers to join our quality assurance team. You will be responsible for testing our web applications, writing automated tests, and ensuring the quality of our products. This is a fully remote position open to candidates across Europe.',
'requirements': [
'3+ years of QA/testing experience',
'Experience with test automation (Selenium, Cypress, Playwright)',
'Knowledge of testing methodologies',
'Experience with API testing',
'Understanding of CI/CD processes',
'Strong attention to detail',
'Must be based in Europe',
],
'responsibilities': [
'Design and execute test plans',
'Write and maintain automated tests',
'Perform manual testing when needed',
'Report and track bugs',
'Collaborate with development teams',
'Participate in release processes',
],
'qualifications': [
'Strong analytical and problem-solving skills',
'Experience with version control (Git)',
'Understanding of software development lifecycle',
'Good communication skills in English',
],
'bonus_points': [
'Experience with performance testing',
'Knowledge of security testing',
'Experience with mobile app testing',
'Programming skills (Python, JavaScript)',
'Experience with test management tools',
],
'benefits': [
'Fully remote work',
'Competitive salary package',
'Learning and development budget',
'Health insurance contribution',
'Flexible working hours',
'30 days annual leave',
],
'start_date': 'ASAP',
'status': 'active',
'featured': False,
'priority': 6,
},
{
'title': 'Marketing Manager',
'department': 'Marketing',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Dublin, Ireland',
'open_positions': 1,
'experience_required': '4+ years',
'salary_min': 50000,
'salary_max': 70000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Annual bonus + Health insurance',
'short_description': 'Lead our marketing efforts and grow our brand presence in Europe.',
'about_role': 'We are looking for a Marketing Manager to join our marketing team in Dublin. You will be responsible for developing and executing marketing strategies to increase brand awareness and drive customer acquisition across European markets. This role offers the opportunity to shape our marketing approach.',
'requirements': [
'4+ years of marketing experience',
'Proven track record of successful marketing campaigns',
'Strong understanding of digital marketing channels',
'Experience with marketing automation tools',
'Excellent analytical and communication skills',
'Experience with B2B marketing',
'Right to work in Ireland',
],
'responsibilities': [
'Develop and execute marketing strategies',
'Manage digital marketing campaigns',
'Oversee content marketing initiatives',
'Analyze campaign performance and ROI',
'Manage marketing budget',
'Collaborate with sales and product teams',
'Coordinate events and webinars',
],
'qualifications': [
'Bachelor\'s degree in Marketing or related field',
'Experience with Google Analytics and marketing tools',
'Strong project management skills',
'Creative thinking and problem-solving abilities',
'Excellent communication skills in English',
],
'bonus_points': [
'Experience with HubSpot or similar platforms',
'Knowledge of SEO and content marketing',
'Video production skills',
'Experience with paid advertising',
'Multilingual (French, German, Spanish)',
],
'benefits': [
'Hybrid work model',
'Competitive salary package',
'Marketing conferences and events budget',
'Professional development opportunities',
'Health insurance',
'Public transport card',
'25 days annual leave',
'Pension contribution',
],
'start_date': 'ASAP',
'status': 'active',
'featured': False,
'priority': 6,
},
{
'title': 'Sales Development Representative',
'department': 'Sales',
'employment_type': 'full-time',
'location_type': 'hybrid',
'location': 'Warsaw, Poland',
'open_positions': 2,
'experience_required': '1+ years',
'salary_min': 35000,
'salary_max': 45000,
'salary_currency': 'EUR',
'salary_period': 'per year',
'salary_additional': '+ Commission + Annual bonus',
'short_description': 'Generate leads and build relationships with potential customers.',
'about_role': 'We are looking for Sales Development Representatives to join our sales team in Warsaw. You will be responsible for prospecting, qualifying leads, and setting up meetings for our sales team. This is an excellent entry-level opportunity with growth potential.',
'requirements': [
'1+ years of sales or customer service experience',
'Strong communication and interpersonal skills',
'Self-motivated and goal-oriented',
'Experience with CRM systems (Salesforce, HubSpot)',
'Fluent English (Polish is a plus)',
'Right to work in Poland',
],
'responsibilities': [
'Prospect and qualify leads',
'Conduct outbound outreach (email, phone, LinkedIn)',
'Schedule meetings for sales team',
'Maintain CRM database',
'Follow up with prospects',
'Achieve monthly quotas',
],
'qualifications': [
'Strong communication skills',
'Ability to work in a fast-paced environment',
'Basic understanding of sales processes',
'Proficiency with Microsoft Office',
],
'bonus_points': [
'Experience in B2B sales',
'Knowledge of the tech industry',
'Multilingual skills',
'Experience with sales tools',
],
'benefits': [
'Hybrid work model',
'Competitive base salary + commission',
'Sales training and development',
'Health insurance',
'Public transport card',
'20 days annual leave',
'Career growth opportunities',
],
'start_date': 'ASAP',
'status': 'active',
'featured': False,
'priority': 5,
},
]
created_count = 0
for job_data in jobs_data:
# Generate slug from title
slug = job_data['title'].lower().replace(' ', '-').replace('/', '-').replace('(', '').replace(')', '')
job, created = JobPosition.objects.get_or_create(
slug=slug,
defaults=job_data
)
if created:
created_count += 1
self.stdout.write(
self.style.SUCCESS(f' ✓ Created job: {job.title} - {job.location}')
)
else:
self.stdout.write(
f' - Job already exists: {job.title} - {job.location}'
)
self.stdout.write(
self.style.SUCCESS(f'\n✓ Created {created_count} European job position(s)!')
)

View File

@@ -1,78 +1,276 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Application Received - GNX</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.7;
color: #2c3e50;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
margin: 0;
padding: 40px 20px;
}
.container {
max-width: 600px;
.email-wrapper {
max-width: 650px;
margin: 0 auto;
padding: 20px;
background: #ffffff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05);
}
.header {
background-color: #4A90E2;
color: white;
padding: 20px;
.email-header {
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 50%, #2E6DA4 100%);
padding: 50px 40px;
text-align: center;
position: relative;
overflow: hidden;
}
.content {
background-color: #f9f9f9;
.email-header::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%);
}
.email-header h1 {
color: #ffffff;
font-size: 32px;
font-weight: 700;
margin: 0;
position: relative;
z-index: 2;
letter-spacing: -0.5px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.email-body {
padding: 50px 40px;
background: #ffffff;
}
.greeting {
font-size: 18px;
color: #1e293b;
margin-bottom: 30px;
font-weight: 500;
}
.intro-text {
font-size: 16px;
color: #475569;
line-height: 1.8;
margin-bottom: 35px;
}
.details-box {
background: linear-gradient(135deg, rgba(74, 144, 226, 0.08) 0%, rgba(74, 144, 226, 0.03) 100%);
border: 2px solid rgba(74, 144, 226, 0.2);
border-left: 5px solid #4A90E2;
padding: 30px;
margin-top: 20px;
margin: 35px 0;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(74, 144, 226, 0.1);
}
.details {
background-color: white;
padding: 15px;
margin: 20px 0;
.details-box h3 {
font-size: 20px;
font-weight: 700;
color: #0f172a;
margin-bottom: 25px;
padding-bottom: 12px;
border-bottom: 2px solid rgba(74, 144, 226, 0.2);
}
.details-list {
list-style: none;
padding: 0;
}
.details-list li {
padding: 15px 0;
border-bottom: 1px solid rgba(74, 144, 226, 0.1);
display: flex;
align-items: flex-start;
}
.details-list li:last-child {
border-bottom: none;
}
.details-list strong {
color: #475569;
min-width: 140px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.details-list span {
color: #1e293b;
font-size: 15px;
font-weight: 500;
flex: 1;
}
.next-steps {
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
border-left: 4px solid #4A90E2;
padding: 25px;
border-radius: 8px;
margin-top: 40px;
}
.footer {
.next-steps h3 {
color: #0f172a;
font-size: 18px;
font-weight: 700;
margin-bottom: 15px;
}
.next-steps p {
color: #475569;
font-size: 15px;
line-height: 1.8;
margin-bottom: 15px;
}
.next-steps p:last-child {
margin-bottom: 0;
}
.closing {
margin-top: 40px;
font-size: 16px;
color: #1e293b;
line-height: 1.8;
}
.closing strong {
color: #0f172a;
}
.email-footer {
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
padding: 40px;
text-align: center;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #ddd;
color: rgba(255, 255, 255, 0.9);
}
.footer-company {
font-size: 18px;
font-weight: 700;
color: #ffffff;
margin-bottom: 8px;
}
.footer-tagline {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 25px;
}
.footer-note {
font-size: 12px;
color: #666;
color: rgba(255, 255, 255, 0.6);
margin-top: 25px;
line-height: 1.6;
}
@media (max-width: 600px) {
body {
padding: 20px 10px;
}
.email-header {
padding: 40px 25px;
}
.email-header h1 {
font-size: 26px;
}
.email-body {
padding: 35px 25px;
}
.details-list li {
flex-direction: column;
}
.details-list strong {
min-width: auto;
margin-bottom: 6px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Application Received</h1>
<div class="email-wrapper">
<div class="email-header">
<h1>Application Received</h1>
</div>
<div class="content">
<p>Dear <strong>{{ applicant_name }}</strong>,</p>
<div class="email-body">
<div class="greeting">Dear <strong>{{ applicant_name }}</strong>,</div>
<p>Thank you for applying for the <strong>{{ job_title }}</strong> position at GNX!</p>
<div class="intro-text">
Thank you for applying for the <strong>{{ job_title }}</strong> position at GNX! We have received your application and our team will review it carefully. We appreciate your interest in joining our team.
</div>
<p>We have received your application and our team will review it carefully. We appreciate your interest in joining our team.</p>
<div class="details">
<div class="details-box">
<h3>Application Details</h3>
<ul>
<li><strong>Position:</strong> {{ job_title }}</li>
<li><strong>Location:</strong> {{ job_location }}</li>
<li><strong>Applied on:</strong> {{ application_date|date:"F d, Y" }}</li>
<ul class="details-list">
<li>
<strong>Position:</strong>
<span>{{ job_title }}</span>
</li>
<li>
<strong>Location:</strong>
<span>{{ job_location }}</span>
</li>
<li>
<strong>Applied on:</strong>
<span>{{ application_date|date:"F d, Y" }}</span>
</li>
</ul>
</div>
<h3>What happens next?</h3>
<p>Our hiring team will review your application and resume. If your qualifications match our requirements, we will contact you within 1-2 weeks to discuss the next steps.</p>
<div class="next-steps">
<h3>What happens next?</h3>
<p>Our hiring team will review your application and resume. If your qualifications match our requirements, we will contact you within 1-2 weeks to discuss the next steps.</p>
<p>If you have any questions, please don't hesitate to reach out to us.</p>
</div>
<p>If you have any questions, please don't hesitate to reach out to us.</p>
<p>Best regards,<br><strong>The GNX Team</strong></p>
<div class="closing">
Best regards,<br>
<strong>The GNX Team</strong>
</div>
</div>
<div class="footer">
<p>This is an automated message. Please do not reply to this email.</p>
<div class="email-footer">
<div class="footer-company">GNX Software Solutions</div>
<div class="footer-tagline">Talent Acquisition Team</div>
<div class="footer-note">
This is an automated message. Please do not reply to this email.<br>
For inquiries, please contact our HR department.
</div>
</div>
</div>
</body>
</html>

View File

@@ -1,87 +1,274 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Job Application - GNX</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.7;
color: #2c3e50;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
margin: 0;
padding: 40px 20px;
}
.email-wrapper {
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #ffffff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05);
}
.header {
background-color: #2C3E50;
color: white;
padding: 20px;
.email-header {
background: linear-gradient(135deg, #2C3E50 0%, #34495e 50%, #1a252f 100%);
padding: 50px 40px;
text-align: center;
position: relative;
overflow: hidden;
}
.content {
background-color: #f9f9f9;
padding: 30px;
margin-top: 20px;
.email-header::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
}
.email-header h1 {
color: #ffffff;
font-size: 32px;
font-weight: 700;
margin: 0;
position: relative;
z-index: 2;
letter-spacing: -0.5px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.email-header .job-title {
color: rgba(255, 255, 255, 0.9);
font-size: 18px;
margin-top: 12px;
font-weight: 400;
position: relative;
z-index: 2;
}
.email-body {
padding: 50px 40px;
background: #ffffff;
}
.section {
background-color: white;
padding: 20px;
margin: 15px 0;
background: #ffffff;
border: 1px solid #e9ecef;
border-left: 4px solid #3498db;
padding: 28px;
margin: 25px 0;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.section h3 {
margin-top: 0;
color: #2C3E50;
font-size: 18px;
font-weight: 700;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 2px solid #e9ecef;
}
.info-row {
margin: 10px 0;
margin: 15px 0;
display: flex;
align-items: flex-start;
}
.label {
font-weight: bold;
.info-label {
font-weight: 700;
color: #555;
min-width: 180px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.cover-letter {
background-color: #f0f0f0;
padding: 15px;
border-radius: 5px;
white-space: pre-wrap;
margin-top: 10px;
.info-value {
color: #2c3e50;
font-size: 15px;
flex: 1;
font-weight: 500;
}
.links a {
display: inline-block;
margin: 5px 10px 5px 0;
.info-value a {
color: #3498db;
text-decoration: none;
font-weight: 600;
}
.footer {
text-align: center;
.info-value a:hover {
text-decoration: underline;
}
.cover-letter {
background: linear-gradient(135deg, #f0f0f0 0%, #f8f8f8 100%);
padding: 25px;
border-radius: 8px;
white-space: pre-wrap;
margin-top: 15px;
line-height: 1.8;
color: #334155;
border-left: 4px solid #daa520;
}
.links {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 15px;
}
.links a {
display: inline-block;
padding: 10px 20px;
background: linear-gradient(135deg, #3498db, #2980b9);
color: #ffffff !important;
text-decoration: none;
border-radius: 6px;
font-weight: 600;
font-size: 14px;
box-shadow: 0 4px 15px rgba(52, 152, 219, 0.3);
transition: all 0.3s ease;
}
.links a:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(52, 152, 219, 0.4);
}
.resume-notice {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
border-left: 4px solid #f59e0b;
padding: 20px 25px;
border-radius: 8px;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #ddd;
text-align: center;
}
.resume-notice strong {
color: #92400e;
font-size: 16px;
display: block;
margin-bottom: 8px;
}
.resume-notice p {
color: #78350f;
font-size: 14px;
margin: 0;
line-height: 1.6;
}
.email-footer {
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
padding: 40px;
text-align: center;
color: rgba(255, 255, 255, 0.9);
}
.footer-company {
font-size: 18px;
font-weight: 700;
color: #ffffff;
margin-bottom: 8px;
}
.footer-tagline {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 25px;
}
.footer-note {
font-size: 12px;
color: #666;
color: rgba(255, 255, 255, 0.6);
margin-top: 25px;
line-height: 1.6;
}
@media (max-width: 600px) {
body {
padding: 20px 10px;
}
.email-header {
padding: 40px 25px;
}
.email-header h1 {
font-size: 26px;
}
.email-body {
padding: 35px 25px;
}
.info-row {
flex-direction: column;
}
.info-label {
min-width: auto;
margin-bottom: 6px;
}
.links {
flex-direction: column;
}
.links a {
width: 100%;
text-align: center;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="email-wrapper">
<div class="email-header">
<h1>🎯 New Job Application</h1>
<p>{{ job_title }}</p>
<div class="job-title">{{ job_title }}</div>
</div>
<div class="content">
<div class="email-body">
<div class="section">
<h3>👤 Applicant Information</h3>
<div class="info-row">
<span class="label">Name:</span> {{ applicant_name }}
<span class="info-label">Name:</span>
<span class="info-value">{{ applicant_name }}</span>
</div>
<div class="info-row">
<span class="label">Email:</span> <a href="mailto:{{ applicant_email }}">{{ applicant_email }}</a>
<span class="info-label">Email:</span>
<span class="info-value"><a href="mailto:{{ applicant_email }}">{{ applicant_email }}</a></span>
</div>
{% if applicant_phone %}
<div class="info-row">
<span class="label">Phone:</span> {{ applicant_phone }}
<span class="info-label">Phone:</span>
<span class="info-value">{{ applicant_phone }}</span>
</div>
{% endif %}
</div>
@@ -90,17 +277,20 @@
<h3>💼 Professional Information</h3>
{% if current_position %}
<div class="info-row">
<span class="label">Current Position:</span> {{ current_position }}
<span class="info-label">Current Position:</span>
<span class="info-value">{{ current_position }}</span>
</div>
{% endif %}
{% if current_company %}
<div class="info-row">
<span class="label">Current Company:</span> {{ current_company }}
<span class="info-label">Current Company:</span>
<span class="info-value">{{ current_company }}</span>
</div>
{% endif %}
{% if years_of_experience %}
<div class="info-row">
<span class="label">Years of Experience:</span> {{ years_of_experience }}
<span class="info-label">Years of Experience:</span>
<span class="info-value">{{ years_of_experience }}</span>
</div>
{% endif %}
</div>
@@ -108,24 +298,29 @@
<div class="section">
<h3>📋 Application Details</h3>
<div class="info-row">
<span class="label">Position Applied:</span> {{ job_title }}
<span class="info-label">Position Applied:</span>
<span class="info-value">{{ job_title }}</span>
</div>
<div class="info-row">
<span class="label">Application Date:</span> {{ application_date|date:"F d, Y at h:i A" }}
<span class="info-label">Application Date:</span>
<span class="info-value">{{ application_date|date:"F d, Y at h:i A" }}</span>
</div>
{% if expected_salary %}
<div class="info-row">
<span class="label">Expected Salary:</span> {{ expected_salary }} {{ salary_currency }}
<span class="info-label">Expected Salary:</span>
<span class="info-value">{{ expected_salary }} {{ salary_currency }}</span>
</div>
{% endif %}
{% if available_from %}
<div class="info-row">
<span class="label">Available From:</span> {{ available_from|date:"F d, Y" }}
<span class="info-label">Available From:</span>
<span class="info-value">{{ available_from|date:"F d, Y" }}</span>
</div>
{% endif %}
{% if notice_period %}
<div class="info-row">
<span class="label">Notice Period:</span> {{ notice_period }}
<span class="info-label">Notice Period:</span>
<span class="info-value">{{ notice_period }}</span>
</div>
{% endif %}
</div>
@@ -148,13 +343,22 @@
<div class="cover-letter">{{ cover_letter }}</div>
</div>
{% endif %}
<div class="resume-notice">
<strong>📎 Resume is attached to this email.</strong>
<p>Please log in to the admin panel to review the full application and update its status.</p>
</div>
</div>
<div class="footer">
<p><strong>Resume is attached to this email.</strong></p>
<p>Please log in to the admin panel to review the full application and update its status.</p>
<div class="email-footer">
<div class="footer-company">GNX Software Solutions</div>
<div class="footer-tagline">Human Resources Department</div>
<div class="footer-note">
This is an automated notification for new job applications.<br>
Please review the application in the admin panel.
</div>
</div>
</div>
</body>
</html>