Procurement - Celery Tasks

Location: api/nextango/apps/procurement/tasks.py Last Updated: 2026-07-09

Overview

Background tasks for the procurement domain. Currently one periodic task runs daily to scan all active inventory levels and surface items that have fallen at or below their configured reorder points, logging warnings to alert operations staff before a stockout occurs.


Task Summary

TaskSchedulePurposeKey Service Call
check_reorder_levelsDaily at 6 AMScan inventory for items at/below reorder pointInventoryLevel ORM query

Task Reference

check_reorder_levels

Source: tasks.py:11-46 Schedule: Daily at 6:00 AM (configured in Celery beat schedule)

Purpose: Scans all active InventoryLevel records whose reorder_point > 0, stock_on_hand is at or below that reorder point, and whose product variant has custom_inventory_management enabled. For each matching item, emits a WARNING log containing the SKU, store name, current on-hand quantity, reorder point, and suggested order quantity. Items with reorder_point=0 are skipped (threshold not configured), as are variants without custom inventory management.

Signature:

@shared_task(name='procurement.check_reorder_levels')
def check_reorder_levels():
    ...

Returns:

{'needs_reorder': <int>}  # Count of SKUs at or below reorder point

Retry Policy: None configured: if the task fails it will not retry automatically.

Why Daily:

  • Reorder levels are a daily operational concern, not real-time
  • Alerts are surfaced to warehouse staff at the start of the business day
  • Receiving a PO updates inventory automatically: stock_on_hand and stock_lifetime_received increment when line items are received (see Signals)

Celery Beat Configuration

from celery.schedules import crontab

CELERY_BEAT_SCHEDULE = {
    'check-reorder-levels': {
        'task': 'procurement.check_reorder_levels',
        'schedule': crontab(hour=6, minute=0),  # Daily at 6 AM
    },
}

Manual Execution

from nextango.apps.procurement.tasks import check_reorder_levels

# Synchronous
result = check_reorder_levels()
print(f"{result['needs_reorder']} SKUs need reordering")

# Asynchronous
check_reorder_levels.delay()

  • Signals: update_inventory_on_receiving fires when a PO is received
  • Models: PurchaseOrder, PurchaseOrderLineItem, and InventoryLevel
  • Views: Analytics endpoints for procurement reporting

Was this page helpful?