import json import logging from django.conf import settings from django.contrib.auth.decorators import login_required from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from pos_sync.models import POSConnection, SyncEvent from pos_sync.services import POSSyncError, apply_inbound_sale logger = logging.getLogger(__name__) def _authorized(request) -> bool: expected = (settings.POS_WEBHOOK_SECRET or "").strip() if not expected: conn = POSConnection.objects.filter(is_active=True).exclude( webhook_secret="" ).first() expected = (conn.webhook_secret if conn else "").strip() if not expected: return False header = request.headers.get("Authorization", "") token = "" if header.startswith("Bearer "): token = header[7:].strip() token = token or request.GET.get("token") or "" return token == expected @login_required def event_list(request): events = SyncEvent.objects.select_related("connection")[:200] connections = POSConnection.objects.all() return render( request, "pos_sync/list.html", {"events": events, "connections": connections}, ) @csrf_exempt @require_http_methods(["POST"]) def inventory_webhook(request): if not _authorized(request): return HttpResponse("unauthorized", status=401) try: payload = json.loads(request.body.decode() or "{}") except json.JSONDecodeError: return HttpResponseBadRequest("invalid json") sku = payload.get("sku") or payload.get("SKU") or "" try: quantity = int(payload.get("quantity") or payload.get("qty") or 0) except (TypeError, ValueError): return HttpResponseBadRequest("invalid quantity") external_id = str(payload.get("external_id") or payload.get("id") or "") try: event = apply_inbound_sale( sku=sku, quantity=quantity, external_id=external_id, payload=payload, ) except POSSyncError as exc: logger.warning("POS inbound rejected: %s", exc) return JsonResponse({"ok": False, "error": str(exc)}, status=400) return JsonResponse({"ok": True, "id": str(event.pk), "status": event.status})