from celery import shared_task from django.db.models import Q from django.utils import timezone from external_api.cdek import client as cdek_client, CDEKStatus from external_api.currency import client as CurrencyAPIClient from .models import Checklist, GlobalSettings @shared_task def check_cdek_status(order_id): obj = Checklist.objects.filter(id=order_id).first() if obj is None or obj.cdek_tracking is None or obj.status == Checklist.Status.COMPLETED: return # Get CDEK statuses statuses = cdek_client.get_order_statuses(obj.cdek_tracking) if not statuses: return new_status = obj.status if CDEKStatus.DELIVERED in statuses: new_status = Checklist.Status.COMPLETED elif CDEKStatus.READY_FOR_SHIPMENT_IN_SENDER_CITY in statuses: new_status = Checklist.Status.CDEK # Update status if obj.status != new_status: print(f'Order [{obj.id}] status: {obj.status} -> {new_status}') obj.status = new_status obj.save() return new_status @shared_task def schedule_cdek_status_update(): qs = Checklist.objects.filter( Q(cdek_tracking__isnull=False) & Q(status__in=Checklist.Status.CDEK_READY_STATUSES) ) order_count = len(qs) print(f'Scheduled to update {order_count} orders') # Spawn a sub-task for every order for obj in qs: check_cdek_status.delay(order_id=obj.id) return order_count @shared_task(autoretry_for=(Exception,), retry_backoff=True, retry_kwargs={'max_retries': 5}) def update_yuan_rate(): # Get fresh rate from API rate = CurrencyAPIClient.get_cny_rate() if not rate: raise Exception("Failed to get yuan rate") print(f"Fetched new yuan rate: {rate}") # Save rate in DB for future usage settings = GlobalSettings.load() settings.yuan_rate = rate settings.yuan_rate_last_updated = timezone.now() settings.save() return rate