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.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.
How the scheduler works
Frappe’s scheduler polls thescheduler_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.
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:
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.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
| Location | What you can see |
|---|---|
| Desk → Scheduled Job Log | Per-task execution timestamps, success/failure status, and error tracebacks |
| Desk → Error Log | Python exceptions raised inside any scheduled task |
frappe.log_error entries | Application-level errors logged by the integration code itself |