58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
"""Push close decisions from pusat to farm-location dashboard-cpsp."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
import httpx
|
|
|
|
from apps.farms.models import Cycle
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SiteClosePushError(Exception):
|
|
def __init__(self, message: str):
|
|
self.message = message
|
|
super().__init__(message)
|
|
|
|
|
|
def push_close_decision(cycle: Cycle, *, approved: bool) -> None:
|
|
active_site = cycle.active_site
|
|
if (
|
|
not active_site
|
|
or not active_site.api_base_url
|
|
or not active_site.api_key
|
|
or not cycle.source_cycle_id
|
|
):
|
|
logger.info("No active-site channel configured for cycle %s; skip push", cycle.pk)
|
|
return
|
|
|
|
base = active_site.api_base_url.rstrip("/")
|
|
url = f"{base}/cycles/{cycle.source_cycle_id}/apply-close-decision/"
|
|
payload = {"decision": "approve" if approved else "reject"}
|
|
if approved:
|
|
if not cycle.end_date:
|
|
raise SiteClosePushError("Approved cycle is missing end_date.")
|
|
payload["end_date"] = cycle.end_date.isoformat()
|
|
|
|
try:
|
|
response = httpx.post(
|
|
url,
|
|
json=payload,
|
|
headers={
|
|
"X-API-Key": active_site.api_key,
|
|
"Content-Type": "application/json",
|
|
},
|
|
timeout=30.0,
|
|
)
|
|
if response.status_code >= 400:
|
|
raise SiteClosePushError(
|
|
f"Gagal kirim keputusan ke situs ({response.status_code}: {response.text[:200]})"
|
|
)
|
|
except SiteClosePushError:
|
|
raise
|
|
except httpx.HTTPError as exc:
|
|
logger.exception("Push close decision failed for cycle %s", cycle.pk)
|
|
raise SiteClosePushError("Gagal kirim keputusan ke situs — coba lagi") from exc
|