238 lines
8.0 KiB
Python
238 lines
8.0 KiB
Python
import json
|
|
from datetime import datetime
|
|
import logging
|
|
from typing import Dict, Any
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.utils.decorators import method_decorator
|
|
from django.views import View
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import transaction
|
|
from .models import Source, JobPosting, IntegrationLog
|
|
from .erp_integration_service import ERPIntegrationService
|
|
|
|
|
|
class ERPIntegrationView(View):
|
|
"""
|
|
API endpoint for receiving job requests from ERP system
|
|
"""
|
|
|
|
def get(self, request):
|
|
"""Health check endpoint"""
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'message': 'ERP Integration API is available',
|
|
'version': '1.0.0',
|
|
'supported_actions': ['create_job', 'update_job']
|
|
})
|
|
|
|
@method_decorator(csrf_exempt)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
def post(self, request):
|
|
"""Handle POST requests from ERP system"""
|
|
try:
|
|
# Start timing for processing
|
|
start_time = datetime.now()
|
|
|
|
# Get request data
|
|
if request.content_type == 'application/json':
|
|
try:
|
|
data = json.loads(request.body.decode('utf-8'))
|
|
except json.JSONDecodeError:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Invalid JSON data'
|
|
}, status=400)
|
|
else:
|
|
data = request.POST.dict()
|
|
# Get action from request
|
|
action = data.get('action', '').lower()
|
|
if not action:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Action is required'
|
|
}, status=400)
|
|
|
|
# Validate action
|
|
valid_actions = ['create_job', 'update_job']
|
|
if action not in valid_actions:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': f'Invalid action. Must be one of: {", ".join(valid_actions)}'
|
|
}, status=400)
|
|
|
|
# Get source identifier
|
|
source_name = data.get('source_name')
|
|
source_id = data.get('source_id')
|
|
|
|
# Find the source
|
|
source = None
|
|
if source_id:
|
|
source = Source.objects.filter(id=source_id).first()
|
|
elif source_name:
|
|
source = Source.objects.filter(name=source_name).first()
|
|
|
|
if not source:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Source not found'
|
|
}, status=404)
|
|
|
|
job_id = data.get('job_id')
|
|
if not job_id:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Job ID is required and must be unique'
|
|
})
|
|
if JobPosting.objects.filter(internal_job_id=job_id).exists():
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Job with this ID already exists'
|
|
}, status=400)
|
|
# Create integration service
|
|
service = ERPIntegrationService(source)
|
|
|
|
# Validate request
|
|
is_valid, error_msg = service.validate_request(request)
|
|
if not is_valid:
|
|
service.log_integration_request(request, 'ERROR', error_message=error_msg, status_code='403')
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': error_msg
|
|
}, status=403)
|
|
|
|
# Log the request
|
|
service.log_integration_request(request, 'REQUEST')
|
|
|
|
# Process based on action
|
|
if action == 'create_job':
|
|
result, error_msg = self._create_job(service, data)
|
|
elif action == 'update_job':
|
|
result, error_msg = self._update_job(service, data)
|
|
|
|
# Calculate processing time
|
|
processing_time = (datetime.now() - start_time).total_seconds()
|
|
|
|
# Log the result
|
|
status_code = '200' if not error_msg else '400'
|
|
service.log_integration_request(
|
|
request,
|
|
'RESPONSE' if not error_msg else 'ERROR',
|
|
response_data={'result': result} if result else {},
|
|
status_code=status_code,
|
|
processing_time=processing_time,
|
|
error_message=error_msg
|
|
)
|
|
|
|
# Return response
|
|
if error_msg:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': error_msg,
|
|
'processing_time': processing_time
|
|
}, status=400)
|
|
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'message': f'Job {action.replace("_", " ")} successfully',
|
|
'data': result,
|
|
'processing_time': processing_time
|
|
})
|
|
|
|
except Exception as e:
|
|
logger = logging.getLogger(__name__)
|
|
logger.error(f"Error in ERP integration: {str(e)}", exc_info=True)
|
|
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Internal server error'
|
|
}, status=500)
|
|
|
|
@transaction.atomic
|
|
def _create_job(self, service: ERPIntegrationService, data: Dict[str, Any]) -> tuple[Dict[str, Any], str]:
|
|
"""Create a new job from ERP data"""
|
|
# Validate ERP data
|
|
# print(data)
|
|
is_valid, error_msg = service.validate_erp_data(data)
|
|
if not is_valid:
|
|
return None, error_msg
|
|
|
|
# Create job from ERP data
|
|
job, error_msg = service.create_job_from_erp(data)
|
|
if error_msg:
|
|
return None, error_msg
|
|
# Prepare response data
|
|
response_data = {
|
|
'job_id': job.internal_job_id,
|
|
'title': job.title,
|
|
'status': job.status,
|
|
'created_at': job.created_at.isoformat(),
|
|
'message': 'Job created successfully'
|
|
}
|
|
|
|
return response_data, ""
|
|
|
|
@transaction.atomic
|
|
def _update_job(self, service: ERPIntegrationService, data: Dict[str, Any]) -> tuple[Dict[str, Any], str]:
|
|
"""Update an existing job from ERP data"""
|
|
# Get job ID from request
|
|
job_id = data.get('job_id')
|
|
if not job_id:
|
|
return None, "Job ID is required for update"
|
|
|
|
# Validate ERP data
|
|
is_valid, error_msg = service.validate_erp_data(data)
|
|
if not is_valid:
|
|
return None, error_msg
|
|
|
|
# Update job from ERP data
|
|
job, error_msg = service.update_job_from_erp(job_id, data)
|
|
if error_msg:
|
|
return None, error_msg
|
|
|
|
# Prepare response data
|
|
response_data = {
|
|
'job_id': job.internal_job_id,
|
|
'title': job.title,
|
|
'status': job.status,
|
|
'updated_at': job.updated_at.isoformat(),
|
|
'message': 'Job updated successfully'
|
|
}
|
|
|
|
return response_data, ""
|
|
|
|
|
|
# Specific endpoint for creating jobs (POST only)
|
|
@require_http_methods(["POST"])
|
|
@csrf_exempt
|
|
def erp_create_job_view(request):
|
|
"""View for creating jobs from ERP (simpler endpoint)"""
|
|
view = ERPIntegrationView()
|
|
return view.post(request)
|
|
|
|
|
|
# Specific endpoint for updating jobs (POST only)
|
|
@require_http_methods(["POST"])
|
|
@csrf_exempt
|
|
def erp_update_job_view(request):
|
|
"""View for updating jobs from ERP (simpler endpoint)"""
|
|
view = ERPIntegrationView()
|
|
return view.post(request)
|
|
|
|
|
|
# Health check endpoint
|
|
@require_http_methods(["GET"])
|
|
def erp_integration_health(request):
|
|
"""Health check endpoint for ERP integration"""
|
|
return JsonResponse({
|
|
'status': 'healthy',
|
|
'timestamp': datetime.now().isoformat(),
|
|
'services': {
|
|
'erp_integration': 'available',
|
|
'database': 'connected'
|
|
}
|
|
})
|