53 lines
2.1 KiB
Python
53 lines
2.1 KiB
Python
from django.utils import timezone
|
|
from rest_framework import decorators, mixins, response, viewsets
|
|
|
|
from apps.core.errors import ApiError
|
|
from apps.integrations.odoo.services import OdooInvoiceService
|
|
from apps.invoicing.models import Invoice
|
|
from apps.invoicing.serializers import InvoiceSerializer
|
|
from apps.rbac.permissions import ActionPermission
|
|
|
|
|
|
class InvoiceViewSet(
|
|
mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet
|
|
):
|
|
serializer_class = InvoiceSerializer
|
|
permission_classes = [ActionPermission]
|
|
code_map = {
|
|
"list": "invoice.view",
|
|
"retrieve": "invoice.view",
|
|
"create": "invoice.create",
|
|
"sync": "invoice.create",
|
|
}
|
|
|
|
def get_queryset(self):
|
|
user = self.request.user
|
|
qs = Invoice.objects.select_related("order").all()
|
|
if user.is_superuser:
|
|
return qs
|
|
return qs.filter(order__customer__user=user)
|
|
|
|
def perform_create(self, serializer):
|
|
order = serializer.validated_data["order"]
|
|
total = (order.price_snapshot or {}).get("total")
|
|
if not total:
|
|
raise ApiError("NO_PRICE_SNAPSHOT", "Order has no price snapshot.")
|
|
serializer.save(number=f"INV-{order.order_number}", amount=total, currency=order.currency)
|
|
|
|
@decorators.action(detail=True, methods=["post"])
|
|
def sync(self, request, pk=None):
|
|
invoice = self.get_object()
|
|
invoice.sync_state = Invoice.SyncState.PROCESSING
|
|
invoice.save(update_fields=["sync_state"])
|
|
try:
|
|
result = OdooInvoiceService().sync_invoice(invoice)
|
|
invoice.odoo_invoice_id = result.get("id", "")
|
|
invoice.sync_state = Invoice.SyncState.SYNCHRONIZED
|
|
invoice.synced_at = timezone.now()
|
|
invoice.save(update_fields=["odoo_invoice_id", "sync_state", "synced_at"])
|
|
except Exception as exc:
|
|
invoice.sync_state = Invoice.SyncState.FAILED
|
|
invoice.last_error = str(exc)
|
|
invoice.save(update_fields=["sync_state", "last_error"])
|
|
return response.Response(InvoiceSerializer(invoice).data)
|