307 lines
11 KiB
Python
307 lines
11 KiB
Python
"""
|
|
Views for integrations app.
|
|
"""
|
|
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.urls import reverse_lazy
|
|
from django.views.generic import ListView, CreateView, DetailView, UpdateView, TemplateView
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.contrib import messages
|
|
|
|
from core.mixins import TenantFilterMixin
|
|
from .models import (
|
|
ExternalOrder,
|
|
NphiesMessage,
|
|
PayerContract,
|
|
EInvoice,
|
|
ZatcaCredential,
|
|
)
|
|
from .forms import ExternalOrderForm, PayerContractForm, ZatcaCredentialForm
|
|
|
|
|
|
# ============================================================================
|
|
# Dashboard
|
|
# ============================================================================
|
|
|
|
class IntegrationsDashboardView(LoginRequiredMixin, TenantFilterMixin, TemplateView):
|
|
"""Integrations dashboard with overview of all integration modules."""
|
|
template_name = 'integrations/integrations_dashboard.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
tenant = self.request.user.tenant
|
|
|
|
# Get counts for dashboard stats
|
|
context['stats'] = {
|
|
'external_orders_count': ExternalOrder.objects.filter(tenant=tenant).count(),
|
|
'nphies_messages_count': NphiesMessage.objects.filter(tenant=tenant).count(),
|
|
'einvoices_count': EInvoice.objects.filter(tenant=tenant).count(),
|
|
'payer_contracts_count': PayerContract.objects.filter(tenant=tenant).count(),
|
|
}
|
|
|
|
return context
|
|
|
|
|
|
# ============================================================================
|
|
# External Orders (Lab & Radiology)
|
|
# ============================================================================
|
|
|
|
class ExternalOrderListView(LoginRequiredMixin, TenantFilterMixin, ListView):
|
|
"""List all external orders."""
|
|
model = ExternalOrder
|
|
template_name = 'integrations/external_order_list.html'
|
|
context_object_name = 'orders'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().filter(
|
|
tenant=self.request.user.tenant
|
|
).select_related('patient', 'ordered_by')
|
|
|
|
# Filter by order type if provided
|
|
order_type = self.request.GET.get('order_type')
|
|
if order_type:
|
|
queryset = queryset.filter(order_type=order_type)
|
|
|
|
# Filter by status if provided
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
queryset = queryset.filter(status=status)
|
|
|
|
return queryset.order_by('-ordered_at')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['order_types'] = ExternalOrder.OrderType.choices
|
|
context['statuses'] = ExternalOrder.Status.choices
|
|
return context
|
|
|
|
|
|
class ExternalOrderCreateView(LoginRequiredMixin, TenantFilterMixin, CreateView):
|
|
"""Create a new external order."""
|
|
model = ExternalOrder
|
|
form_class = ExternalOrderForm
|
|
template_name = 'integrations/external_order_form.html'
|
|
success_url = reverse_lazy('integrations:order-list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
form.instance.ordered_by = self.request.user
|
|
messages.success(self.request, _('External order created successfully.'))
|
|
return super().form_valid(form)
|
|
|
|
|
|
class ExternalOrderDetailView(LoginRequiredMixin, TenantFilterMixin, DetailView):
|
|
"""View external order details."""
|
|
model = ExternalOrder
|
|
template_name = 'integrations/external_order_detail.html'
|
|
context_object_name = 'order'
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(
|
|
tenant=self.request.user.tenant
|
|
).select_related('patient', 'ordered_by')
|
|
|
|
|
|
class ExternalOrderUpdateView(LoginRequiredMixin, TenantFilterMixin, UpdateView):
|
|
"""Update an external order."""
|
|
model = ExternalOrder
|
|
form_class = ExternalOrderForm
|
|
template_name = 'integrations/external_order_form.html'
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
def get_success_url(self):
|
|
return reverse_lazy('integrations:order-detail', kwargs={'pk': self.object.pk})
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, _('External order updated successfully.'))
|
|
return super().form_valid(form)
|
|
|
|
|
|
# ============================================================================
|
|
# NPHIES Messages
|
|
# ============================================================================
|
|
|
|
class NphiesMessageListView(LoginRequiredMixin, TenantFilterMixin, ListView):
|
|
"""List all NPHIES messages."""
|
|
model = NphiesMessage
|
|
template_name = 'integrations/nphies_message_list.html'
|
|
context_object_name = 'messages'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
# Filter by direction if provided
|
|
direction = self.request.GET.get('direction')
|
|
if direction:
|
|
queryset = queryset.filter(direction=direction)
|
|
|
|
# Filter by resource type if provided
|
|
resource_type = self.request.GET.get('resource_type')
|
|
if resource_type:
|
|
queryset = queryset.filter(resource_type=resource_type)
|
|
|
|
# Filter by status if provided
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
queryset = queryset.filter(status=status)
|
|
|
|
return queryset.order_by('-created_at')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['directions'] = NphiesMessage.Direction.choices
|
|
context['resource_types'] = NphiesMessage.ResourceType.choices
|
|
context['statuses'] = NphiesMessage.Status.choices
|
|
return context
|
|
|
|
|
|
class NphiesMessageDetailView(LoginRequiredMixin, TenantFilterMixin, DetailView):
|
|
"""View NPHIES message details."""
|
|
model = NphiesMessage
|
|
template_name = 'integrations/nphies_message_detail.html'
|
|
context_object_name = 'message'
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
|
|
# ============================================================================
|
|
# Payer Contracts
|
|
# ============================================================================
|
|
|
|
class PayerContractListView(LoginRequiredMixin, TenantFilterMixin, ListView):
|
|
"""List all payer contracts."""
|
|
model = PayerContract
|
|
template_name = 'integrations/payer_contract_list.html'
|
|
context_object_name = 'payers'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
# Filter by active status if provided
|
|
is_active = self.request.GET.get('is_active')
|
|
if is_active:
|
|
queryset = queryset.filter(is_active=is_active == 'true')
|
|
|
|
return queryset.order_by('payer_name')
|
|
|
|
|
|
class PayerContractCreateView(LoginRequiredMixin, TenantFilterMixin, CreateView):
|
|
"""Create a new payer contract."""
|
|
model = PayerContract
|
|
form_class = PayerContractForm
|
|
template_name = 'integrations/payer_contract_form.html'
|
|
success_url = reverse_lazy('integrations:payer-list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, _('Payer contract created successfully.'))
|
|
return super().form_valid(form)
|
|
|
|
|
|
class PayerContractUpdateView(LoginRequiredMixin, TenantFilterMixin, UpdateView):
|
|
"""Update a payer contract."""
|
|
model = PayerContract
|
|
form_class = PayerContractForm
|
|
template_name = 'integrations/payer_contract_form.html'
|
|
success_url = reverse_lazy('integrations:payer-list')
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, _('Payer contract updated successfully.'))
|
|
return super().form_valid(form)
|
|
|
|
|
|
# ============================================================================
|
|
# E-Invoices (ZATCA)
|
|
# ============================================================================
|
|
|
|
class EInvoiceListView(LoginRequiredMixin, TenantFilterMixin, ListView):
|
|
"""List all e-invoices."""
|
|
model = EInvoice
|
|
template_name = 'integrations/einvoice_list.html'
|
|
context_object_name = 'einvoices'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().filter(
|
|
tenant=self.request.user.tenant
|
|
).select_related('invoice')
|
|
|
|
# Filter by clearance status if provided
|
|
clearance_status = self.request.GET.get('clearance_status')
|
|
if clearance_status:
|
|
queryset = queryset.filter(clearance_status=clearance_status)
|
|
|
|
# Filter by submission mode if provided
|
|
submission_mode = self.request.GET.get('submission_mode')
|
|
if submission_mode:
|
|
queryset = queryset.filter(submission_mode=submission_mode)
|
|
|
|
return queryset.order_by('-created_at')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['clearance_statuses'] = EInvoice.ClearanceStatus.choices
|
|
context['submission_modes'] = EInvoice.SubmissionMode.choices
|
|
return context
|
|
|
|
|
|
class EInvoiceDetailView(LoginRequiredMixin, TenantFilterMixin, DetailView):
|
|
"""View e-invoice details."""
|
|
model = EInvoice
|
|
template_name = 'integrations/einvoice_detail.html'
|
|
context_object_name = 'einvoice'
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(
|
|
tenant=self.request.user.tenant
|
|
).select_related('invoice')
|
|
|
|
|
|
# ============================================================================
|
|
# ZATCA Credentials
|
|
# ============================================================================
|
|
|
|
class ZatcaCredentialListView(LoginRequiredMixin, TenantFilterMixin, ListView):
|
|
"""List all ZATCA credentials."""
|
|
model = ZatcaCredential
|
|
template_name = 'integrations/zatca_credential_list.html'
|
|
context_object_name = 'credentials'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().filter(tenant=self.request.user.tenant)
|
|
|
|
# Filter by environment if provided
|
|
environment = self.request.GET.get('environment')
|
|
if environment:
|
|
queryset = queryset.filter(environment=environment)
|
|
|
|
return queryset.order_by('-created_at')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['environments'] = ZatcaCredential.Environment.choices
|
|
return context
|
|
|
|
|
|
class ZatcaCredentialCreateView(LoginRequiredMixin, TenantFilterMixin, CreateView):
|
|
"""Create a new ZATCA credential."""
|
|
model = ZatcaCredential
|
|
form_class = ZatcaCredentialForm
|
|
template_name = 'integrations/zatca_credential_form.html'
|
|
success_url = reverse_lazy('integrations:credential-list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, _('ZATCA credential created successfully.'))
|
|
return super().form_valid(form)
|