2025-11-02 14:35:35 +03:00

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)