Commera

Commera

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

Events

An event tells your plugin that something happened in the store. Commera records the event, commits, and then calls your handler in a background job. A handler cannot stop or change the action that caused the event. To stop an action, use a hook.

Register a handler

Add a commera_events dict to hooks.py. Each key is an event name, and each value is a list of handlers.

commera_events = {
	"order_paid": ["my_app.orders.on_order_paid"],
	"order_refunded": ["my_app.orders.on_order_refunded"],
}

bench migrate prints a warning and writes an Error Log for a key that is not an event name, for example order_payed.

The handler gets one argument, a CommeraEvent. Commera ignores its return value.

import frappe
from commera.sdk.events import CommeraEvent


def on_order_paid(event: CommeraEvent):
	if frappe.db.exists("My Job", {"event_id": event.id}):
		return
	frappe.get_doc({"doctype": "My Job", "event_id": event.id, "sales_order": event.reference_name}).insert()

The first part of the dotted path must be your app's name. Commera uses it to find the plugin that owns the handler.

The CommeraEvent object

commera.sdk.events.CommeraEvent is a frozen dataclass.

Field Type Value
id str A stable ID. It is the same on each retry and on each repeat delivery
name str The event name, for example order_paid
reference_doctype str Sales Order for order events, Item for product and stock events
reference_name str The name of the reference document
data dict The event data, see below. {} when there is no data
created_at datetime When Commera recorded the event

The id of an order event is <order>-<event>, for example SAL-ORD-2026-00010-order_placed. An order event that can occur more than one time adds a key: <order>-<event>-<key>. A product or stock event is <event>-<key>. The item code is not in the id, so use event.reference_name.

Order events

Commera fires order events only for store orders. A store order is a Sales Order with Order Type set to Shopping Cart (commera.sdk.STORE_ORDER_TYPE). An order that staff make in Desk is not a store order.

Event When it fires How often
order_placed The shopper places the order. A cash on delivery (COD) order is still a draft Sales Order Once
order_paid Gateway orders: right after order_placed. COD orders: when the order is fully billed and every invoice is paid Once
order_cancelled The Sales Order is cancelled, from the storefront, the dashboard or Desk Once
order_fulfilled The order status changes to Shipped, Delivered, Partially Returned or Returned, whichever comes first Once
order_delivered The order status changes to Delivered Once
order_returned The order status changes to Partially Returned or Returned Once per status
order_refunded A refund Payment Entry for the order is submitted Once per Payment Entry

Order data

Every order event carries a snapshot of the order, taken when the event fires.

Key Value
customer The Customer name
currency The order currency
grand_total The order grand total
payment_mode The checkout payment mode, for example COD
docstatus 0 draft, 1 submitted, 2 cancelled, when the event fired
shipping_address The address the order ships to: its shipping address, else its billing address. None when it has neither

shipping_address is a dict with the Address name and address_title, address_line1, address_line2, city, state, pincode, country and phone. get_order returns the same dict.

order_refunded adds payment_entry (the refund Payment Entry, also the key in event.id) and amount (the part of this refund that goes to this order, in the order currency, with tax and shipping).

order_returned adds status (Partially Returned or Returned) and partial (True for Partially Returned).

The snapshot can be old when your handler runs. For current values, call get_order.

When fulfilment events fire

Commera sets the order status from the order's Delivery Notes and Shipping Requests.

  • A shipment status of Pickup Scheduled, In Transit, Out For Delivery, Undelivered or Lost sets Shipped. Commera fires order_fulfilled.
  • A shipment status of Delivered sets Delivered. Commera fires order_fulfilled, then order_delivered.
  • With no Shipping Request, a submitted Delivery Note sets Delivered.
  • A drop-ship line (Supplier delivers to Customer) counts as delivered when its Purchase Order is received. An order with both kinds of lines moves only as far as its slower part.
  • A return Delivery Note for part of the delivered quantity sets Partially Returned. For all of it, Returned. Commera fires order_returned.
  • A shipment status of RTO sets Returned, and order_returned has partial set to False.

To move an order to Shipped from your plugin, call record_shipment.

When order_refunded fires

Commera fires order_refunded for each submitted Payment Entry of type Pay that it can link to a store order: a refund from the dashboard, the refund that a cancel pays out, or a Payment Entry that references the order, one of its invoices or its credit note. When one Payment Entry refunds more than one order, each order gets its own event.

Product and stock events

These events fire only for items that are on the storefront.

Event When it fires event.data
product_updated A product changes. One event per product for each transaction item_code (the template Item), changed (a sorted list)
inventory_changed Stock changes in the store warehouse (Commera Settings > Ecommerce Warehouse) warehouse, actual_qty, available_qty

changed holds one or more of these values:

Value What changed
details The product Item or one of its size Items was saved
options An option was saved without a publish change, or sizes were added or removed
price A selling Item Price of the product or a size was added, changed or deleted
published An option was published or unpublished

A new product fires nothing until you publish it. changed tells you what to read again, not the new values.

Commera records these events only when at least one plugin handles them.

Delivery rules

  • After commit. Commera queues the delivery after the transaction commits. If the action rolls back, the event does not exist.
  • Background job. Each delivery runs on the default queue. Do not use frappe.local.request, a shopper session or a cart cookie.
  • User. The handler runs as commera-plugins@commera.local. This user has every desk role, so permission checks pass. Documents that your handler makes show this user as the owner.
  • Lanes. Deliveries in one lane run one at a time, oldest first. For order events, each plugin has one lane per order: your order_placed handler finishes before your order_paid handler starts. For item events, each plugin has one lane per item and event. Plugins never share a lane.
  • At least once. Commera never fires the same event.id twice, but it can deliver it twice. A worker can stop after your handler commits and before Commera marks the delivery done.
  • Commits. Commera commits after each handler that succeeds. Writes that you commit stay, even if the handler raises later. Commera rolls back the rest.

Retries

When a handler raises, Commera rolls back the uncommitted writes, writes an Error Log with the title commera_events["<event>"] hook failed: <handler>, and tries again later. The delays are 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours. After the sixth failed attempt, the delivery is Failed.

A scheduled job starts the deliveries that are due, on each scheduler tick. The tick is 4 minutes by default, so a retry runs up to one tick after its delay. Make sure that the scheduler is enabled on the site, or retries do not run. A delivery that stays Running for more than 30 minutes counts as a failed attempt.

While a delivery waits for a retry, the later deliveries in its lane wait too. When it is Failed, they run.

See deliveries

  • Settings > Plugins, then Open on your plugin: the Recent deliveries list shows each delivery with its event, order, status and time. The statuses are Queued, Sending, Retrying, Sent and Failed. Only a System Manager sees this list.
  • On the order page in /commera, a red alert says that your plugin couldn't process the order when one of its deliveries for that order is Failed.
  • In Desk, the Commera Event record of the event lists its deliveries with the status Queued, Running, Done or Failed.

A System Manager sees a Retry button on a Failed delivery, in the list and on the order page alert.

Retention

Commera keeps order events, because their rows stop an order event from firing twice. Log Settings deletes product_updated and inventory_changed events after 14 days, unless a delivery of the event is still waiting.

Next steps

Last updated 3 days ago
Was this helpful?
Thanks!