Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aerele/medusa_integration/llms.txt

Use this file to discover all available pages before exploring further.

The ERPNext Medusa Integration registers several background jobs with the Frappe scheduler. These tasks keep product data, inventory levels, prices, and OTP records in sync between ERPNext and the Medusa storefront without requiring manual intervention. This page documents every scheduled task, its trigger schedule, and what it does.

How the scheduler works

Frappe’s scheduler polls the scheduler_events registry defined in hooks.py and dispatches jobs to background workers. Tasks can be triggered on cron expressions, named intervals such as daily_long, or other built-in schedules.
The scheduler must be enabled for any of these tasks to run. If you have just installed the integration or migrated to a new server, verify the scheduler is active before relying on automatic sync.
To check or enable the scheduler, run the following command on your server:
bench --site <your-site-name> enable-scheduler
To view execution history and detect failures, open Desk → Scheduled Job Log in your ERPNext instance. Each row shows the task name, start time, and whether it succeeded or raised an error.

Every-minute tasks (* * * * *)

These two tasks run once per minute and are designed to be fast and lightweight.

send_quotation_emails

Function: medusa_integration.api.send_quotation_emails Queries the ERPNext Email Queue for unsent messages whose reference_doctype is Quotation and immediately dispatches them using frappe.email.doctype.email_queue.email_queue.send_now. This ensures that quotation notification emails — sent when a quotation transitions to the “Ready for Customer Review” workflow state — are delivered promptly rather than waiting for the standard email queue flush interval.

expire_otps

Function: medusa_integration.api.expire_otps Scans the Email OTP doctype for records that have passed their expiry time and marks them as expired. Keeping stale OTP records cleaned up prevents false positives during verification and avoids unbounded table growth.

Daily tasks at 1 AM (0 1 * * *)

Four tasks fire together every night at 01:00 server time. They perform heavier operations and may take several minutes to complete.

fetch_clearance_items

Function: medusa_integration.api.fetch_clearance_items Identifies items that are nearing expiry or have been marked as clearance stock and updates the Expiring Items and Best Deals doctypes. The storefront reads these records to display clearance sections to customers.

add_top_selling_items_to_collection

Function: medusa_integration.api.add_top_selling_items_to_collection Queries submitted Sales Invoice Items over all time, grouped by item and product category (Dental, Medical, Infection Control, Medical Laboratory IVD), and replaces the child-table rows in the Product Collection single doctype with the top 20 sellers per category. The storefront reads Product Collection to render “top picks” sections.

export_items_and_images_custom

Function: medusa_integration.api.export_items_and_images_custom Bulk-exports all published Website Items that do not yet have a medusa_id to Medusa. Rather than processing the entire list sequentially, the function divides the unsynced items into four equally-sized batches and enqueues each batch as a separate background job:
frappe.enqueue(
    "medusa_integration.api.export_items_batch",
    queue="long",
    timeout=28800,
    is_async=True,
    job_name=f"export_items_batch_{i}",
    batch_index=i,
    batch_size=batch_size
)
Each batch job runs on the long queue with an 8-hour (28800 second) timeout. Make sure at least one bench worker --queue long process is running, otherwise the jobs will remain queued indefinitely.
Each batch calls export_website_item() per record, which creates the product and a default variant in Medusa, then stores the returned medusa_id and medusa_variant_id back on the Website Item.

sync_missing_prices_to_medusa

Function: medusa_integration.api.sync_missing_prices_to_medusa Finds all Item Price records that belong to the “Standard Selling” price list, have no customer set, and have no medusa_price_id yet. For each such record it creates a Medusa price list entry and writes the returned price ID back to the medusa_price_id field on the Item Price. This is a catch-up task for prices that were created before their Website Item was exported, or where an earlier price-sync event failed.

Daily-long tasks

update_webitem_stock

Function: medusa_integration.api.update_webitem_stock Schedule: daily_long Iterates over all Website Items and pushes current inventory quantities from ERPNext to Medusa. The daily_long interval is a Frappe built-in that runs once per day and is dispatched to the long-running worker queue, making it appropriate for operations that touch many records.

Monitoring scheduled tasks

LocationWhat you can see
Desk → Scheduled Job LogPer-task execution timestamps, success/failure status, and error tracebacks
Desk → Error LogPython exceptions raised inside any scheduled task
frappe.log_error entriesApplication-level errors logged by the integration code itself
Filter the Scheduled Job Log by Scheduled Job Type to isolate a specific task. If a task shows a “Failed” status, the full traceback is stored in the Error Log under the same timestamp.

Build docs developers (and LLMs) love